【问题标题】:Python BS4 Beautiful Soup HTML.Parser not working on a websitePython BS4 Beautiful Soup HTML.Parser 在网站上不起作用
【发布时间】:2019-11-22 12:48:44
【问题描述】:

我有 python 3.7 代码来尝试从以下网站 (https://www.whoscored.com/Matches/1294545/LiveStatistics/Germany-Bundesliga-2018-2019-Bayern-Munich-Hoffenheim) 提取足球统计数据。看来我与 BS4 Beautiful soup 一起使用的 HTML 解析器根本没有提取网站内的任何标签。

我首先尝试提取特定标签,例如代表主队和客队的两个不同 div 标签以及包含球员姓名的标签。当它呈现一个提取标签的空列表时,我只是尝试提取该网站上的所有 div 标签,但仍然得到一个空列表。

这是我使用的代码:

from requests import get
from bs4 import BeautifulSoup

url = 'https://www.whoscored.com/Matches/1294545/LiveStatistics/Germany- 
Bundesliga-2018-2019-Bayern-Munich-Hoffenheim'

response = get(url)
html_soup = BeautifulSoup(response.text, 'html.parser')
containers_home_offensive = html_soup.find_all('div')

【问题讨论】:

  • 该网站最有可能使用 JavaScript 通过 AJAX 加载统计信息,它不在 HTML 源代码中。
  • 您应该调用网页使用的相同 API,而不是尝试抓取 HTML。只有在没有 API 的时候才需要刮。

标签: python beautifulsoup


【解决方案1】:

在这种情况下,Request 不是解析数据的最佳工具,因为该网站使用 JavaScript,所以最好使用 Selenium 和 Web 驱动程序。 我试了一下,我可以在 2 个不同的列表中解析两支球队的球员姓名。

from selenium import webdriver
from bs4 import BeautifulSoup
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
import time

# Open web page
driver = webdriver.Firefox(executable_path='YOUR PATH') #You have to put the path of your WebDriver
driver.get('https://www.whoscored.com/Matches/1294545/LiveStatistics/Germany-Bundesliga-2018-2019-Bayern-Munich-Hoffenheim')

# Accept
element=WebDriverWait(driver,20).until(ec.element_to_be_clickable((By.XPATH,"/html/body/div[1]/div/div/div[2]/button")))
driver.execute_script("arguments[0].click();", element)
time.sleep(3)

# Scrolling down the page
results = driver.find_element_by_css_selector("#statistics-table-home-summary > table:nth-child(1)")
driver.execute_script("arguments[0].scrollIntoView();", results)
time.sleep(7)

# Make soup
source = driver.page_source
soup = BeautifulSoup(source, 'lxml')

table_home = soup.find_all('table', {"id": "top-player-stats-summary-grid"})[0]
players_home = [a.text for a in table_home.find_all('a')]
print(players_home)

table_away = soup.find_all('table', {"id": "top-player-stats-summary-grid"})[1]
players_away = [a.text for a in table_away.find_all('a')]
print(players_away)

driver.quit()

【讨论】:

    【解决方案2】:

    当您可以直接从 HTML 中提取匹配统计信息时,您不必使用 Selenium:

    import re
    from ast import literal_eval
    
    url = 'https://www.whoscored.com/Matches/1294545/LiveStatistics/Germany-Bundesliga-2018-2019-Bayern-Munich-Hoffenheim'
    res = requests.get(
        url,
        headers={
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0',
        }
    )
    res.raise_for_status()
    html = res.text
    

    到目前为止没有什么特别的。

    match_data = re.search('var matchStats = ([^;]+)', html, flags=re.MULTILINE).group(1)
    match_data_clean = re.sub(',,', ",'',", match_data_clean)
    
    stats = literal_eval(match_data_clean)
    

    当我们检查match_data 时,我们可以看到一堆语法无效的数组,如下所示:

    ams',,'yellow',,,21,328
    

    所以我们通过在逗号之间插入空字符串来使用re 魔术来清除它。

    打印stats 给我们:

    [[[37,
       1211,
       'Bayern Munich',
       'Hoffenheim',
       '24/08/2018 19:30:00',
       '24/08/2018 00:00:00',
       6,
       'FT',
       '1 : 0',
       '3 : 1',
       '',
       '',
       '3 : 1',
       'Germany',
       'Germany'],
      [[[21, [], [['Kasim Adams', '', 'yellow', '', '', 21, 328428, 0]], 0, 1],
        [23,
         [['Thomas Müller',
           'Joshua Kimmich',
           'goal',
           '(1-0)',
           '',
           23,
           37099,
           283323]],
         [],
         1,
         0],
    

    从这里开始,它只是找到与您正在寻找的数据相对应的正确索引。

    【讨论】:

    • 几分钟前我才注意到,由于某种原因,即使您建议的代码正在运行,我也无法抓取所有 4 个列表项/列下的所有状态(“摘要”,“进攻”、“传球”、“防守”)。我尝试将 href 链接作为 URL 链接复制并粘贴到这些列,但我仍然继续抓取相同的数据(仅限“摘要”)。我还打印并搜索了变量 html,但在其他三个列下找不到特定数据。知道我如何能够访问这些吗?
    猜你喜欢
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多