【问题标题】:Scraping HTML tables to CSV's using BS4 for use with Pandas使用 BS4 将 HTML 表抓取到 CSV 以与 Pandas 一起使用
【发布时间】:2019-06-24 09:57:05
【问题描述】:

我已经开始了一个宠物项目,该项目基本上是一个带有漂亮简单 GUI 的大量 NFL 统计数据的索引编译。幸运的是,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 格式,我将不胜感激!

提前致谢!

【问题讨论】:

    标签: python pandas csv web-scraping beautifulsoup


    【解决方案1】:

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

    感谢所有回复的人!

    【讨论】:

      【解决方案2】:

      由于 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()
      

      【讨论】:

      • 哈哈哈我发誓我尝试过传递soup.find那些相同的参数('table',id='rushing_and_receiving')并得到一个意外的关键字错误或类似的东西。非常感谢所有反馈的家伙!
      • 啊,我明白你的意思了,它只是抢了几张桌子。我将更多地使用这两种解决方案,看看我想出了什么,并会在必要时在这里更新。
      【解决方案3】:

      我会完全绕过漂亮的汤,因为 pandas 很适合这个网站。 (至少我掩饰的前 4 个表) 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')
      

      【讨论】:

      • 感谢您的回复!这就是我为了掩饰文档而得到的,当然有一个'read_html'方法哈哈。我会检查一下并报告!
      • 这很好用,我觉得自己像个傻瓜一样错过了这个并摆弄了 BeautifulSoup 这么久。至少我得到了一些数据科学/html 解析 101 的内容。谢谢一百万!
      • 这个网站看起来像是使用 JS 来呈现一些表格 - 如果需要类似的东西,请查看 requests_html
      • 由于上面提到的 ajax 问题,我不确定这是否有效。幸运的是,ajax 端点提供了可以用 bs4 解析的有效 HTML。
      • 我尝试了 pandas 中的 'read_html' 和 to_csv 方法,并且能够在表格出现在页面上时将表格按顺序解析为 csv,尽管我只尝试了一些。当我真正实现它并开始编译所有数据时,我会报告我遇到的任何问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-06
      • 1970-01-01
      • 2021-10-04
      • 2017-03-21
      • 2013-12-04
      • 2021-07-08
      相关资源
      最近更新 更多