MarketBeat评级页面爬取问题:XHR请求与Selenium操作失效
解决方案:获取MarketBeat评级历史数据
一、高效接口调用方案(替代Selenium)
MarketBeat的页面基于ASP.NET WebForms,直接POST JSON参数无效,需模拟表单提交并携带页面隐藏验证字段,步骤如下:
获取初始页面的隐藏验证字段
首次GET请求页面,提取WebForms用于验证请求合法性的__VIEWSTATE、__VIEWSTATEGENERATOR、__EVENTVALIDATION参数。构造正确的表单Payload
Payload需包含日期参数、隐藏字段,并以application/x-www-form-urlencoded格式发送,同时加入触发筛选按钮的参数。
示例代码:
import requests from bs4 import BeautifulSoup import pandas as pd session = requests.Session() base_url = "https://www.marketbeat.com/ratings/" # 第一步:获取页面隐藏字段 response = session.get(base_url) soup = BeautifulSoup(response.text, "html.parser") viewstate = soup.find("input", {"id": "__VIEWSTATE"})["value"] viewstate_generator = soup.find("input", {"id": "__VIEWSTATEGENERATOR"})["value"] event_validation = soup.find("input", {"id": "__EVENTVALIDATION"})["value"] # 第二步:构造表单数据并发送请求 payload = { "__VIEWSTATE": viewstate, "__VIEWSTATEGENERATOR": viewstate_generator, "__EVENTVALIDATION": event_validation, "ctl00$cphPrimaryContent$txtStartDate": "01/01/2023", "ctl00$cphPrimaryContent$btnFilter": "Filter" } headers = { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36" } response = session.post(base_url, data=payload, headers=headers) # 解析表格数据 soup = BeautifulSoup(response.text, "html.parser") tables = pd.read_html(str(soup)) print(tables[0])
二、修复Selenium操作问题
若必须使用浏览器自动化,可通过以下方式避免页面重载导致的元素失效:
替换clear()方法
用Ctrl+A选中输入框现有内容再输入新日期,避免触发页面重载。使用显式等待
确保元素加载完成后再操作,避免动态加载导致的定位失败。
示例代码:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import pandas as pd driver = webdriver.Chrome() driver.get("https://www.marketbeat.com/ratings/") # 等待输入框加载完成 input_element = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "cphPrimaryContent_txtStartDate")) ) # 选中现有内容并替换 input_element.send_keys(Keys.CONTROL + "a") input_element.send_keys("01/01/2023") # 点击筛选按钮触发数据加载 filter_btn = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.ID, "cphPrimaryContent_btnFilter")) ) filter_btn.click() # 等待表格加载并提取数据 table = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, "table.table")) ) tables = pd.read_html(table.get_attribute("outerHTML")) print(tables[0]) driver.quit()
注意事项
- 接口调用时需模拟真实浏览器
User-Agent,避免被拦截。 - 隐藏验证字段每次请求可能变化,需每次先GET页面获取最新值。
- 若遇反爬机制,可调整请求频率或使用代理。
内容的提问来源于stack exchange,提问作者AmyTheGhostHunter
相关产品推荐
相关产品推荐

