[英]Scrapy FormRequest , trying to send a post request (FormRequest) with currency change formdata
[英]Scrapy - FormRequest sends GET request when the method is POST
这是我要抓取的页面
页面上的数据来自此URL
这是我的检索器的代码。 我至少检查了标头和formdata 5次。 我认为它们是正确的。 问题是,即使我重写了parse
方法的默认行为,也很难将GET
请求发送到start_url
。
class MySpider(CrawlSpider):
name = 'myspider'
start_urls = [
'https://277kmabdt6-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%20(lite)%203.27.1%3BJS%20Helper%202.26.0%3Bvue-instantsearch%201.7.0&x-algolia-application-id=277KMABDT6&x-algolia-api-key=bf8b92303c2418c9aed3c2f29f6cbdab',
]
formdata = {
'requests': [{'indexName': 'listings',
'params': 'query=&hitsPerPage=24&page=0&highlightPreTag=__ais-highlight__&highlightPostTag=__%2Fais-highlight__&filters=announce_type%3Aproperty-announces%20AND%20language_code%3Apt%20AND%20listing_id%3A%205&facets=%5B%22announce_type%22%5D&tagFilters='}]
}
headers = {
'accept': 'application/json',
'content-type': 'application/x-www-form-urlencoded',
'Origin': 'https://www.flat.com.br',
'Referer': 'https://www.flat.com.br/search?query=',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
}
def parse(self, response):
for url in self.start_urls:
yield scrapy.FormRequest(
url=url,
method='POST',
headers=self.headers,
formdata=self.formdata,
callback=self.parse_page,
)
def parse_page(self, response):
print json.loads(response.text)
这是我运行蜘蛛程序时收到的消息。
我的问题是; 为什么要向URL发送GET
请求,我会丢失吗? 是我的请求失败的其他原因吗?
2019-07-01 11:45:58 [scrapy] DEBUG: Crawled (400) <GET https://277kmabdt6-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%20(lite)%203.27.1%3BJS%20Helper%202.26.0%3Bvue-instantsearch%201.7.0&x-algolia-application-id=277KMABDT6&x-algolia-api-key=bf8b92303c2418c9aed3c2f29f6cbdab> (referer: None)
2019-07-01 11:45:58 [scrapy] DEBUG: Ignoring response <400 https://277kmabdt6-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%20(lite)%203.27.1%3BJS%20Helper%202.26.0%3Bvue-instantsearch%201.7.0&x-algolia-application-id=277KMABDT6&x-algolia-api-key=bf8b92303c2418c9aed3c2f29f6cbdab>: HTTP status code is not handled or not allowed
您需要将重命名parse
方法为start_requests
因为默认情况下Scrapy将GET
从每个URL self.start_urls
:
def start_requests(self):
for url in self.start_urls:
yield scrapy.FormRequest(
url=url,
method='POST',
headers=self.headers,
formdata=self.formdata,
callback=self.parse_page,
)
我认为只有当您的有效载荷为body=json.dumps(self.formdata)
而不是formdata=self.formdata
时,您才能获得有效的响应,因为它们是json格式。 建议部分应如下所示:
def start_requests(self):
for url in self.start_urls:
yield scrapy.FormRequest(
url=url,method='POST',
headers=self.headers,body=json.dumps(self.formdata),
callback=self.parse_page,
)
当您使用parse()
方法时,默认情况下该方法通过get
请求从start_urls
获取响应,但是在这种情况下,您在start_urls
使用的url永远不会通过parse()
方法,因为它将引发状态400错误或类似的错误。 因此,要像尝试方法一样使用parse()
方法,请确保在start_urls
使用的url
能够获得所需的状态。 也就是说,即使您使用状态为200的其他url
,然后使用right url
处理发布请求,也可以根据需要进行响应。
import json
import scrapy
class MySpider(scrapy.Spider):
name = 'myspider'
#different url
start_urls = ['https://stackoverflow.com/questions/tagged/web-scraping']
url = 'https://277kmabdt6-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia%20for%20vanilla%20JavaScript%20(lite)%203.27.1%3BJS%20Helper%202.26.0%3Bvue-instantsearch%201.7.0&x-algolia-application-id=277KMABDT6&x-algolia-api-key=bf8b92303c2418c9aed3c2f29f6cbdab'
formdata = {
'requests': [{'indexName': 'listings',
'params': 'query=&hitsPerPage=24&page=0&highlightPreTag=__ais-highlight__&highlightPostTag=__%2Fais-highlight__&filters=announce_type%3Aproperty-announces%20AND%20language_code%3Apt%20AND%20listing_id%3A%205&facets=%5B%22announce_type%22%5D&tagFilters='}]
}
headers = {
'accept': 'application/json',
'content-type': 'application/x-www-form-urlencoded',
'Origin': 'https://www.flat.com.br',
'Referer': 'https://www.flat.com.br/search?query=',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
}
def parse(self,response):
yield scrapy.Request(
url=self.url,method='POST',
headers=self.headers,body=json.dumps(self.formdata),
callback=self.parse_page,
)
def parse_page(self, response):
print(json.loads(response.text))
首先将解析方法重命名为:
def start_requests(self):
发送表单时,应改用scrapy.FormRequest。 如果您要发送的是原始正文,则只想使用method = post。 在这种情况下,它看起来像是正式数据,所以可以这样做。
formdata = {
'requests': [{'indexName': 'listings',
'params': 'query=&hitsPerPage=24&page=0&highlightPreTag=__ais-highlight__&highlightPostTag=__%2Fais-highlight__&filters=announce_type%3Aproperty-announces%20AND%20language_code%3Apt%20AND%20listing_id%3A%205&facets=%5B%22announce_type%22%5D&tagFilters='}]
}
headers = {
'accept': 'application/json',
'content-type': 'application/x-www-form-urlencoded',
'Origin': 'https://www.flat.com.br',
'Referer': 'https://www.flat.com.br/search?query=',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
}
def start_requests(self):
for link in self.start_urls:
yield scrapy.FormRequest(link, headers=headers, formdata=formdata, callback=self.parse_page)
您还可以使用其他工具(例如来自响应的表单请求)来帮助实现这一目的。 如果要发送原始json字符串或其他内容,则需要将字典转换为字符串,然后按照此处的操作将方法设置为POST。 FormRequest将自动发送POST请求,如果您使用from响应功能,它将很聪明。
参考: https : //docs.scrapy.org/en/latest/topics/request-response.html#request-subclasses
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.