使用BS4将HTML表格爬到CSV以便与Pandas一起使用

时间:2019-01-31 01:34:06

标签: python pandas csv web-scraping beautifulsoup

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

这很好用,但是,手动获取所有这些数据非常繁琐,因此我决定尝试创建一个Web抓取器,该抓取器可以抓取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”。相反,它将获取“ Team Stats and Rank”页面上的第一张表。它还以一种非常丑陋/无用的格式呈现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格式,我将不胜感激!

谢谢!

3 个答案:

答案 0 :(得分:3)

由于ajax加载,pandas解决方案对我不起作用,但是您可以在控制台中看到每个表从其加载的URL,并直接向其请求。在这种情况下,URL为:BUILD_EXCLUSIVE_KERNEL

然后您可以使用其ID https://widgets.sports-reference.com/wg.fcgi?css=1&site=pfr&url=%2Fteams%2Fnwe%2F2008.htm&div=div_rushing_and_receiving直接获取该表。

这似乎可行。

rushing_and_receiving

答案 1 :(得分:1)

由于熊猫在该网站上的效果很好,因此我将完全绕开美丽的汤。 (至少我掩盖了前四张桌子) Documentation here

import pandas as pd

url = 'https://www.pro-football-reference.com/teams/nwe/2008.htm'
data = pd.read_html(url)
# data is now a list of dataframes (spreadsheets) one dataframe for each table in the page
data[0].to_csv('somefile.csv')

答案 2 :(得分:0)

我希望我可以认为这两个答案都是正确的,因为它们都很有用,但是,Beautiful,使用BeautifulSoup的第二个答案是更好的答案,因为它允许隔离特定的表,而方法的本质是网站的结构限制了Pandas中“ read_html”方法的有效性。

感谢所有回应!