使用requests爬取网页表格名称时,如何实现后续分页数据的持续提取?
站点分页爬取的实现方案
该站点为ASP.NET WebForm 回发驱动架构,所有分页操作无独立URL,完全依靠携带动态防伪字段的POST请求完成跳转,无法通过修改URL参数直接访问分页内容。
核心实现逻辑
- 所有请求必须携带从上个响应中提取的最新
__VIEWSTATE、__EVENTVALIDATION、__VIEWSTATEGENERATOR动态字段,这组字段是服务器校验请求合法性的核心标识,固定复用初始值会被拦截 - 分页请求不需要再携带提交搜索的
Start Search按钮参数,需通过专属的回发字段告知服务器本次操作为点击“下一页”按钮 - 循环终止条件:解析当前页HTML时,未检测到可点击的“下一页”元素,即代表到达最后一页,退出循环
完整修改后代码
import requests from bs4 import BeautifulSoup link = 'https://hsapps.azdhs.gov/ls/sod/SearchProv.aspx?type=DD' with requests.Session() as s: s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' # 初始GET请求,获取页面基础防伪字段 r = s.get(link) soup = BeautifulSoup(r.text, "lxml") # 构建首次提交搜索的payload current_payload = { 'ctl00$ContentPlaceHolder1$btnSubmit1': 'Start Search', '__VIEWSTATE': soup.select_one('#__VIEWSTATE')['value'], '__EVENTVALIDATION': soup.select_one('#__EVENTVALIDATION')['value'], '__VIEWSTATEGENERATOR': soup.select_one('#__VIEWSTATEGENERATOR')['value'] } all_facility_names = [] while True: # POST请求获取当前页内容 r = s.post(link, data=current_payload) soup = BeautifulSoup(r.text, "lxml") # 提取当前页所有机构名称 for item in soup.select("#ctl00_ContentPlaceHolder1_DgFacils tr:has(> td)"): facility_name = item.select("td")[1].text.strip() all_facility_names.append(facility_name) print(facility_name) # 检测是否存在可跳转的下一页链接 next_page_link = soup.select_one("a[href*='__doPostBack'][href*='Next']") if not next_page_link: break # 提取当前页最新的防伪字段,构建下一页请求的payload current_payload = { # 指向下一页按钮对应的服务器控件ID '__EVENTTARGET': 'ctl00$ContentPlaceHolder1$DgFacils$ctl00$ctl02$btnNext', '__EVENTARGUMENT': '', '__VIEWSTATE': soup.select_one('#__VIEWSTATE')['value'], '__EVENTVALIDATION': soup.select_one('#__EVENTVALIDATION')['value'], '__VIEWSTATEGENERATOR': soup.select_one('#__VIEWSTATEGENERATOR')['value'] } print(f"共提取到{len(all_facility_names)}条机构名称")
调试注意事项
- 若运行时出现服务器校验失败的情况,可在浏览器开发者工具的网络面板中,手动点击一次下一页操作,查看实际POST请求中
__EVENTTARGET的真实值,替换代码中对应控件ID即可 - 部分分页控件在最后一页会将下一页按钮设置为禁用状态,此时可额外判断元素的class属性,避免发送无效请求
__VIEWSTATE字段值可能包含特殊字符,requests库会自动完成URL编码,无需手动转义
内容的提问来源于stack exchange,提问作者MITHU
相关产品推荐
相关产品推荐

