• 日常反反爬虫


    这里介绍几种工作中遇到过的常见反爬虫机制及应对策略。

    爬虫的君子协议

    有些网站希望被搜索引擎抓住,有些敏感信息网站不希望被搜索引擎发现。

    网站内容的所有者是网站管理员,搜索引擎应该尊重所有者的意愿,为了满足以上等等,就需要提供一种网站和爬虫进行沟通的途径,给网站管理员表达自己意愿的机会。有需求就有供应,robots协议就此诞生。

    scrapy是默认遵守robots协议的,需要我们在settings.py文件中将代码改成

    ROBOTSTXT_OBEY = Flase

    封锁请求头

    当访问过于频繁的时候,网站后台会去识别你的请求头,判断你是浏览器访问,还是程序访问。

    我们只需要伪造请求头信息,制造出浏览器访问的假象。

    以下分别提供三个爬虫代码的请求头更改

    1 import requests
    2 import re
    3 
    4 url = 'https://list.tmall.com/search_product.htm?q=%B0%D7%BE%C6&type=p&vmarket=&spm=875.7931836%2FB.a2227oh.d100&from=mallfp..pc_1_searchbutton'
    5 
    6 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063'}
    7 
    8 content = requests.get(url,headers=headers)
    requests版
     1 from selenium import webdriver
     2 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
     3 
     4 dcap = dict(DesiredCapabilities.PHANTOMJS)
     5 dcap["phantomjs.page.settings.userAgent"] = (
     6 "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 6 Build/LYZ28E) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.23 Mobile Safari/537.36"
     7 )
     8 driver = webdriver.PhantomJS(desired_capabilities=dcap)
     9 driver.get("https://httpbin.org/get?show_env=1")
    10 driver.get_screenshot_as_file('01.png')
    11 driver.quit()
    selenium+phantomjs版

    scrapy随机更改请求头,首先在settings.py文件中添加请求头,再告诉scrapy去哪取请求头。

    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/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
        "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/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
        "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"
    ]
    DOWNLOADER_MIDDLEWARES = {
        'onenine.middleware.RandomUserAgentMiddleware': 400,
        'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,
    }

    在settings.py中,我们的路径设置应该是

    yourproject.middlewares(文件名).middleware类

    再在Middleware.py中定义请求头处理模块。

    from settings import USER_AGENT_LIST
    
    import random
    from scrapy import log
    
    class RandomUserAgentMiddleware(object):
        def process_request(self, request, spider):
            ua  = random.choice(USER_AGENT_LIST)
            if ua:
                request.headers.setdefault('User-Agent', ua)

    如果实在不想在网上找各种请求头,可以使用fake-useragent伪造请求头

    import requests
    from fake_useragent import UserAgent
    ua = UserAgent()
    headers = {'User-Agent': ua.random}
    url = '待爬网页的url'
    resp = requests.get(url, headers=headers)
    View Code

    js渲染页面

    我们在页面上看的网页是js渲染过后的页面,当我们去通过源码拿数据的时候就会发现找不到我们相要的数据。

    以下提供三种解决思路。

    • selenium+webdriver

      使用浏览器驱动加上selenium可以完全模拟人为操作。在解决验证码问题时有奇效。但是,一般情况下是不会建议使用selenium,主要是效率问题。虽然使用phantomjs等无头浏览器会减少内存消耗,效率比较其他两种方法还是低了很多,且不适用做分布式开发。(最新版本的selenium和phantomjs分手了。)

    • scrapy_splash

      有些类似于selenium,但较于selenium,scrapy_splash是基于Twisted和QT开发的轻量浏览器引擎,并且提供直接的http api。快速、轻量的特点使其容易进行分布式开发。scrapy和splash集合兼容做的特别好,不过需要在docker环境下运行。有兴趣的可以去自行了解。(目前使用遇到js渲染不完全)

    • 抓包

      通过分析页面的api接口拿到想要数据。这是效率最快的一种方法,也是最麻烦的方法。有些网站对自己的api接口封锁特别严苛,淘宝其中一个api接口甚至会出现每拿四条数据就需要验证码识别的情况。

    ip封锁

    面对ip封锁,我们只能使用代理ip。

    一般做爬虫的只是出于学习目的的情况可以自己做一个ip池,通过抓取免费ip代理网站的ip放到数据库中自己用。但是一般免费的ip是不稳定的,存活时间短暂且不高匿。

    商业的代理ip有很多,鱼龙混杂,ip切换模式也各有不同。我们现在使用的ip代理是能达到秒切,有效防止因为ip的原因被ban,当然价格也可观。

    以下是三种使用ip代理接口的代码

      import requests
    
        # 要访问的目标页面
        targetUrl = "http://test.abuyun.com/proxy.php"
    
        # 代理服务器
        proxyHost = "http-dyn.abuyun.com"
        proxyPort = "9020"
    
        # 代理隧道验证信息
        proxyUser = "H01234567890123D"
        proxyPass = "0123456789012345"
    
        proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
          "host" : proxyHost,
          "port" : proxyPort,
          "user" : proxyUser,
          "pass" : proxyPass,
        }
    
        proxies = {
            "http"  : proxyMeta,
            "https" : proxyMeta,
        }
    
        resp = requests.get(targetUrl, proxies=proxies)
    requests版
     from selenium import webdriver
    
        # 代理服务器
        proxyHost = "http-dyn.abuyun.com"
        proxyPort = "9020"
    
        # 代理隧道验证信息
        proxyUser = "H01234567890123D"
        proxyPass = "0123456789012345"
    
        service_args = [
            "--proxy-type=http",
            "--proxy=%(host)s:%(port)s" % {
                "host" : proxyHost,
                "port" : proxyPort,
            },
            "--proxy-auth=%(user)s:%(pass)s" % {
                "user" : proxyUser,
                "pass" : proxyPass,
            },
        ]
    
        # 要访问的目标页面
        targetUrl = "http://test.abuyun.com/proxy.php"
    
        phantomjs_path = r"./phantomjs"
    
        driver = webdriver.PhantomJS(executable_path=phantomjs_path, service_args=service_args)
        driver.get(targetUrl)
    
        print driver.title
        print driver.page_source.encode("utf-8")
    
        driver.quit()                        
                        
    selenium+phantonjs版

    scrapy需在中间件middlewares.py中定义

    import base64
    
        # 代理服务器
        proxyServer = "http://http-dyn.abuyun.com:9020"
    
        # 代理隧道验证信息
        proxyUser = "H01234567890123D"
        proxyPass = "0123456789012345"
    
        # for Python3
        #proxyAuth = "Basic " + base64.urlsafe_b64encode(bytes((proxyUser + ":" + proxyPass), "ascii")).decode("utf8")
    
        class ProxyMiddleware(object):
            def process_request(self, request, spider):
                request.meta["proxy"] = proxyServer
    
                request.headers["Proxy-Authorization"] = proxyAuth                        
                        

    再到settings.py文件中修改参数

    DOWNLOADER_MIDDLEWARES = {  
    #    'myproxies.middlewares.MyCustomDownloaderMiddleware': 543,  
         'scrapy.contrib.downloadermiddleware.httpproxy.HttpProxyMiddleware':543,  
         'yourproject.middlewares.ProxyMiddleware':125  
    }  
  • 相关阅读:
    个人作业—软件评测
    结对第二次作业——某次疫情统计可视化的实现
    结对第一次—某次疫情统计可视化(原型设计)
    软工实践寒假作业(2/2)
    寒假规划作业(1/2)
    【图像处理】利用双线性插值算法进行图像的缩放
    只用css实现“每列四行,加载完一列后数据自动填充到下一列”的效果
    js中运算符优先级问题
    微信、QQ中app的下载问题
    浅述html5和web app
  • 原文地址:https://www.cnblogs.com/lixiaoliuer/p/8671401.html
Copyright © 2020-2023  润新知