如何使用BeautifulSoup中的Python将单行中多列分隔的数据导出为.csv或.xls?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用BeautifulSoup中的Python将单行中多列分隔的数据导出为.csv或.xls?相关的知识,希望对你有一定的参考价值。

我目前将这些数据存储为result变量。

['Draw Date:']
['Draw Date:']
['']
['']
['']
['Draw Date:  2019-01-15']
['']
['Perdana Lottery']
[]
['F', '2771', 'M', '0133', 'A', '6215']
[]
['A', '----', 'B', '1859', 'C', '3006', 'D', '3327']
['E', '5699', 'F', '----', 'G', '1123', 'H', '9193']
['I', '9076', 'J', '0573', 'K', '0950', 'L', '7258']
['', 'M', '-----', '', '', '']
['N', '1226', 'O', '0565', 'P', '1563', 'Q', '1420']
['R', '5265', 'S', '9345', 'T', '0483', 'U', '0933']
['', 'V', '6468', 'W', '3247', '']
['']
['']
['']
['']

我想将此数据导出为.csv或.xls格式的表格,如下所示:

+------------+----------+----------+----------+----------+-------------+
| Date       | First    | Second   | Third    | Special  | Consolation |
+------------+---+------+---+------+---+------+---+------+---+---------+
| 2019-01-15 | F | 2771 | M | 0133 | A | 6215 | A | ---- | N | 1226    |
|            |   |      |   |      |   |      | B | 1859 | O | 0565    |
|            |   |      |   |      |   |      | C | 3006 | P | 1563    |
|            |   |      |   |      |   |      | ... etc  | ... etc     |
+------------+---+------+---+------+---+------+----------+-------------+

......等表示来自上述结果变量的剩余数据。我没有在这里写出来以避免混乱。

那么,我应该使用哪些模块以及如何操作?请注意,我是一个完整的Python新手。我只知道一些PHP的东西,但说实话,我开始喜欢py。

答案

第一个问题是您需要知道奖品之间的分割位置。没有看到Special Prize文本,这将是困难的。另一种方法是使用find_all()来发现tdth元素。列表理解另外仅添加非空单元格。这将生成包含您需要的所有数据的单个列表。

cols包含所需列的列表。手动填写第1,第2和第3奖项,因为这些条目应该是固定的。然后使用循环将相应的字母和奖品添加到最后四列。

Python groupby()函数可用于将列表分组为由split_on中的元素分隔的子组。

from itertools import groupby, zip_longest, islice
from bs4 import BeautifulSoup
import requests
import csv


def grouper(iterable, n):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return zip(*args)


response = requests.get("http://perdana4d.com/resulten.php")
soup = BeautifulSoup(response.content, 'lxml') 
rows = [cell.get_text(strip=True) for cell in soup.find_all(['td', 'th']) if len(cell.get_text(strip=True))]
draw_date = rows[2].split(' ')[-1]
split_on = ['Special Prize', 'Consolation Prize']

cols = [
    ['Date', draw_date], 
    ['FirstL', rows[7]], 
    ['FirstP', rows[8]], 
    ['SecondL', rows[9]], 
    ['SecondP', rows[10]], 
    ['ThirdL', rows[11]], 
    ['ThirdP', rows[12]], 
    ['SpecialL'], 
    ['SpecialP'], 
    ['ConsolationL'], 
    ['ConsolationP']
    ]

col_l = islice(cols, 7, None, 2)
col_p = islice(cols, 8, None, 2)

for k, g in groupby(rows[13:], lambda x: x not in split_on):
    if k:
        l = next(col_l)
        p = next(col_p)

        for letter, prize in grouper(g, 2):
            l.append(letter)
            p.append(prize)

with open('output.csv', 'w', newline='') as f_output:
    csv.writer(f_output).writerows(zip_longest(*cols, fillvalue=''))

这将导致CSV文件在加载到电子表格包时具有以下类型的格式:

CSV format

这里使用了很多Python技术,需要一段时间才能理解。例如,grouperitertools recipes之一。 islice()是一种迭代对象而不需要从第一个位置开始的方法。

CSV文件的最终输出是使用Python的CSV库完成的。这会将行列表转换为格式正确的输出行。由于数据采用列格式,因此需要一个技巧将列表转换为行列表,这是使用zip_longest()完成的。

如果将print语句添加到代码中以查看数据的样子,这可能会有所帮助。

注意,要将数据直接保存为Excel格式(.xlsx),您需要安装另一个库,例如,您可以使用openpyxlxlwt

以上是关于如何使用BeautifulSoup中的Python将单行中多列分隔的数据导出为.csv或.xls?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 python 中使用 beautifulsoup4 来抓取标签中的内容

如何在python中忽略BeautifulSoup解析器中的换行符

如何使用Python BeautifulSoup刮取ID

如何在 Python 中使用 BeautifulSoup 保存对 HTML 文件所做的更改?

[Python]BeautifulSoup安装与使用

如何从 BeautifulSoup ( Python ) 中的表中获取第一个子表行