python - 使用 BS4 将 HTML 表抓取为 CSV 以与 Pandas 一起使用

标签 python pandas csv web-scraping beautifulsoup

我已经开始了一个宠物项目,创建一个本质上是大量 NFL 统计数据的索引汇编,并带有一个漂亮的简单 GUI。还好网站https://www.pro-football-reference.com以表格形式提供您能想象到的所有数据,这些数据可以在网站上导出为 CSV 格式并手动复制/粘贴。我开始这样做,然后使用 Pandas 库,开始将 CSV 读入 DataFrame 中以利用数据。

这很有效,但是,手动获取所有这些数据非常繁琐,因此我决定尝试创建一个网络抓取工具,可以抓取 HTML 表格并将其转换为可用的 CSV 格式。我正在努力,特别是隔离各个表,而且还以可读/可用的格式呈现生成的 CSV。

这是刮刀现在的样子:

from bs4 import BeautifulSoup
import requests
import csv

def table_Scrape():
    url = 'https://www.pro-football-reference.com/teams/nwe/2008.htm'
    req = requests.get(url)
    soup = BeautifulSoup(req.text, 'html.parser')
    table = soup.select_one('table.stats_table')
    headers = [th.text.encode("utf-8") for th in table.select("tr th")]
    with open("out.csv", "w", encoding='utf-8') as f:
        wr = csv.writer(f)
        wr.writerow(headers)
        wr.writerows([
            [td.text.encode("utf-8") for td in row.find_all("td")]
            for row in table.select("tr + tr")
        ])    
table_Scrape()

这确实将请求正确发送到 URL,但没有获取我正在查找的数据“Rushing_and_Receiving”。相反,它会获取“团队统计和排名”页面上的第一个表格。它还以相当丑陋/无用的格式呈现 CSV,如下所示:

b'',b'',b'',b'Tot Yds & TO',b'',b'',b'Passing',b'Rushing',b'Penalties',b'',b'Average Drive',b'Player',b'PF',b'Yds',b'Ply',b'Y/P',b'TO',b'FL',b'1stD',b'Cmp',b'Att',b'Yds',b'TD',b'Int',b'NY/A',b'1stD',b'Att',b'Yds',b'TD',b'Y/A',b'1stD',b'Pen',b'Yds',b'1stPy',b'#Dr',b'Sc%',b'TO%',b'Start',b'Time',b'Plays',b'Yds',b'Pts',b'Team Stats',b'Opp. Stats',b'Lg Rank Offense',b'Lg Rank Defense'

b'309',b'4944',b'920',b'5.4',b'22',b'8',b'268',b'288',b'474',b'3222',b'27',b'14',b'6.4',b'176',b'415',b'1722',b'8',b'4.1',b'78',b'81',b'636',b'14',b'170',b'30.6',b'12.9',b'Own 27.8',b'2:38',b'5.5',b'29.1',b'1.74'
b'8',b'5',b'',b'',b'8',b'13',b'1',b'',b'12',b'12',b'13',b'5',b'13',b'',b'4',b'6',b'4',b'7',b'',b'',b'',b'',b'',b'1',b'21',b'2',b'3',b'2',b'5',b'4'
b'8',b'10',b'',b'',b'20',b'20',b'7',b'',b'7',b'11',b'31',b'15',b'21',b'',b'11',b'15',b'4',b'15',b'',b'',b'',b'',b'',b'24',b'16',b'5',b'13',b'14',b'15',b'11'

我知道获取正确表格的问题在于以下行:

table = soup.select_one('table.stats_table')

我仍然认为是 Python 新手,因此如果有人可以帮助我能够使用 BS4 查询并将特定表解析为 CSV 格式,我将不胜感激!

提前致谢!

最佳答案

由于 ajax 加载,pandas 解决方案对我不起作用,但您可以在控制台中看到每个表加载的 URL,并直接请求它。在本例中,URL 为:https://widgets.sports-reference.com/wg.fcgi?css=1&site=pfr&url=%2Fteams%2Fnwe%2F2008.htm&div=div_rushing_and_receiving

然后您可以使用其 id rushing_and_receiving 直接获取该表。

这似乎有效。

from bs4 import BeautifulSoup
import requests
import csv

def table_Scrape():
    url = 'https://widgets.sports-reference.com/wg.fcgi?css=1&site=pfr&url=%2Fteams%2Fnwe%2F2008.htm&div=div_rushing_and_receiving'
    req = requests.get(url)
    soup = BeautifulSoup(req.text, 'html.parser')
    table = soup.find('table', id='rushing_and_receiving')
    headers = [th.text for th in table.findAll("tr")[1]]
    body = table.find('tbody')
    with open("out.csv", "w", encoding='utf-8') as f:
        wr = csv.writer(f)
        wr.writerow(headers)
        for data_row in body.findAll("tr"):
            th = data_row.find('th')
            wr.writerow([th.text] + [td.text for td in data_row.findAll("td")])

table_Scrape()

关于python - 使用 BS4 将 HTML 表抓取为 CSV 以与 Pandas 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54452121/

相关文章:

ios - 如何将 CSV 数据解析为 App UI 的 XCode

python - 将包含值列表的字典转换为数据框

python - 如何让 Eclipse 在键入时向我显示方法的签名?

python - 用 1 和 0 填充 DataFrame

python - 属性错误: 'DataFrame' object has no attribute 'ravel'

python - 合并带有时间戳的 csv 文件

python - 在python中检测粘贴

python - 向量化 np.random.binomial 以接受多维数组

python - 使用列表中的索引值从大型数据帧创建较小的数据帧

java - 如何使用 Java 将 CSV 的空单元格替换为 NULL 文本