【问题标题】:Scrapy, Xpath, no results?Scrapy,Xpath,没有结果?
【发布时间】:2020-07-11 15:00:36
【问题描述】:

我正在尝试抓取的网址:

https://www.controller.com/listings/aircraft/for-sale/list?SortOrder=23&scf=False&page=1

我是 Scrapy 和一般编程的新手,但在此之前我仍然能够抓取一些网站。

当我第一次尝试抓取上面的 URL 时,我一直遇到代码 403。经过一些研究,我能够通过下载用于 scrapy 的 user_agents 包绕过它。以下用户代理有效:

'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36'

我已经尝试了简单的 Xpath 代码,如下所示,只是为了确保我得到了输出。

    def parse(self, response):
        text = response.xpath("//div[@class='mobile-map-select']/text()").extract()
        print(text)

多次尝试不同的代码后,我仍然得到一个空列表作为输出。

有人知道为什么会这样吗?

【问题讨论】:

    标签: html python-3.x xpath web-scraping scrapy


    【解决方案1】:

    某些网站要求您发布标题和 cookie。这称为重新设计请求。有时要访问 HTML,您需要尝试模仿对服务器的确切请求,因此这意味着发布标头和 cookie。

    重新设计 HTTP 请求

    首先,您想使用 chrometools 之类的东西来查看请求。右键单击检查并单击网络选项卡,重新加载要查看请求的页面,网络选项卡下应该开始填充服务器发出的所有请求以加载页面。在这里,我们可以准确找到加载页面 HTML 所需的 HTTP 请求类型。

    图片1:Here

    这里我们可以在左侧看到站点 HTML 请求,在右侧我们有请求 URL 是我们想要制作的 URL

    图片2:Here

    在右侧,我们现在有请求标头和发送的 cookie。您创建一个带有键和值的字典标头。我们也可以对 cookie 做同样的事情。

    然后我们想要产生一个带有这些标头和这些 cookie 的 Scrapy 请求,这模仿了服务器期望的请求。

    重新设计 HTTP 请求的更简单方法

    您可以复制 HTTP 请求的 curl 命令,如下图所示。

    图片:here

    将其复制到here,一个将其转换为python请求的网站。这将为您提供格式良好的标题/cookie 等。然后您可以复制标题和 cookie 的字典。

    代码示例

    import scrapy
    
    class TestSpider(scrapy.Spider):
        name = 'test'
        allowed_domains = ['https://www.controller.com/listings/aircraft/for-\ 
                          sale/list?SortOrder=23&scf=False&page=1']
        start_urls = ['http://controller.com/']
    
    
    
        cookies = {
        '__cfduid': 'dec92bef19d6ab9ae41ad9a69d3cd1be21594487232',
        'ASP.NET_SessionId': '5cjpkvyh5sjstdhd12eglk5b',
        'USERID': '170264603',
        'TRACKING': 'SessionStarted=1&GUID=9a1b8738f0b94ccb943e2f865c9a2199&UserReferrer=https%3a%2f%2fwww.controller.com%2flistings%2faircraft%2ffor-sale%2flist%3fSortOrder%3d23%26scf%3dFalse%26page%3d1',
        'TopPopup-Cookie_11': 'Unit=available&Retry=2020-07-12T17:07:15.9365191Z',
        '__RequestVerificationToken': 'AJ3z0d7OpPyY49AuIT-JJCxLZ5-JjJ0Fwf20lAdSLIRmrowO1Kwv-Cy3Bo7AHkkyODF0Sg2',
        'BIGipServerwww.controller.com_http_pool': '1065461952.20480.0000',
        'UserSettingsSession': 'Geo=GB%7cUnited+Kingdom%7cEdinburgh%7cEdinburgh%7cEH11%7c55.9335%7c-3.254%7c0%7c0%7c%7c&screen-size-set=True',
        'UserSettings': 'currency-preference=USD&override-currency=True&onelinelistings=False&unit-preference=imperial&override-unit=True&DefaultMap=&thumbnailphotos=True&screen-height=912&screen-width=1368&image-height=480&image-width=639',
        'reese84': '3:vi2UoeO7DhA7Vp0/IEXo+Q==:0C/8X3VRY0DMDTzIz4ceLFK5QsFhd0l+hlqDe5lhpnON5Y0j4IuQ/kfec8PKCiE6bqdpfPB3/8EK0gk4yh43mSJnfJS3Xwmzm9Tl9YyEMnRrZ2+xNjWQHWqZydQVUlfJlQwPsBz/6/dF7I21OZq4KnSk8SbfVHOQM5J7NpDJIAWggoeLQmgbD1v/3+zePS13n71Xnkz3XAei43S/RI/U74wuRlYkO204yb/Me5hngUW/8Reqguk3iXdNN9H4GAjKdZKmYxsVVGtN/huigZQ4+05I2rHk+nV3zirdYAdZJ10qLw+2RpBAQ30S4YwBulz9wEODkSbUhJGTSh9dUK/i3grtrHIHfNDgyJqrI0Ydif1gDOf77qBz35gQQO1rRMvXj3p5VB7/FnOa+2UVlL8WG79AFSo1t7NEuINjGmKUaHc=:hH59BHHAflKbvFUyM1poFPhO9puxXq5tjYw7E9wzA78=',
        'KeepUserOnSite': 'True',
        'CurrentLatitude': '55.902207999999995',
        'CurrentLongitude': '-3.3292287999999997',
    }
    
         headers = {
             'authority': 'www.controller.com',
             'cache-control': 'max-age=0',
             'upgrade-insecure-requests': '1',
             'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
             'accept':'text/html,application/xhtml+xml,application/xml;q=0.9,
                 image/webp,image/apng,*/*;q=0.8,application/signed- 
                 exchange;v=b3;q=0.9',
             'sec-fetch-site': 'none',
             'sec-fetch-mode': 'navigate',
             'sec-fetch-user': '?1',
             'sec-fetch-dest': 'document',
             'accept-language': 'en-US,en;q=0.9',
               }
    
         def start_requests(self):
             url = 'https://www.controller.com/listings/aircraft/for-sale/list? \
                    SortOrder=23&scf=False&page=1'
             yield scrapy.Request(url=url,headers=self.headers,
                  cookies=self.cookies,callback=self.parse)
    
         def parse(self,response):
             response.text 
    

    Request 方法接受一个 url,因为我们在 start_request 函数之外定义了 headers,我们必须使用 self.headers 和 self.cookies 来访问它。然后我们想将响应发送到函数解析,我们通过指定回调来做到这一点。 start_request 函数可用于在解析函数之前处理 URL。当我们设置蜘蛛进行解析时,Scrapy 会自动正常传递响应。

    【讨论】:

    • 哇,非常感谢!我非常感谢您抽出时间以如此周到的方式做出回应。作为初学者,这绝对有助于理解重新设计请求是什么以及它是如何工作的。我按照您提供的步骤确保我能够获得与您相同的输出并且代码有效:) 再次非常感谢!
    • 我认为您的意思是 start_requests() 而不是 start_request()。此外,start_requests(self) 除了 self 之外不接受任何参数,对吗@AaronS?
    • 在更改为 'start_requests()' 并从 start_requests 函数中取出 'response' 参数后,我在运行 scrapy 时遇到错误:2020-07-13 13:01:46 [scrapy.downloadermiddlewares.cookies] WARNING: Invalid cookie found in request <GET https://www.controller.com/listings/aircraft/for-s ale/list?SortOrder=23&scf=False&page=1>: {'name': 'CurrentLongitude', 'value': ''} ('value' is missing) 而在进行此更改之前,我实际上得到了正确的输出?
    • 我怀疑输入的 cookie 已过期,这就是您收到错误消息的原因。这取决于您是否要多次运行此蜘蛛。如果这只是一次刮擦,那么我上面的答案就可以了。如果是多次抓取或例行抓取,则需要在每次发出请求时获取 cookie。有几种方法可以做到这一点,查看 scrapy 文档中的 cookie 中间件,或者您可以使用 selenium/splash 来呈现 cookie 并在请求中单独传递。
    • @AaronS 这对我不起作用,它给出 405 Method not allowed 你能帮我解决这个问题吗?
    猜你喜欢
    • 2020-06-30
    • 2021-05-01
    • 2021-09-29
    • 2022-11-04
    • 2019-07-09
    • 2016-03-05
    • 2020-10-19
    • 2018-01-21
    • 2013-06-23
    相关资源
    最近更新 更多