Selenium Geckodriver爬取香港赛马会网站出现ReferenceError错误求助
问题:爬取香港赛马会赔率的代码突然失效,提示
winOddsByRace未定义 我用于爬取香港赛马会网站赔率数据的代码,此前数月运行稳定从未崩溃:
wb = xw.Book("jockeyclub.xlsx") rc1 = wb.sheets['Race Card 1'] def scrape_odds(url, worksheet): # 指定geckodriver路径 gecko_driver_path = '/Users/nicholaschan/Desktop/hkjcwebscraping/geckodriver' # 创建GeckoDriver服务实例 gecko_service = Service(executable_path=gecko_driver_path) # 初始化Firefox浏览器 driver = webdriver.Firefox(service=gecko_service) # 访问目标页面 driver.get(url) # 等待页面加载 driver.implicitly_wait(10) # 通过JS变量获取赔率数据 win_odds_string = driver.execute_script('return winOddsByRace') # 打印并写入Excel print(win_odds_string) worksheet.range('A26').value = win_odds_string # 关闭浏览器 driver.quit() scrape_odds('https://bet.hkjc.com/racing/pages/odds_wp.aspx?lang=en&date=2024-01-14&venue=ST&raceno=1',rc1)
但今日运行时,虽然能正常打开Firefox并访问目标链接,却立即抛出以下错误:
File "/Users/nicholaschan/Desktop/hkjcwebscraping/scrapodds1.py", line 52, in <module> scrape_odds('https://bet.hkjc.com/racing/pages/odds_wp.aspx?lang=en&date=2024-01-14&venue=ST&raceno=1',rc1) File "/Users/nicholaschan/Desktop/hkjcwebscraping/scrapodds1.py", line 42, in scrape_odds win_odds_string = driver.execute_script('return winOddsByRace') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py", line 407, in execute_script return self.execute(command, {"script": script, "args": converted_args})["value"] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py", line 347, in execute self.error_handler.check_response(response) File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/selenium/webdriver/remote/errorhandler.py", line 229, in check_response raise exception_class(message, screen, stacktrace) selenium.common.exceptions.JavascriptException: Message: ReferenceError: winOddsByRace is not defined Stacktrace: @https://bet.hkjc.com/racing/pages/odds_wp.aspx?lang=en&date=2024-01-14&venue=ST&raceno=1:2:7 @https://bet.hkjc.com/racing/pages/odds_wp.aspx?lang=en&date=2024-01-14&venue=ST&raceno=1:3:8
我尝试修改代码的部分内容,但每次运行仍会报错。请问为何此前运行正常的代码突然失效?
原因分析与解决思路
核心原因
代码突然失效的大概率是以下几种情况:
- 网站前端逻辑更新:香港赛马会修改了页面的JavaScript结构,之前全局暴露的
winOddsByRace变量被移除、重命名或改为局部变量,导致你的代码无法获取该变量。这是网站迭代或反爬的常见操作。 - 等待机制不充分:你使用的
implicitly_wait(10)是隐式等待,仅能等待DOM元素加载完成,但无法确保所有JavaScript变量都初始化完成。现在页面可能需要更长时间生成该变量,或者需要触发交互才会出现。 - 反爬策略触发:网站可能检测到爬虫行为,限制了JavaScript变量的暴露,或者需要验证(如Cookie、用户代理)才能获取数据。
解决建议
- 验证变量状态:手动打开目标页面,按F12打开开发者工具,在Console标签输入
winOddsByRace,确认该变量是否真的不存在。如果不存在,搜索页面内的赔率相关关键词,寻找新的变量名(比如winOdds、raceOddsData等)。 - 优化等待逻辑:替换隐式等待为显式等待,等待目标JavaScript变量加载完成:
from selenium.webdriver.support.ui import WebDriverWait # 替换原有的driver.implicitly_wait(10) wait = WebDriverWait(driver, 20) # 等待winOddsByRace变量被定义 wait.until(lambda driver: driver.execute_script('return typeof winOddsByRace !== "undefined"'))
- 模拟用户行为:添加真实的用户代理(UA),保存并复用Cookie,或者在页面加载后模拟滚动、点击等操作,避免被反爬机制拦截。
- 更换数据获取方式:如果无法再通过JS变量获取数据,可以尝试直接解析页面HTML元素提取赔率;或者通过开发者工具的Network标签,找到加载赔率数据的API接口,直接调用接口获取数据(这种方式更稳定且效率更高)。
内容的提问来源于stack exchange,提问作者NNBananas
相关产品推荐
相关产品推荐

