首页 > 解决方案 > 无法使用 BeautifulSoup find_all 或 Pandas.read_html 函数从表中抓取数据

问题描述

背景

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

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 的表。

标签: pythonpython-3.xpandasweb-scrapingbeautifulsoup

解决方案


无需使用硒。这些表格可以在 html 的注释中找到。只要把它们拉出来,你就可以抓住所有的表格标签。该特定表是第二个表(在索引位置 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)

推荐阅读