zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Scrapy中间件采集HTTPS网站失败的原因

scrapy中间件HTTPS网站 失败 原因 采集
2023-06-13 09:18:30 时间
亿牛云代理

Scrapy 是一个基于 Python 的网络抓取框架,可以帮助开发人员从网站中快速有效地提取数据。Scrapy 的一个显著优势是可以通过中间件来定制和优化抓取过程。中间件是一种插件,可以在请求和响应之间执行特定的功能,例如更换用户代理、管理 cookie 和处理重定向。Scrapy 中间件还可以让用户设置代理 IP,这对于从有反抓取措施的网站抓取大量数据非常有用。使用代理 IP 可以隐藏用户的真实身份,避免被网站封禁。总之,Scrapy 中间件提供了一种灵活且可定制的方式来改善网络抓取过程。 要使用代理 IP,可以编写一个中间件组件,在请求对象中设置代理和认证信息,这样Scrapy 就会使用代理和认证信息来访问网站。在项目中新建middlewares.py文件(./项目名/middlewares.py),下面是相应的代码:

import base64            
import sys
import random

PY3 = sys.version_info[0] >= 3

def base64ify(bytes_or_str):
    """
    将输入的字符串或字节数组使用 base64 进行编码,并返回编码后的结果。
    如果输入为字符串,则先将其转换为字节数组。
    """
    if PY3 and isinstance(bytes_or_str, str):
        input_bytes = bytes_or_str.encode('utf8')
    else:
        input_bytes = bytes_or_str

    output_bytes = base64.urlsafe_b64encode(input_bytes)
    if PY3:
        return output_bytes.decode('ascii')
    else:
        return output_bytes

class ProxyMiddleware(object):
    """
    scrapy 的中间件,用于为每个请求添加代理。
    """
    def process_request(self, request, spider):
        #亿牛云爬虫加强版 代理服务器地址和端口号
        proxy_host = "www.16yun.cn"
        proxy_port = "31111"

        #亿牛云爬虫加强版 代理服务器验证信息
        proxy_username = "16YUN"
        proxy_password = "16IP"

        # 将请求的代理设置为指定的代理服务器
        request.meta['proxy'] = "http://{0}:{1}".format(proxy_host, proxy_port)
        # 为请求添加代理服务器验证头
        request.headers['Proxy-Authorization'] = 'Basic ' +  base64ify(proxy_username + ":" + proxy_password)

        # 每次请求后关闭 TCP 连接,以强制切换 IP
        request.headers['Connection'] = "Close"

上述代码可以直接部署使用,但是一部分用户在采集一段时间之后,发现https网站会出现目标服务器识别拒绝响应的情况,是什么原因造成的呢?问题就出现在当采集https网站的时候,标识'Proxy-Authorization'的认证信息会被传递至目标网站服务器,一旦目标服务器识别该信息即加入反爬处理,导致爬虫请求失效。

如何解决该问题呢?Scrapy版本从2.6.2开始,对该问题进行了修护,通过直接设置用户认证信息的方式,无需添加验证标识,会自动在请求头中设置'Proxy-Authorization'。这样即使在https的请求中,该认证信息也不会被传递至目标网站服务器从而避免被反爬,修改如下:

import base64            
import sys
import random

PY3 = sys.version_info[0] >= 3

def base64ify(bytes_or_str):
    """
    将输入的字符串或字节数组使用 base64 进行编码,并返回编码后的结果。
    如果输入为字符串,则先将其转换为字节数组。
    """
    if PY3 and isinstance(bytes_or_str, str):
        input_bytes = bytes_or_str.encode('utf8')
    else:
        input_bytes = bytes_or_str

    output_bytes = base64.urlsafe_b64encode(input_bytes)
    if PY3:
        return output_bytes.decode('ascii')
    else:
        return output_bytes

class ProxyMiddleware(object):
    """
    scrapy 的中间件,用于为每个请求添加代理。
    """
    def process_request(self, request, spider):
        # 亿牛云爬虫加强版 代理服务器地址和端口号
        proxy_host = "www.16yun.cn"
        proxy_port = "31111"

        #亿牛云爬虫加强版 代理服务器验证信息
        proxy_username = "16YUN"
        proxy_password = "16IP"
       
        # [版本>=2.6.2]直接设置用户认证信息,无需添加验证头,会自动在请求头中设置Proxy-Authorization     
        request.meta['proxy'] = "http://{0}:{1}@{2}:{3}".format(proxyUser,proxyPass,proxyHost,proxyPort)

        # 每次请求后关闭 TCP 连接,以强制切换 IP
        request.headers['Connection'] = "Close"

通过上述修改,就能避免出现长期采集过程中被目标网站拒绝服务。

可以通过爬虫程序访问网站https://httpbin.org/headers进行测试,分析用户认证信息是否已经被处理。