反爬虫

反爬虫策略

  1. 动态设置User-Agent(随机切换User-Agent,模拟不同用户的浏览器信息)
  2. 禁用Cookies, 有些网站通过cookie的使用信息发现爬虫行为
  3. scrapy中可以通过COOKIES_ENABLED 控制 CookiesMiddleware 开启或关闭
  4. 设置延迟下载(防止访问过于频繁,设置为 2秒 或更高)
  5. Google Cache 和 Baidu Cache:如果可能的话,使用谷歌/百度等搜索引擎服务器页面缓存获取页面数据。
  6. 使用IP地址池. scrapy设置downloadmiddleware

开启下载中间件

  • 说明:
    1. 当引擎传递请求给下载器的过程中,下载中间件可以对请求进行处理 (例如增加http header信息,增加proxy信息等)
    2. 在下载器完成http请求,传递响应给引擎的过程中, 下载中间件可以对响应进行处理(例如进行gzip的解压等)
# settings.py
DOWNLOADER_MIDDLEWARES = {
    'mySpider.middlewares.MyDownloaderMiddleware': 543,
}

主要方法

process_request(self, request, spider)

  • 说明:
    1. 当每个request通过下载中间件时,该方法被调用。
    2. 须返回以下其中之一:None, Response 对象, Request 对象, raise IgnoreRequest
    • 返回 None, Scrapy将继续处理该request,执行其他的中间件的相应方法,直到合适的下载器处理函数(download handler)被调用, 该request被执行(其response被下载)。
    • 返回 Response 对象,Scrapy将不会调用 任何 其他的 process_request() 或 process_exception() 方法,或相应地下载函数; 其将返回该response。 已安装的中间件的 process_response() 方法则会在每个response返回时被调用。
    • 返回 Request 对象,Scrapy则停止调用 process_request方法并重新调度返回的request。当新返回的request被执行后, 相应地中间件链将会根据下载的response被调用。
    • raise一个 IgnoreRequest 异常,则安装的下载中间件的 process_exception() 方法会被调用。如果没有任何一个方法处理该异常, 则request的errback(Request.errback)方法会被调用。如果没有代码处理抛出的异常, 则该异常被忽略且不记录(不同于其他异常那样)。

process_response(self, request, response, spider)

  • 说明:
    1. 当下载器完成http请求,传递响应给引擎的时候调用
    2. 必须返回以下其中之一: 返回Response 对象, 返回Request 对象, raise一个 IgnoreRequest 异常。
    • 返回 Response (可以与传入的response相同,也可以是全新的对象), 该response会被在链中的其他中间件的 process_response() 方法处理。
    • 返回 Request 对象,则中间件链停止, 返回的request会被重新调度下载。处理类似于 process_request() 返回request所做的那样。
    • 如果其抛出一个 IgnoreRequest 异常,则调用request的errback(Request.errback)。 如果没有代码处理抛出的异常,则该异常被忽略且不记录(不同于其他异常那样)。

设置user-agent与proxy

# settings.py
USER_AGENTS = [
    "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
    "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
    "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
    "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
    "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6"
    ]

PROXIES = [
    {'ip_port': '111.8.60.9:8123', 'user_passwd': 'user1:pass1'},# user1是用户名,pass1是密码
    {'ip_port': '101.71.27.120:80', 'user_passwd': 'user2:pass2'},
    {'ip_port': '122.96.59.104:80', 'user_passwd': 'user3:pass3'},
    {'ip_port': '122.224.249.122:8088', 'user_passwd': 'user4:pass4'},
]

# 除非特殊需要,禁用cookies,防止某些网站根据Cookie来封锁爬虫。
COOKIES_ENABLED = False
# 设置下载延迟
DOWNLOAD_DELAY = 3
# 最后设置setting.py里的DOWNLOADER_MIDDLEWARES,添加自己编写的下载中间件类。
DOWNLOADER_MIDDLEWARES = {
    'mySpider.middlewares.RandomUserAgent': 50,
    'mySpider.middlewares.ProxyMiddleware': 100
}

# middlewares.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import random
import base64
from settings import USER_AGENTS
from settings import PROXIES

# User-Agent中间件
class RandomUserAgent(object):
    def process_request(self, request, spider):
        useragent = random.choice(USER_AGENTS)
        request.headers.setdefault("User-Agent", useragent)

# Proxy中间件
class RandomProxy(object):
    def process_request(self, request, spider):
        proxy = random.choice(PROXIES) # 随机选择一个proxy
        if proxy['user_passwd'] is None:
            # 没有代理账户验证的代理使用方式
            request.meta['proxy'] = "http://" + proxy['ip_port']
        else:
            # 对账户和密码进行base64编码转换
            base64_userpasswd = base64.b64encode(proxy['user_passwd'])
            # 对应到代理服务器的信令格式里
            request.headers['Proxy-Authorization'] = 'Basic ' + base64_userpasswd
            request.meta['proxy'] = "http://" + proxy['ip_port']

中间件处理代理ip异常

  • 对失败的请求, scrapy默认重试3次, 如果都失败就放弃该请求.
  • 通常购买的ip代理, 每分钟才会更换一次ip, 如果ip不稳定或者被封ip, 重试3次都会失败.
  • 重试失败时, scrapy抛出 TCPTimeOutError 异常.
  • 在中间件捕获这个异常, 进行重试或更换ip
from twisted.internet.error import TCPTimedOutError
import scrapy

class RetryCustomMiddleware(RetryMiddleware):
    def __init__(self):
        RetryMiddleware.__init__(self, settings)

    def process_response(self, request, response, spider):
        if spider.name = 'retry_spider':
            if response.status == 404:
                origin_url = request.meta['redirect_urls'][0]
                return request.replace(
                    url=origin_url,
                )
            return response

    # 异常处理
    def process_exception(request, exception, spider):
        if isinstance(exception, TCPTimedOutError): # 如果异常是超时类型
            self.remove_broken_proxy(request.meta['proxy']) # 移除代理ip
            return request.copy() # 重新请求, 由代理中间件重新设置ip

    def remove_broken_proxy(self, proxy):
        # 从代理池删除ip
        pass

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值