需提交表单才可访问页面的网页抓取问题(返回404)
表单提交后访问目标页面仍返回404的爬虫问题
我需要抓取一个必须先在输入框提交内容并点击按钮才可访问的页面,直接访问该页面URL会显示404错误。该页面SSL证书无效,必须禁用验证。以下是我尝试的代码,但访问目标页面始终返回404:
import requests from bs4 import BeautifulSoup from IPython.display import HTML import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) fst_url = "https://extranet.agricultura.gov.br/sigsif_cons/!ap_estabelec_nacional_cons" # First URL scd_url = "https://extranet.agricultura.gov.br/sigsif_cons/!ap_estabelec_nacional_lista" # Second URL session = requests.Session() session.verify = False # Disable SSL verification response = session.get(fst_url) if response.status_code == 200: soup = BeautifulSoup(response.text, 'html.parser') form = soup.find('form') if form: form_data = { 'nm_razao_social': ' ', # Input that needs to be submited in the first page } session.post(fst_url, data=form_data) scd_response = session.get(scd_url) if scd_response.status_code == 200: scd_soup = BeautifulSoup(scd_response.text, 'html.parser') else: print('Failed to retrieve the second URL. Status Code:', scd_response.status_code) else: print('Form not found on the first page.') else: print('Access to the first URL failed.') if 'results_soup' in locals(): results_html = HTML(results_soup) results_html
问题原因与修复方案
1. 表单数据不完整
你只提交了nm_razao_social一个字段,但网页表单通常包含隐藏字段(如CSRF令牌、表单标识等),服务器会校验这些字段的合法性,缺少的话会拒绝请求,导致后续会话状态未正确更新,访问目标页面时返回404。
2. 提交地址与请求方式错误
- 表单的提交地址不一定是当前页面URL,需要以表单的
action属性为准; - 未检查POST请求的响应状态,无法确认表单是否提交成功。
3. 目标页面访问逻辑错误
部分网站提交表单后,结果页面不会通过直接GET预设URL访问,而是通过POST请求的重定向直接返回结果,或者需要携带会话中生成的特定参数。
修改后的代码
import requests from bs4 import BeautifulSoup from IPython.display import HTML import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) fst_url = "https://extranet.agricultura.gov.br/sigsif_cons/!ap_estabelec_nacional_cons" scd_url = "https://extranet.agricultura.gov.br/sigsif_cons/!ap_estabelec_nacional_lista" session = requests.Session() session.verify = False # 禁用SSL验证 # 1. 获取初始表单页面,提取所有表单字段 response = session.get(fst_url) if response.status_code != 200: print('无法访问初始页面') exit() soup = BeautifulSoup(response.text, 'html.parser') form = soup.find('form') if not form: print('页面中未找到表单') exit() # 提取表单中所有输入字段(包括隐藏项) form_data = {} for input_tag in form.find_all('input'): name = input_tag.get('name') if name: # 覆盖需要手动填写的字段值,其余保留默认 if name == 'nm_razao_social': form_data[name] = ' ' else: form_data[name] = input_tag.get('value', '') # 确定表单提交地址,优先使用form的action属性 submit_url = form.get('action', fst_url) # 处理相对路径,拼接完整URL if not submit_url.startswith('http'): submit_url = requests.compat.urljoin(fst_url, submit_url) # 2. 提交表单 post_response = session.post(submit_url, data=form_data) if post_response.status_code not in [200, 302]: print('表单提交失败,状态码:', post_response.status_code) exit() # 3. 尝试获取结果页面:先尝试GET目标URL,失败则直接使用POST响应内容 scd_response = session.get(scd_url) if scd_response.status_code == 200: scd_soup = BeautifulSoup(scd_response.text, 'html.parser') print('成功获取结果页面') else: # 有些网站提交表单后直接在POST响应中返回结果 scd_soup = BeautifulSoup(post_response.text, 'html.parser') print('改用POST响应内容,状态码:', post_response.status_code) # 后续结果展示(如果需要) if 'scd_soup' in locals(): results_html = HTML(scd_soup.prettify()) results_html
内容的提问来源于stack exchange,提问作者Kaio
相关产品推荐
相关产品推荐

