zoukankan      html  css  js  c++  java
  • Scrapy 教程(六)-反爬

    伪装浏览器

    服务器可以查看访问的终端,如果不是浏览器,可能会被屏蔽,而且即使你用同一浏览器访问频率过快,也可能被屏蔽,所以需要伪装浏览器反爬。

    有以下几种方法

    1. 在 settings中添加 user_agent

    #USER_AGENT = 'qiushi (+http://www.yourdomain.com)'
    USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0'

    也可以添加其他header

    DEFAULT_REQUEST_HEADERS = {
      'Accept': 'text/html, application/xhtml+xml, application/xml',
      'Accept-Language': 'zh-CN,zh;q=0.8',
      'Host':'ip84.com',
      'Referer':'http://ip84.com/',
      'X-XHR-Referer':'http://ip84.com/'
    }

    2. 重写中间件

    在原有 middlewares.py 中重写中间件,或者新建文件重写,都可以,最终在settings中设置就行了。

    可以准备多个浏览器,每次访问随机选一个

    from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
    class UserAgent(UserAgentMiddleware):def process_request(self, request, spider):
            user_agent_list = [
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
            "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
            "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
            "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
            "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
            "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
            "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
            "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
            "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
            "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 "
            "(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
            "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
            "(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 "
            "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
            "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 "
            "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"]
            ua = random.choice(user_agent_list)
            if ua:
                request.headers.setdefault('User-Agent', ua)

    注意 这里继承了 自带的 UserAgentMiddleware

    settings设置

    DOWNLOADER_MIDDLEWARES = {
       'qiushi.middlewares.UserAgent':1,
       'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware':None}

    None 表示关闭该中间件,注意这个中间件需要关闭scrapy自带的,其他的不一定需要。

    伪装浏览器中间件的优先级尽量高一点。

    限制访问频率

    降低访问目标网站的频率,很简单,自己也可以实现,在scrapy中只需修改settings

    DOWNLOAD_DELAY = 3

    这样做有个问题,虽然延迟访问,但是不能动态改变,规则访问也容易被视为爬虫,此时可以如下配置

    RANDOMIZE_DOWNLOAD_DELAY=True

    利用一个随机值,将延迟时间设置为  0.5-1.5 之间的随机数 X DOWNLOAD_DELAY

    但这可能仍然不够,scrapy 可以实现自动限速扩展,具体请百度。

    禁用cookies请求

    修改settings

    COOKIES_ENABLED = False

    如果网站无需登录就可以爬取,最好禁用 cookie,因为 cookie 会跟踪爬虫的访问过程,容易被发现

    使用网络代理

    用同一个IP频繁请求一个网站,是很容易被封的。那怎么办呢?使用代理是最常用的解决方式。

    需要说明的是:

    如果你是用猫来上网,可以通过重启更换IP,因为每次重启会重新分配IP;

    如果你不差钱,可以买很多代理IP,那实现代理爬虫也很简单。

    在有代理的情况下创建代理爬虫的方法

    创建中间件

    class ProxyMiddleware(object):
        def process_request(self, request, spider):
            request.meta['proxy'] = 'http://xx.x.x.x:3128'    

    修改settings

    DOWNLOADER_MIDDLEWARES = {
       'qiushi.middlewares.UserAgent':1,
       'qiushi.middlewares.ProxyMiddleware':100}

    没错,就是这么简单。

    问题来了,1. 没钱怎么办? 2. 如果代理被封了怎么办?

    可以通过爬虫获取大量免费代理IP,然后检测其是否有效

    创建免费代理爬虫

    免费代理

    免费代理需要注意以下几点:

    1. 免费代理不保证能用

    2. 即使能用,其存活期也比较短,可能检测时能用,真正用时已经不能用了

    3. 免费代理分为透明代理匿名代理,需要的是匿名代理 【透明代理好像服务器能够看到你真实IP】

    4. 免费代理分为http型和https型,一般根据目标url选择,如果目标url为http类型,只能用http型代理;如果目标url为https类型,一般用https型代理,也可以试试http型代理是否能用。【https加密】

    5. 比较好的免费代理网站  快代理     西刺代理,使用爬虫爬虫该网站

    检测代理

    如何检测代理是否有效呢?

    1. 专业检测网站 

    http://www.xdaili.cn/monitor

    2. 利用urllib2或者request代理检测,参考我的博客  https://www.cnblogs.com/yanshw/p/10863479.html

    urllib2 大概是这样

    opener = urllib2.build_opener(urllib2.ProxyHandler({'https':'https://119.99.45.153:9999'}))
    urllib2.install_opener(opener)
    response = urllib2.urlopen('http://tianqi.2345.com/', timeout=3)
    print(response.getcode())

    request 大概是这样

    import requests
    
    url = 'http://ip.chinaz.com/'
    proxies = {
        'http': 'http://172.16.6.70:3128',
        }
    r = requests.get(url, proxies=proxies)
    print(r)
    print(dir(r))
    print(r.headers)

    检测时要注意返回的是不是代理IP,如果代理IP不能用,也会返回,返回的是自己的IP,也就是说 urllib 会搜索环境变量中的代理

    3. 当然也有其他方法

    很不错的教程

    使用网络代理实际上会遇到很多坑的,日后慢慢补充。

    Cookies登录中间件

    利用cookies进行模拟登录

    获取cookie

    1. 手动输入登录,通过浏览器查看cookie

    2. 利用selenium模拟登录,并且用不同账户,获取多个cookie,防止cookie被封

    定义中间件

    class LoginMiddleware(object):
        def __init__(self):
            self.client = redis.StrictRedis()
        
        def process_request(self, request, spider):
            if spider.name == 'loginSpider':
                cookies = json.loads(self.client.lpop('cookies').decode())
                request.cookies = cookies

    注意最后一句就行了,其他灵活变通。

    更pythonic的写法

    1. 把 user-agent-list 、 proxy-list 等写到 settings 里,格式仍是list【也可以写在数据库等任何可以的地方,对应方法获取即可】

    2. 在中间件里导入 settings

    3. 调用 settings[‘key’]

    示例代码

    PROXIES = ['https://114.217.243.25:8118',
              'https://125.37.175.233:8118',
              'http://1.85.116.218:8118']
    import random
    from scrapy.conf import settings
    class ProxyMiddleware(object):
      def process_request(self, request, spider):
          proxy = random.choice(settings['PROXIES'])
          request.meta['proxy'] = proxy
  • 相关阅读:
    Python面向对象
    Python函数
    Linux之路
    Python之路
    函数
    动态参数
    python模块的运行机制以及time模块格式转换
    Python PEP8代码规范_20180614
    Oracle 分页查询方法和效率分析
    oracle 12c数据库启动(包含CDB和PDB)以及常见异常处理
  • 原文地址:https://www.cnblogs.com/yanshw/p/10858087.html
Copyright © 2011-2022 走看看