【问题标题】:Unable to scrape data from tables using BeautifulSoup find_all or Pandas.read_html functions无法使用 BeautifulSoup find_all 或 Pandas.read_html 函数从表中抓取数据
【发布时间】:2021-02-23 00:42:50
【问题描述】:

背景

我正在编写代码以从以下网页中抓取文本

https://www.pro-football-reference.com/boxscores/201809060phi.htm.

该页面包含多个表格,我想从中提取特定数据。为了说明此处的示例,我希望从标有“游戏信息”的表中标有“屋顶”的行中提取数据。

尝试:

我尝试通过两种方式收集这些信息:使用 BeautifulSoup(在我的情况下还导入 MechanicalSoup,因为我有额外的代码可以在 for 循环中打开链接),以及使用 Pandas 模块。

熊猫尝试

import mechanicalsoup
from bs4 import BeautifulSoup
import pandas

root_url="https://www.pro-football-reference.com"

#Opens the main pro-football page with list of 2018 games
browser=mechanicalsoup.StatefulBrowser()
browser.open("https://www.pro-football-reference.com/years/2018/games.htm")
main_page = browser.get_current_page()
browser.close()
data=main_page.find_all("tr")

#Finds the link to box-score information for the first game.  
#Will iterate over all games in a for loop later on.
box_score_tag = data[1].find("td",{"data-stat":"boxscore_word"})
box_score_link = root_url+box_score_tag.a.get("href")

#Opens the box-score page for the first game
browser2=mechanicalsoup.StatefulBrowser()
browser2.open(box_score_link)
boxscorepage=browser2.get_current_page()
browser2.close()

#attempt to scrape all the tables using Pandas
tables = pandas.read_html(box_score_link)
print(len(tables))

显然还有更多表时,使用 Pandas 函数的输出是 3(即仅拉出 3 个表)。

BeautifulSoup Attempt(替换最后 3 行)

#attempt to scrape the specific table in question using BeautifulSoup
game_info = boxscorepage.find_all("table",{"id":"game_info"})
print(game_info)

这不输出任何内容 - 在此页面上,找到一些标签(div、spans 等)有效,但其他标签无效。在这种情况下,它没有按预期找到带有 game_info 的表。

【问题讨论】:

    标签: python python-3.x pandas web-scraping beautifulsoup


    【解决方案1】:

    missing 表是由JS 生成的,因此您最好使用selenium,然后将bs4pandas 放在上面。

    例如:

    import time
    
    import pandas as pd
    from bs4 import BeautifulSoup
    from selenium import webdriver
    from selenium.webdriver.chrome.options import Options
    
    options = Options()
    options.headless = True
    driver = webdriver.Chrome(options=options)
    
    driver.get("https://www.pro-football-reference.com/boxscores/201809060phi.htm")
    time.sleep(2)
    
    soup = BeautifulSoup(driver.page_source, "html.parser").find("div", {"id": "div_game_info"})
    
    df = pd.read_html(str(soup), skiprows=[0])
    df = pd.concat(df)
    df.to_csv("game_info.csv", index=False)
    

    这将为您提供.csv 文件中的表格。

    【讨论】:

      【解决方案2】:

      无需使用 Selenium。这些表可以在 html 的 cmets 中找到。只要把它们拉出来,你就可以抓住所有的表格标签。该特定表是第二个表(在索引位置 1)。

      代码:

      import requests
      from bs4 import BeautifulSoup
      from bs4 import Comment
      import pandas as pd
      
      
      url = 'https://www.pro-football-reference.com/boxscores/201809060phi.htm'
      response = requests.get(url)
      
      soup = BeautifulSoup(response.text, 'html.parser')
      comments = soup.find_all(string=lambda text: isinstance(text, Comment))
      
      tables = []
      for each in comments:
          if 'table' in each:
              try:
                  tables.append(pd.read_html(each)[0])
              except:
                  continue
              
      print (tables[1].loc[1:])
      

      输出:

      print (tables[1].loc[1:])
                  0                         1
      1    Won Toss         Eagles (deferred)
      2        Roof                  outdoors
      3     Surface                     grass
      4    Duration                      3:19
      5  Attendance                     69696
      6     Weather    81 degrees, wind 8 mph
      7  Vegas Line  Philadelphia Eagles -1.0
      8  Over/Under              44.5 (under)
      

      【讨论】:

        猜你喜欢
        • 2018-07-31
        • 2021-02-28
        • 2021-11-25
        • 2021-11-01
        • 2018-05-22
        • 1970-01-01
        • 1970-01-01
        • 2019-09-03
        • 1970-01-01
        相关资源
        最近更新 更多