使用Scrapy发送无登录POST请求提交表单并获取结果的代码问题
问题描述
尝试使用Scrapy向表单页面http://www.umdata.org/SearchChurches.aspx发送POST请求,目标是:
- 填写并提交指定表单字段;
- 通过自定义的
parse_after_search函数获取结果表格中的数据。
但运行代码后,response.xpath返回空列表,无法得到预期的字符串结果。
运行代码
import scrapy from scrapy.http import FormRequest class QuotesSpider(scrapy.Spider): name = 'greatriver' login_url = 'http://www.umdata.org/SearchChurches.aspx' start_urls = [login_url] def parse(self, response): login_url = 'http://www.umdata.org/SearchChurches.aspx' return FormRequest.from_response( response, url=login_url, clickdata={'name': 'ctl00$ContentPlaceHolder1$btnSearch'}, formdata = {'ctl00$ContentPlaceHolder1$ddlState': 'AK'}, callback = self.parse_after_search, ) def parse_after_search (self, response): print (response.xpath('//*[@id="ContentPlaceHolder1_gvResults"]/tbody/tr[3]/td[1]/a'))
运行结果
2023-04-20 20:00:04 [scrapy.core.engine] INFO: Spider opened 2023-04-20 20:00:04 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2023-04-20 20:00:04 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6024 2023-04-20 20:00:05 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://www.umdata.org/SearchChurches.aspx> (referer: None) 2023-04-20 20:00:06 [scrapy.core.engine] DEBUG: Crawled (200) <POST http://www.umdata.org/SearchChurches.aspx> (referer: http://www.umdata.org/SearchChurches.aspx) [] 2023-04-20 20:00:06 [scrapy.core.engine] INFO: Closing spider (finished) 2023-04-20 20:00:06 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
问题分析与解决方案
1. XPath表达式错误
- 代码中XPath使用了转义的
",需替换为实际的引号(单引号或双引号); - 浏览器自动生成的
<tbody>标签在原始HTML中可能不存在,需移除XPath中的/tbody路径; - 要获取字符串内容,需在XPath末尾添加
/text()(获取文本)或/@href(获取链接),否则只会返回节点对象列表。
2. ASP.NET表单必要参数处理
ASP.NET页面提交表单时,需要携带__VIEWSTATE、__VIEWSTATEGENERATOR、__EVENTVALIDATION等隐藏字段,FormRequest.from_response会自动从页面中提取这些字段,无需手动添加,只需确保没有覆盖默认行为。
修正后的代码
import scrapy from scrapy.http import FormRequest class QuotesSpider(scrapy.Spider): name = 'greatriver' login_url = 'http://www.umdata.org/SearchChurches.aspx' start_urls = [login_url] def parse(self, response): # 利用from_response自动提取表单隐藏字段,仅覆盖需要修改的字段 return FormRequest.from_response( response, clickdata={'name': 'ctl00$ContentPlaceHolder1$btnSearch'}, formdata={'ctl00$ContentPlaceHolder1$ddlState': 'AK'}, callback=self.parse_after_search, ) def parse_after_search(self, response): # 修正XPath:移除tbody,使用正确引号,添加/text()获取文本内容 church_names = response.xpath('//*[@id="ContentPlaceHolder1_gvResults"]/tr[position()>2]/td[1]/a/text()').getall() print(church_names)
说明
- 移除了重复的
url参数,FormRequest.from_response默认使用当前response的URL; - XPath中用
position()>2跳过表格的表头行(前两行),批量获取所有结果行的教堂名称; - 使用
getall()获取所有匹配的文本内容,返回字符串列表。
内容的提问来源于stack exchange,提问作者Jonathan Gottlieb
相关产品推荐
相关产品推荐

