使用BeautifulSoup解析网站

3

我正在尝试学习使用Python解析HTML,目前遇到了困难——soup.findAll返回了一个空数组,因此有些元素无法被找到。以下是我的代码:

import requests
import urllib.request
import time
from bs4 import BeautifulSoup
headers = {"User-Agent":'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36'}
url = 'https://www.oddsportal.com/matches/tennis/20191114/'

responce = requests.get(url,headers=headers)

soup = BeautifulSoup(responce.text, 'html.parser')

info = soup.findAll('tr', {'class':'odd deactivate'})

print(info)

非常感谢您提供的任何帮助,先行致谢。


它们可以动态添加。你检查了response里面有什么了吗? - BlueSheepToken
3
我在页面上没有看到任何一个“奇怪的取消激活”tr,根本就没有“取消激活”。 - azro
2
你应该包含一个最小的response.text示例来完成你的[mcve]。 - wwii
有很多,https://imgur.com/qsZ9lw2 @BlueSheepToken,我刚刚检查了一下,似乎响应中没有这样的标签,这是否意味着它们是动态添加的,我无法访问它们? - noob
1
似乎在“响应”中不存在“奇怪的停用”。 - jkazan
2个回答

2
我正在尝试学习如何使用Python解析HTML。你选择的网页对于网络爬虫来说并不是很友好。一般来说,大多数网页使用以下两种常见方法来加载/显示数据:
1. 用户向服务器发出请求(例如访问页面)。 服务器从数据库中获取必要的数据。服务器使用模板引擎生成HTML响应,并将响应返回给用户的浏览器进行渲染。 2. 用户向服务器发出请求。服务器返回一个HTML框架响应,该响应通过使用其他请求/使用API等动态地填充数据。
您选择的网页属于第二种类型。仅因为您可以在Chrome Dev Tools的“元素”选项卡中看到<tr>元素,并不意味着服务器向您发送了这些内容。通过查看Chrome Dev Tools的网络选项卡,您可以看到向这两个资源发出了请求: https://fb.oddsportal.com/ajax-next-games/2/0/1/20191114/yje3d.dat?=1574007087150 https://fb.oddsportal.com/ajax-next-games-odds/2/0/X0/20191114/1/yje3d.dat?=1574007087151 (查询字符串参数对您来说可能不同。访问这些URL也不会很有趣,除非您提供正确的有效载荷。)
第一个资源似乎是一个jQuery脚本,它发起一个请求,响应中包含HTML(这是您的表格)。它看起来像这样:

您可以看到,他们似乎为每个比赛分配了唯一的ID。在这种情况下,Giron Marcos vs. Holt Brandon的ID是ATM9GmXG
第二个资源类似。它也是一个jQuery脚本,似乎正在向他们的主API发出请求。这一次的响应是JSON格式的,这对于网页抓取来说总是理想的。以下是其中的部分内容(请注意相同的ID):


2
显然,该页面只有在浏览器中调用时才加载“odds”部分。因此,您可以使用SeleniumChrome驱动程序
请注意,您需要下载Chrome驱动程序并将其放置在您的.../python/目录中。确保选择匹配的驱动程序版本,即与您安装的Chrome浏览器版本相匹配的Chrome驱动程序版本。
from bs4 import BeautifulSoup 
from urllib.request import urlopen 
import requests, time, traceback, random, csv, codecs, re, os

# Webdriver
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()
options.add_argument('log-level=3')
browser = webdriver.Chrome(chrome_options=options)

url = 'https://www.oddsportal.com/matches/tennis/20191114/'
browser.get(url)
soup = BeautifulSoup(browser.page_source, "html.parser")
info = soup.findAll('tr', {'class':'odd deactivate'})
print(info) 

阅读错误信息:获取与您计算机上安装的Chrome浏览器版本匹配的Chrome驱动程序版本。在浏览器中检查Chrome版本,如下所示->帮助->关于Google Chrome。 - Peter

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