Scrapy请求SEC EDGAR搜索页带#的URL被截断如何解决
问题核心原因
URL中#后的内容属于前端哈希路由参数,HTTP协议规定哈希部分不会被发送到服务端,所以Scrapy请求时会自动截断这部分,只请求https://www.sec.gov/edgar/search这个基础地址。而搜索结果是浏览器加载完基础页面后,JS读取哈希参数再发起后台请求渲染生成的,直接用普通Scrapy请求拿不到结果。
方案1:直接调用真实搜索API(效率最高,推荐)
你可以直接抓浏览器发起的后台搜索请求,跳过前端页面渲染步骤:
- 打开浏览器F12开发者工具,切换到「网络」面板,筛选「Fetch/XHR」,执行搜索后就能看到真实的搜索请求地址为
https://efts.sec.gov/LATEST/search-index - 请求方法为POST,请求体是JSON格式,对应你的搜索参数即可。
示例代码:
import scrapy import json class Sec(scrapy.Spider): name = 'sec' def start_requests(self): api_url = "https://efts.sec.gov/LATEST/search-index" # 对应你的搜索参数构造请求体 payload = { "q": "MSIGX", "dateRange": "1y", "category": "form-cat1", "startdt": "", # 也可以自定义起止日期 "enddt": "" } headers = { "Content-Type": "application/json", # 其他你之前的get_sec_header()里的请求头都可以加进来,比如User-Agent } yield scrapy.Request( url=api_url, method="POST", body=json.dumps(payload), headers=headers, callback=self.parse_result, meta={'s': row["symbol"]} ) def parse_result(self, response): # 直接解析返回的JSON数据即可拿到所有搜索结果 data = response.json() # 后续处理逻辑 print(data)
方案2:使用JS渲染工具加载页面
如果需要和页面交互或者不想逆向API,可以使用Scrapy对接Playwright等无头浏览器工具,等待JS渲染完成后再提取数据:
- 先安装依赖:
pip install scrapy-playwright,然后执行playwright install chromium - 在项目settings.py中添加配置:
DOWNLOADER_MIDDLEWARES = { "scrapy_playwright.middleware.PlaywrightMiddleware": 800, } PLAYWRIGHT_LAUNCH_OPTIONS = {"headless": True}
- 修改请求代码,启用Playwright渲染:
def start_requests(self): url = 'https://www.sec.gov/edgar/search/#/q=MSIGX&dateRange=1y&category=form-cat1' yield scrapy.Request( url=url, headers=get_sec_header(), callback=self.parse, meta={ 's':row["symbol"], 'playwright': True, # 启用Playwright渲染 'playwright_wait': 2000 # 等待2秒让页面加载完成 }, dont_filter=True ) def parse(self, response): # 此时response已经是渲染完成的页面,可以正常提取内容 print(response.xpath('//div[contains(@class,"search-result")]//text()').getall())
内容的提问来源于stack exchange,提问作者giulio di zio
相关产品推荐
相关产品推荐

