繁体   English   中英

Scrapy-方法为POST时,FormRequest发送GET请求

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM