Python网络爬虫:Beautiful Soup

4

我在抓取网页时遇到了一个问题。我想要获取两支球队之间得分的差距(例如:+2,+1...),但是当我使用find_all方法时,它返回一个空列表...

from bs4 import BeautifulSoup
from requests import get
url='https://www.mismarcadores.com/partido/Q942gje8/#punto-a-punto;1'
response=get(url)
html_soup=BeautifulSoup(response.text,'html.parser')


html_soup.find_all('span',class_='match-history-diff-score-inc')

3
看起来你寻找的内容在使用beautifulsoup解析页面时没有加载出来。可能这些内容是动态加载的,而beautifulsoup无法获取。建议尝试使用Selenium查找此类问题。 - W Stokvis
Selenium 会使速度变慢,从浏览器中跟踪网络,找到特定的请求,然后您可以使用 requests + bs4 来解决问题。相信我,您的代码将快 5 倍。 - Sagun Shrestha
3个回答

8
你遇到的问题是网页内容通过JavaScript动态生成。因此,requests无法处理它,所以最好使用类似Selenium的工具。
编辑:根据@λuser的建议,我修改了我的答案,只使用XPath搜索您要查找的元素。请注意,我使用XPath函数starts-with()来获取match-history-diff-score-dec和match-history-diff-score-inc。仅选择其中之一会使您错过近一半的相对分数更新。这就是为什么输出结果显示103个而不是56个的原因。
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.mismarcadores.com/partido/Q942gje8/#punto-a-punto;1")

table = driver.find_elements_by_xpath('//td//span[starts-with(@class, "match-history-diff-score-")]')

results = []
for tag in table:
    print(tag.get_attribute('innerHTML'))
print(results)

这将输出:
['+2', '+1', '+2', '+2', '+1', '+2', '+4', '+2', '+2', '+4', '+7', '+5', '+8', '+5', '+7', '+5', '+3', '+2', '+5', '+3', '+5', '+3', '+5', '+6', '+4', '+6', '+7', '+6', '+5', '+2', '+4', '+2', '+5', '+7', '+6', '+8', '+5', '+3', '+1', '+2', '+1', '+4', '+7', '+5', '+8', '+6', '+9', '+11', '+10', '+9', '+11', '+9', '+10', '+11', '+9', '+7', '+5', '+3', '+2', '+1', '+3', '+1', '+3', '+2', '+1', '+3', '+2', '+4', '+1', '+2', '+3', '+6', '+3', '+5', '+2', '+1', '+1', '+2', '+4', '+3', '+2', '+4', '+1', '+3', '+5', '+7', '+5', '+8', '+7', '+6', '+5', '+4', '+1', '+4', '+6', '+9', '+7', '+9', '+7', '+10', '+11', '+12', '+10']

1
如果你正在使用Selenium,为什么还要用Beautifulsoup再次解析源代码呢?Selenium已经可以执行XPath查询并提取文本了。 - λuser
是的,你说得对。这有点多余。也许我会编辑我的回答,只使用Selenium提供一种解决方案。 - Mihai Chelaru

7

Selenium可能可以解决你的问题,但我建议你从浏览器中跟踪网络,并找到生成所需数据的请求。在你的情况下,它是d_mh_Q942gje8_es_1

我不喜欢Selenium,因为它太重了,会使你的脚本变慢。它是为自动化测试而构建的,而不是为了网页抓取。

以下是我的脚本,使用requests,无疑比Selenium运行得更快。

import requests
from bs4 import BeautifulSoup

url = 'https://d.mismarcadores.com/x/feed/d_mh_Q942gje8_es_1'

r = requests.get(url, headers={'x-fsign':'SW9D1eZo'}) # Got this from browser
soup = BeautifulSoup(r.text, 'html.parser')
diff_list = [diff.text for diff in soup.find_all('span',{'class' : 'match-history-diff-score-inc'})]
print(diff_list)

输出:

['+2', '+1', '+2', '+2', '+2', '+4', '+2', '+4', '+7', '+8', '+7', '+5', '+5', '+5', '+6', '+6', '+7', '+4', '+5', '+7', '+8', '+1', '+2', '+4', '+7', '+8', '+9', '+11', '+11', '+10', '+11', '+1', '+3', '+3', '+3', '+4', '+2', '+3', '+6', '+5', '+1', '+1', '+2', '+4', '+4', '+3', '+5', '+7', '+8', '+4', '+6', '+9', '+9', '+10', '+11', '+12']

2
如果您检查页面源代码(例如通过Chrome或Firefox的view-source:或将html字符串写入文件),您会发现您要查找的元素(搜索match-history-diff-score-inc)并不存在。 实际上,这些费率是使用JS动态加载的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接