首页 > 解决方案 > 在 Python 中使用 Selenium 抓取随时间变化的动态 URL

问题描述

我正在尝试抓取以下 URL:

https://www.oddsportal.com/soccer/england/premier-league/liverpool-norwich-4IMoMG3q/

使用 Chrome 开发者工具中的 Network 选项卡,您可以看到有一个 API 可以将数据馈送到网站中 - 它采用 JSON 的形式 - 如下所示。这些数据是我想要抓取的。

https://fb.oddsportal.com/feed/match/1-1-4IMoMG3q-5-2-yj1e3.dat?_=1562831112277

这是我目前正在尝试使用的代码:

from selenium.webdriver.chrome.options import Options
import json
import urllib.parse
from time import time

options = Options()
options.headless = True
driver = webdriver.Chrome(options=options)

# Access the initial webpage to create the info_dict (including the match_id, and hash)
driver.get('https://www.oddsportal.com/soccer/england/premier-league/liverpool-norwich-4IMoMG3q')
page = driver.page_source
info_dict = json.loads(page.split('var page = new PageEvent(')[-1].split(');')[0])
xhash = urllib.parse.unquote(info_dict['xhash'])
match_id = info_dict['id']

# Access to the feed URL based on the values from the info_dict
driver.get('http://fb.oddsportal.com/feed/match/1-1-{}-1-2-{}.dat?_={}'.format(match_id, xhash, int(round(time()*1000)) + 1000))
print(driver.page_source)

URL 由 3 个因素组成 - match_id、哈希和以毫秒为单位的纪元时间。但是,当我尝试在 Selenium 中访问它时,我得到以下响应:

globals.jsonpCallback('/feed/match/1-1-4IMoMG3q-1-2-yjb3a.dat?_=1562795864899', {'e':'404'});

真的很感激任何帮助,因为我真的不明白我哪里出错了!

标签: pythonpython-3.xseleniumweb-scraping

解决方案


我知道很久以前有人问过它,但它可能会在另一天对其他人有所帮助,谁知道呢。

正如在此处解释和解决的那样,您的 url 的最后一部分,在 dat?= 之后,是根据当前日期计算的,并在一段时间后变得无处不在。

如果您在拨打电话时生成它,您将获得数据。例如,如果您想要 2018-2019 赛季的法国 Ligue1 比赛,代码的原始版本可能是(您需要正确解析 page.text):

import requests
import datetime

def timestamp_date():
    return int(datetime.datetime.now().timestamp()*1000)

url ='https://fb.oddsportal.com/ajax-sport-country-tournament-archive/1/Gji6p9u4/X0/1/0/8/?_='+str(timestamp_date())
headers = {
'User-Agent': 'curl/7.64.0',
'Referer': 'https://www.oddsportal.com/soccer/france/ligue-1-2018-2019/results/',
 }
page = requests.get(url, headers=headers)
page.text

推荐阅读