zoukankan      html  css  js  c++  java
  • 爬虫

    应对反爬

    更换ip地址

    比如我用requests来发送请求

    import requests
    
    proxies = {
      "http": "http://10.10.1.10:3128",
      "https": "http://10.10.1.10:1080",  # 这里用 https 代理会失效,取的是 https ip 也不行,可能我爬取的是 http 网站(猜测)
    }
    
    requests.get("http://example.org", headers=headers, proxies=proxies)
    

    参数proxies就是更换的代理ip,注意格式里https的头还是http

    至于ip怎么搞,一些卖ip的网站首页上有免费的ip可以用,写了个爬虫爬下来用
    后来可能是爬多了,别人把我封了,就花钱买了ip
    这里推荐一下大象代理,http://www.daxiangdaili.com
    五块钱两万个ip,可能不太稳定,但自己用应该够了

    requests文档
    http://docs.python-requests.org/zh_CN/latest/user/advanced.html#proxies

    更换UserAgent

    User-Agent 首部包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。

    我是这么做的
    去网上复制十几个UserAgent,放到列表里,每次从中随机取一个

    from random import choice
    
    ua_list = [
        'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36',
        'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
        'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv,2.0.1) Gecko/20100101 Firefox/4.0.1',
        'Mozilla/5.0 (Windows NT 6.1; rv,2.0.1) Gecko/20100101 Firefox/4.0.1',
        'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0;',
        'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)',
        'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
        'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)',
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
        '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/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)',
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)',
    ]
    
    def ua_get():
        ua = choice(ua_list)
        headers = {"User-Agent": ua, }
        return headers
    

    看到更骚的操作是,使用搜索引擎爬虫的UserAgent
    试了一下,但会报错,就没去深究了

    redis 代理ip池

    之前的做法是每次从代理接口取一个ip,所有的请求都用这一个ip去伪装
    问题是,取的间隔至少得一秒,如果这个ip不能用或者速度慢,那这一秒内的请求全部不能用,并且会一直请求到超时
    既然用的是五块钱两万个ip,那肯定一大堆不能用的

    所以去网上看了别人的做法,然后按自己的想法做了一个ip池
    具体做法是

    每次从接口取10个ip,放进redis里,取的方式是先进后出,每次从头部取
    设置请求的时间,如果请求超时或者报错了,就重新取一个ip再发请求
    限制发送次数,超过次数就退出来
    如果请求发送成功,拿到了想要的东西,就把那个能用的ip从尾部塞回去
    如果去redis取ip的时候发现空了,就重新去接口拿10个

    整个过程就是这样,贴一个丑陋的函数

    def requests_send(url):
        h = header_get()
        code = 0
        count = 0
        while code != 200:  # 如果请求不成功,就接着请求下去
            count += 1
            print('第{}次请求'.format(count))
            if count > 10:  # 限制次数
                break
            try:
                ip = pop()  # 取ip
                p = dict(http='http://{}'.format(ip))
                print('proxy', p)
                r = requests.get(url, headers=h, proxies=p, timeout=3)  # 发送请求
                response = r.content.decode('utf-8')
                code = r.status_code
                path = response
            except Exception as err:  # 报错了的话,也会重新请求
                print(str(err))
            else:
                print('path[-4:]', path[-4:])
                if path[-4:] != '.mp3':  # 如果没拿到想要的,重新开始一次
                    continue
                rds.rpush('ip-proxy-pool', ip)  # 成功了把ip塞回去
                print('补充1个', ip)
                return dict(code=200, path=path)
        return dict(code=-1)
    

    这种做法并不好,有条件的话,应该时刻保持着ip能用,但那样的话请求量就陡增了很多

    文档
    https://cloud.tencent.com/developer/article/1004915
    https://www.jianshu.com/p/588241a313e7

  • 相关阅读:
    Angular2.x-主/细节组件
    Angular2.x-显示heroes列表
    Angular2.x
    Linux-百度云之AccleriderMini使用
    Angular结构简单介绍
    Phonegap
    Deepin-安装vscode
    javascript 递归函数调用(recursive funciton call)
    go 中的pacage 名称 和import {}中的名称
    go get 下载的包放在哪里呢?
  • 原文地址:https://www.cnblogs.com/xb21/p/8386111.html
Copyright © 2011-2022 走看看