【问题标题】:Scrapy - Connection lost in a non-clean fashion. Inconsistent across a single domainScrapy - 连接以不干净的方式丢失。跨单个域不一致
【发布时间】:2018-06-28 00:17:11
【问题描述】:

我创建了一个基本的蜘蛛来从 totaljobs.com 上抓取一小组工作列表。我已经使用一个起始 URL 设置了蜘蛛,以显示我感兴趣的作业列表。从那里,我为每个结果页面启动一个单独的请求。在这些请求中的每一个中,我都会启动一个单独的请求,回调到不同的解析方法,以处理各个作业 URL。

我发现起始 URL 和所有结果页面请求都得到了很好的处理——scrapy 连接到站点并返回页面内容。但是,当它尝试跟踪每个单独的工作页面的 URL 时,scrapy 无法建立连接。在我的日志文件中,它指出:

[<twisted.python.failure.Failure twisted.internet.error.ConnectionLost: Connection to the other side was lost in a non-clean fashion: Connection lost.>]

恐怕我没有大量的编程经验或互联网协议等知识,所以请原谅我无法提供更多关于这里可能发生的事情的信息。我尝试更改 TLS 连接类型;更新到最新版本的 scrapy、twisted 和 OpenSSL;回滚到以前版本的 scrapy、twisted 和 OpenSSL;回滚加密版本,创建自定义上下文工厂并尝试各种浏览器代理和代理。我每次都得到相同的结果:只要 URL 与特定的作业页面相关,scrapy 就无法连接,我得到上述日志文件输出。

我可能忽略了一些对经验丰富的爬虫来说非常明显的东西,这阻止了我与 scrapy 的联系。我已尝试遵循这些线程中的一些建议:

https://github.com/scrapy/scrapy/issues/1429

https://github.com/requests/requests/issues/4458

https://github.com/scrapy/scrapy/issues/2717

但是,其中一些有点超出我的想象,例如如何更新密码列表等。我认为这是某种认证问题,但是scrapy又能够连接到该域上的其他 URL,所以我不知道。

我用来测试的代码非常基本,但无论如何都在这里:

import scrapy

class Test(scrapy.Spider):


    start_urls = [
                    'https://www.totaljobs.com/job/welder/jark-wakefield-job79229824'
                    ,'https://www.totaljobs.com/job/welder/elliott-wragg-ltd-job78969310'
                    ,'https://www.totaljobs.com/job/welder/exo-technical-job79019672'
                    ,'https://www.totaljobs.com/job/welder/exo-technical-job79074694'
                        ]

    name = "test"

    def parse(self, response):
        print 'aaaa'
                yield {'a': 1}

以上代码中的网址没有连接成功。

以下代码中的网址正在连接成功。

import scrapy

class Test(scrapy.Spider):


    start_urls = [
                    'https://www.totaljobs.com/jobs/permanent/welder/in-uk'
                    ,'https://www.totaljobs.com/jobs/permanent/mig-welder/in-uk'
                    ,'https://www.totaljobs.com/jobs/permanent/tig-welder/in-uk'
                        ]

    name = "test"

    def parse(self, response):
        print 'aaaa'
                yield {'a': 1}

如果有人可以复制这种行为(或者不是,视情况而定)并告诉我,那就太好了。请让我知道我是否应该提交其他详细信息。如果我忽略了一些非常明显的事情,我深表歉意。我正在使用:

Windows 7 64 位

Python 2.7

scrapy 版本 1.5.0

扭曲版本 17.9.0

openSSL 版本 17.5.0

lxml 版本 4.1.1

【问题讨论】:

  • 也许该站点正在执行某种机器人检测并断开连接。
  • 我怀疑是这种情况。我很想知道是否有任何方法可以准确地确定有哪些措施可以防止机器人进入。如果我知道我可以做哪些检查来检测这些措施,那么我可以完全避免为这些类型的网站编写爬虫,而不是设计一种方法来绕过蚂蚁抓取措施。
  • 有几种检测机器人的措施,包括一些微妙的事情,比如浏览器发送标头的顺序。除非您将来自普通浏览器的流量与使用 Wireshark 之类的机器人进行比较,否则很难判断。

标签: python python-2.7 web-scraping scrapy python-requests


【解决方案1】:

您或许可以尝试设置一个用户代理,看看是否会有所改变。

您也可以尝试在请求之间或使用代理进行延迟较大的请求。

由于它是一个求职网站,我想他们有某种反刮削机制。

这不是一个惊人的答案,但我可以与您分享一些见解,也许可以帮助您确定下一步。

【讨论】:

【解决方案2】:

这是一个blog 的链接,我最近读到了关于使用 Scrapy 进行负责任的网络抓取的内容。希望对你有帮助

【讨论】:

  • 这里不鼓励仅链接的答案。他们很容易链接腐烂。
【解决方案3】:

在我的情况下,它是由用户代理被拒绝引起的。我们应该为每个请求更改用户代理。为此,您应该使用scrapy fake user agent,然后使用此中间件确保它在每次重试时更改用户代理。

from scrapy.downloadermiddlewares.retry import *
from scrapy.spidermiddlewares.httperror import *

from fake_useragent import UserAgent

class Retry500Middleware(RetryMiddleware):

    def __init__(self, settings):
        super(Retry500Middleware, self).__init__(settings)

        fallback = settings.get('FAKEUSERAGENT_FALLBACK', None)
        self.ua = UserAgent(fallback=fallback)
        self.ua_type = settings.get('RANDOM_UA_TYPE', 'random')

    def get_ua(self):
        '''Gets random UA based on the type setting (random, firefox…)'''
        return getattr(self.ua, self.ua_type)

    def process_response(self, request, response, spider):
        if request.meta.get('dont_retry', False):
            return response
        if response.status in self.retry_http_codes:
            reason = response_status_message(response.status)
            request.headers['User-Agent'] = self.get_ua()
            return self._retry(request, reason, spider) or response
        return response

    def process_exception(self, request, exception, spider):
        if isinstance(exception, self.EXCEPTIONS_TO_RETRY) \
                and not request.meta.get('dont_retry', False):
            request.headers['User-Agent'] = self.get_ua()
            return self._retry(request, exception, spider)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    相关资源
    最近更新 更多