用户
搜索

[思路/技术] 爬虫与反爬虫

  • TA的每日心情
    慵懒
    2018-4-21 16:11
  • 签到天数: 92 天

    连续签到: 2 天

    [LV.6]常住居民II

    i春秋作家

    从未进过后台和拿过shell的菜鸟。求大佬带

    Rank: 7Rank: 7Rank: 7

    31

    主题

    86

    帖子

    1494

    魔法币
    收听
    2
    粉丝
    3
    注册时间
    2017-1-24

    i春秋签约作者春秋文阁

    我是salf i春秋作家 从未进过后台和拿过shell i春秋签约作者 春秋文阁 楼主
    发表于 2018-5-14 21:19:42 43071

    爬虫与反爬虫

    爬虫工程师和反爬虫工程师可谓是天敌的两个职业。他们之间用代码进行交流,这篇文章将用简单的说明和代码来展示爬虫与反爬虫之间的斗争

    反爬虫的演变

    无反爬

    #flask必备部分下面不再出现
    import flask
    app = Flask(__name__)
    
    @app.route('/')
    def main():
        return 'Hello, World!'

    网站都没有任何反爬虫措施 所以爬虫只需要简单的请求就行了

    import requests
    requests.get('http://url')

    user-agent限制

    爬虫库默认使用了特殊user-agent 比如requests默认的user-agent像是python-requests/2.3.0 CPython/2.6.6 Windows/7 .所以反爬虫工程师开始检查user-agent .
    i春秋使用的创宇盾也进行了检查 如果是爬虫默认的user-agent请求 会直接返回503

    def main():
        erruser-agent = ['python-requests/2.3.0','xxxx']
        for i in  requests.user_agent.string.split:
              if i in  erruser-agent:
                 return 'fuck you'
        return 'Hello, World!'

    当然爬虫工程师也不傻 直接用正常的user-agent

    import requests
    HEADER = {
            'User-Agent': ' "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"',
    }
    requests.get('http://url', headers=HEADER)

    频率限制

    因为一个正常用户不可能像爬虫那样疯狂访问,访问频率过高也成为了爬虫的特征。不过http是一个无状态的协议 无法识别是否是同一个用户。所以反爬虫工程师们决定根据ip来识别 如果一个ip访问频率过高就把他暂时拉入黑名单

    # 黑名单ip
    ban = []
    # ip访问次数 每分钟自动清空的代码省略 处理异常省略
    ipget = {}
    ipmaxget = 30
    @app.route('/')
    def main():
        ip = request.remote_addr
        if ip in ban:
           return 'fuck you'
        if ipget[ip]:
           ipget[ip]=ipget[ip]+1
        else:
           ipget[ip] = 1
        if  ipget[ip]>ipmaxget:
            ban.append(ip)
            return 'fuck you' 
        return 'Hello, World!'

    爬虫工程师发现反爬虫工程师开始封ip 自然不会甘心 要知道还有代理这种东西。
    打造属于自己的代理IP池
    想办法弄到了一批代理后 随机使用代理 反爬虫工程师根据ip识别的方法也束手无策

    proxylist = ['xxx'] #省略
    proxies = {'http': random.choice(proxylist)}
    requests.get('http://url', headers=HEADER)

    图形验证码

    反爬虫要注意效果和用户体验之间的平衡 用上验证码防爬的相当少
    由于实现验证码的代码有点长和基本已经内置 故不给出代码

    图像验证码在以前时代基本是无法破解的 但是现在机器/深度学习发展起来 图像验证码已经不再安全了

    看了一下论坛已经有表哥写了类似的内容 就不再重述 python-i春秋验证码识别

    javascript获取数据

    大部分爬虫都是直接获取html 并没有处理javascript的能力。所以反爬虫工程师开始使用javascript展示界面

    def main():
         return '<script >document.write('hello world')</script>'

    但是数据还是要返回到浏览器的 爬虫工程师分析javascript也能找到想要的数据
    然后演变成了javascript混淆与反混淆之战

    或者开始使用ajax之类来请求数据

    @app.route('/')
    def main():
         return '<script>document.write($.ajax({url:"/ajax",async:false}))</script>'
    
    @app.route('/ajax')
    def ajax()
         return 'hello world'

    爬虫工程师可以进行网络分析 找到真正请求的url.但是反爬虫工程师如果进行参数加密 爬虫工程师根本没办法构造自己所需要的数据的请求

    这个时候就要使用模拟浏览器获取内容了

    import pychrome
    host,port=xxx,xxx
    brower = pychrome.Browser(url='http://{host}:{post}'.format(host=host, post=port))
    tab = brower.new_tab(url=url) # 打开网页
    tab.start()
    tab.wait(3) #等待3秒javascript运行
    req = tab.call_method('Runtime.evaluate', expression='document.documentElement.innerHTML')['result']['value'] #得到完整网页

    使用方法可以参考 chrome无头模式模拟

    cookie检查

    这个各个网站反爬虫工程师实现都不一样 不过大概思路就是首次访问给你一个合法cookies 每次访问都在javascript进行改动 如果多次没有cookie或者cookie 直接拉黑

    这个只能通过多次网络和javascript分析找到规律或者使用模拟浏览器访问解决

    更先进的验证码

    现在更先进的验证码比如语音验证码和12306那种验证码已经开始使用  这里就没有什么通用的方法了 只有使用ai技术进行识别  ,一个好的爬虫工程师不但是爬虫工程师还是ai工程师

    本帖被以下淘专辑推荐:

    • · 思路|主题: 27, 订阅: 2
    个人博客 https://blue-bird1.github.io/
    发表于 2018-5-16 14:46:11
    你有盾,我有矛。
    寻一方沃土
    使用道具 举报 回复
    发表于 2018-5-16 15:18:49
    了解一下
    使用道具 举报 回复
    发表于 2018-5-16 20:55:07
    您好,您的文章中的user-agent后面的内容多了一个空格,在执行requests时候会引起异常。。
    requests.exceptions.InvalidHeader: Invalid return character or leading space in header: User-Agent
    把空格去掉就好了
    该会员没有填写今日想说内容.
    使用道具 举报 回复
    感谢分享
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册