精华内容
下载资源
问答
  • 目录注:笔记大部分来源书本,仅供学习交流:【Python3反爬虫原理与绕过实战—韦世东】5、App反爬虫(1)App抓包软件(2)APK文件反编译 注:笔记大部分来源书本,仅供学习交流:【Python3反爬虫原理与绕过实战—韦...

    注:笔记大部分来源书本,仅供学习交流:【Python3反爬虫原理与绕过实战—韦世东】

    • 将爬虫的爬取过程分为网络请求,文本获取和数据提取3个部分。
    • 信息校验型反爬虫主要出现在网络请求阶段,这个阶段的反爬虫理念以预防为主要目的,尽可能拒绝反爬虫程序的请求。
    • 动态渲染、文本混淆则出现在文本获取及数据提取阶段,这个阶段的反爬虫理念以保护数据为主要目的,尽可能避免爬虫获得重要数据
    • 特征识别反爬虫通过客户端的特征、属性或用户行为特点来区分正常用户和爬虫程序的手段
    • APP网络传输和数据收发相对隐蔽,用户无法直接查看客户端发出的请求信息和服务端返回的响应内容,也无法直接查看App的代码,构成了反爬虫
    • python常见反爬虫类型(信息校验型、动态渲染、文本混淆、特征识别反爬虫等)

    5、App反爬虫

    (1)App抓包软件
    • 可以安装mitmproxy、charles、fillder三者之一对手机抓包
    • 原由:借助抓包工具能够查看App的网络请求信息,前提是App使用的网络传输协议是HTTP;如果App使用的网络传输协议是HTTPS,需要计算机和手机端同时安装证书;
    • 漏点:对于Android手机只有版本号小于7的Android系统才允许在证书得到信任后对App抓包,高版本的需要刷机(有风险);
    • 推荐:选择使用Android模拟器(一个能够在计算机上运行Android系统的应用软件),模拟器允许用户安装任意版本的Android系统,在接近真机体验的同时还不会造成任何设备的损坏;
    (2)APK文件反编译
    • 签名验证是防止恶意连接和避免服务器端被数据欺骗的有效方式之一,也是后端API常用的防护手段之一;
    • 高级语言的源程序需要通过编译生成可执行文件,编译就是将编程语言翻译成计算机能够识别和处理的二进制数据的过程;
    • 反编译又名计算机软件反向工程,指的是将软件应用还原成开发语言代码的过程;
    • APK(Android Application Package)即Android应用程序包,如果我们想要查看Android应用程序的源码,就需要使用反编译手段提取APK中的代码;
    • 借助反编译软件Apktool和JADX将APK反编译成代码
    • 示例:安装JADX软件>启动JADX软件后>点击“文件”菜单并在下方列表中选择“打开文件”>选择对应的APK文件>点击菜单栏“导航”_“搜索文本”>转到相应代码 ;JADX软件使用 , jadx下载与使用jadx安装包
    • App与服务器的通信使用的也是HTTP协议和WebSocket协议,所以基于这两种网络协议的反爬虫手段可以应用在App上,想要查看App的代码,必须将对应的APK文件反编译成代码
    (3)App代码混淆反爬虫
    • 代码混淆:将代码转换成一种功能等价但人类难以阅读和理解的文本。混淆指使用简短或冗长且无规律的字符替代代码中的方法、类和变量的名称,在缺乏注释和混淆映射表的情况下,工程师几乎无法阅读项目代码。
    • Anfroid代码混淆其实是对项目中的字符进行映射与压缩。混淆时会将代码中的类名、变量名和函数名用无意义的简短名称进行映射,如:
    # 映射示例:映射前 ————》 映射后
    seaking  ————》 e
    class indexview  ————》 class v
    
    • 这样能够保证反编译APK后得到的代码无法见名知意,令APK难以被逆向。Android可以使用ProGuard
    • ProGuard是Android官方提供的代码压缩和混淆工具,它会检测和移除封装应用中的未使用的类、字段、方法、属性以及自带代码库中的未使用项。ProGuard还可以优化字节码,移除未使用的代码指令,以及用短名称混淆其余的类和方法。
    • 每次构建混淆规则时,ProGuard会在/build/outputs/mapping/release/中输出下列文件。
    """这些文件便于开发者对混淆后的代码进行追踪和调试,如果mapping,txt该文本被覆盖或丢失,那么即使是项目开发者,也无法阅读混淆过后的代码"""
    dump.txt:说明APK中所有类文件的内部结构;
    mapping.txt:提供原始与混淆过的类、方法和字段名称之间的转换;
    seeds.txt:列出未进行混淆的类和成员;
    usage.txt:列出打算从APK文件中移除的代码
    
    • 代码混淆并不能阻止APK被反编译,但是可以有效提高他人阅读程序代码的难度,进而加强对数据的保护。代码中的字符串并不会被混淆
    (4)App应用加固知识扩展
    • 除了Android官方文档介绍的代码混淆方法外,App一般从防逆向、防调试、防篡改和防窃取的角度出发,使用DEX加密、LLVM混淆、内存监控等手段保护自己的源代码和资源
    • DEX加密的主要目的是防止App被反编译。JADX等反编译工具实际上是先将DEX文件编译成Smail语言的代码,再转换成class文件进行阅读和修改。DEX加密实际上是用代码对Android项目的Classes.dex文件进行加密,就像在原来的DEX上面加了一层壳一样,所以DEX加密又称为加壳。
    (5)App应用程序自动化测试工具Appium和Airtest
    • Appium提供了滑动、触摸(点击)、长按、模拟输入和文本提取等常见功能;
    • Airtest Project也提供了滑动、触摸(点击)、长按、模拟输入和文本提取等常见功能;它还支持“图码”混合编程

    6、验证码

    展开全文
  • 反爬虫

    2019-02-20 14:36:24
    1. 反爬虫模拟浏览器 什么是爬虫? 就是在互联网上一直爬行的蜘蛛, 如果遇到需要的资源, 那么它就会抓取下来(html内容); 模拟浏览器快速访问页面的内容. 浏览网页的过程中发生了什么? 浏览器输入...

    1. 反爬虫模拟浏览器

    1. 什么是爬虫?
      就是在互联网上一直爬行的蜘蛛, 如果遇到需要的资源, 那么它就会抓取下来(html内容);
      模拟浏览器快速访问页面的内容.
    2. 浏览网页的过程中发生了什么?
    • 浏览器输入http://www.baidu.com/bbs/;
    • 1). 根据配置的DNS获取www.baidu.com对应的主机IP;
    • 2). 根据端口号知道跟服务器的那个软件进行交互。
    • 3). 百度的服务器接收客户端请求:
    • 4). 给客户端主机一个响应(html内容) ----- html, css, js
    • 5). 浏览器根据html内容解释执行, 展示出华丽的页面;
    1. 常见模拟浏览器的信息:

    1.Android

    Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19
    Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
    Mozilla/5.0 (Linux; U; Android 2.2; en-gb; GT-P1000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

     2.Firefox
    

    Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
    Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0

    3.Google Chrome
    

    Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
    Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19

    4.iOS
    

    Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3

    代码案例

    import random
    import re
    
    from urllib.request import urlopen, Request
    from urllib.error import  URLError
    def get_content(url):
        """获取页面内容, 反爬虫之模拟浏览器"""
        # 防止一个浏览器访问频繁被封掉;
        user_agents = [
            "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0",
            "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19",
            "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0",
        ]
        try:
            # reqObj = Request(url, headers={'User-Agent': user_agent})
            reqObj = Request(url)
            # 动态添加爬虫请求的头部信息, 可以在实例化时指定, 也可以后续通过add—header方法添加
            reqObj.add_header('User-Agent', random.choice(user_agents))
        except URLError as e:
            print(e)
            return  None
        else:
            content = urlopen(reqObj).read().decode('utf-8').replace('\t', ' ')
            return  content
    
    
    def parser_content(content):
        """解析页面内容, 获取银行名称和官网URL地址"""
        pattern = r'<a href="(.*)" target="_blank"  style="color:#08619D">\s+(.*)\s+</a>'
        bankinfos = re.findall(pattern, content)
        if not bankinfos:
            raise  Exception("没有获取符合条件的信息")
        else:
            return  bankinfos
    
    def main():
        url = "http://www.cbrc.gov.cn/chinese/jrjg/index.html"
        content = get_content(url)
        bankinfos = parser_content(content)
        with open('doc/bankinfo.txt', 'w') as f:
            # ('http://www.cdb.com.cn/', '国家开发银行\r')
            for bank in bankinfos:
                name = bank[1].rstrip()
                url = bank[0]
                # 根据正则判断银行的url地址是否合法, 如果合法才写入文件;
                pattern =  r'^((https|http|ftp|rtsp|mms)?:\/\/)\S+'
                if re.search(pattern, url):
                    f.write('%s: %s\n' %(name, url))
                else:
                    print("%s无官方网站" %(name))
            print("写入完成....")
    
    
    if __name__ == '__main__':
        main()
    

    2. 反爬虫设置代理

    如何防止IP被封?
    - 设置延迟: time.sleep(random.randint(1,3))
    - 使用IP代理, 让其他的IP代替你的IP访问页面;

    如何获取代理IP?
    https://www.xicidaili.com/ (西刺代理网站提供)

    如何检测代理是否成功?
    http://httpbin.org/get

    代码案例

    # ProxyHandler ======> Request()
    # Opener ======  urlopen()
    # 安装Opener
    from urllib.request import ProxyHandler, build_opener, install_opener, urlopen
    from urllib import  request
    
    def use_proxy(proxies, url):
        # 1. 调用urllib.request.ProxyHandler
        proxy_support = ProxyHandler(proxies=proxies)
        # 2. Opener 类似于urlopen
        opener = build_opener(proxy_support)
        # 3. 安装Opener
        install_opener(opener)
    
        # user_agent =  "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
        # user_agent =  "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0"
        user_agent = 'Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3'
        # 模拟浏览器;
        opener.addheaders = [('User-agent', user_agent)]
        urlObj = urlopen(url)
        content = urlObj.read().decode('utf-8')
        return  content
    
    if __name__ == '__main__':
        url = 'http://httpbin.org/get'
        proxies = {'https': "111.177.178.167:9999", 'http': '114.249.118.221:9000'}
        use_proxy(proxies, url)
    
    展开全文
  • 转 爬虫与反爬虫套路

    2018-09-18 10:51:00
    爬虫需谨慎,你不知道的爬虫与反爬虫套路! 面试的时候,因为双方爬虫理念或者反爬虫理念不同,也很可能互不认可,影响自己的求职之路。本来程序员就有“文人相轻”的倾向,何况理念真的大不同。 2018-01-29 09:28...

    爬虫需谨慎,你不知道的爬虫与反爬虫套路!

    面试的时候,因为双方爬虫理念或者反爬虫理念不同,也很可能互不认可,影响自己的求职之路。本来程序员就有“文人相轻”的倾向,何况理念真的大不同。

    2018-01-29 09:28

    9月15日技术沙龙 | 与东华软件、AWS、京东金融、饿了么四位大咖探讨精准运维!

    爬虫与反爬虫,是一个很不阳光的行业。这里说的不阳光,有两个含义。

    第一是,这个行业是隐藏在地下的,一般很少被曝光出来。很多公司对外都不会宣称自己有爬虫团队,甚至隐瞒自己有反爬虫团队的事实。这可能是出于公司战略角度来看的,与技术无关。

    第二是,这个行业并不是一个很积极向上的行业。很多人在这个行业摸爬滚打了多年,积攒了大量的经验,但是悲哀的发现,这些经验很难兑换成闪光的简历。

    面试的时候,因为双方爬虫理念或者反爬虫理念不同,也很可能互不认可,影响自己的求职之路。本来程序员就有“文人相轻”的倾向,何况理念真的大不同。

    然而这就是程序员的宿命。不管这个行业有多么的不阳光,依然无法阻挡大量的人进入这个行业,因为有公司的需求。

    那么,公司到底有什么样的需求,导致了我们真的需要爬虫/反爬虫呢?

    反爬虫很好理解,有了爬虫我们自然要反爬虫。对于程序员来说,哪怕仅仅是出于“我就是要证明我技术比你好”的目的,也会去做。

    对于公司来说,意义更加重大,最少,也能降低服务器负载,光凭这一点,反爬虫就有充足的生存价值。

    那么爬虫呢?最早的爬虫起源于搜索引擎。搜索引擎是善意的爬虫,可以检索你的一切信息,并提供给其他用户访问。为此他们还专门定义了 robots.txt 文件,作为君子协定,这是一个双赢的局面。

    然而事情很快被一些人破坏了,爬虫很快就变的不再“君子”了。后来有了“大数据”,无数的媒体鼓吹大数据是未来的趋势,吸引了一批又一批的炮灰去创办大数据公司。

    这些人手头根本没有大数据,他们的数据只要用一个 U 盘就可以装的下,怎么好意思叫大数据呢?

    这么点数据根本忽悠不了投资者,于是他们开始写爬虫,拼命地爬取各个公司的数据。很快他们的数据,就无法用一个 U 盘装下了。这个时候终于可以休息休息,然后出去吹嘘融资啦。

    然而可悲的是,大容量 U 盘不断地在发布,他们总是在拼命地追赶存储增加的速度。

    以上是爬虫与反爬虫的历史,下面通过四个方面深入谈下爬虫与反爬虫:

    • 爬虫反爬虫运行现状
    • 爬虫反爬虫技术现状
    • 爬虫反爬虫套路现状
    • 爬虫反爬虫的未来

    爬虫反爬虫运行现状

    电子商务行业的爬虫与反爬虫更有趣一些,最初的爬虫需求来源于比价。

    这是某些电商网站的核心业务,大家买商品的时候,是一个价格敏感型用户的话,很可能用过网上的比价功能(真心很好用啊)。

    毫无悬念,他们会使用爬虫技术来爬取所有相关电商的价格。他们的爬虫还是比较温柔的,对大家的服务器不会造成太大的压力。

    然而,这并不意味着大家喜欢被他爬取,毕竟这对其他电商是不利的,于是需要通过技术手段来做反爬虫。

    按照技术人员的想法,对方用技术怼过来,我们就要用技术怼回去,不能怂啊。这个想法是很好的,但是实际应用起来根本不是这么回事。

    诚然,技术是很重要的,但是实际操作上,更重要的是套路。谁的套路更深,谁就能玩弄对方于鼓掌之中。

    谁的套路不行,有再好的技术,也只能被耍的团团转。这个虽然有点伤技术人员的自尊,然而,我们也不是第一天被伤自尊了。大家应该早就习惯了吧。

    真实世界的爬虫比例

    大家应该听过一句话吧,大概意思是说,整个互联网上大概有 50% 以上的流量其实是爬虫。

    第一次听这句话的时候,我还不是很相信,我觉得这个说法实在是太夸张了。怎么可能爬虫比人还多呢? 爬虫毕竟只是个辅助而已。

    现在做了这么久的反爬虫,我依然觉得这句话太夸张了。50%?你在逗我?就这么少的量?

    举个例子,某公司,某个页面的接口,每分钟访问量是 1.2 万左右,这里面有多少是正常用户呢?50%?60%?还是?

    正确答案是:500 以下。也就是说,一个单独的页面,12000 的访问量里,有 500 是正常用户,其余是爬虫。

    注意,统计爬虫的时候,考虑到你不可能识别出所有的爬虫,因此,这 500 个用户里面,其实还隐藏着一些爬虫。

    那么爬虫率大概是:(12000-500)/12000=95.8%。

    这个数字你猜到了吗?这么大的爬虫量,这么少的用户量,大家到底是在干什么?是什么原因导致了明明是百人级别的生意,却需要万级别的爬虫来做辅助? 95% 以上,19 保 1?

    答案可能会相当令人喷饭,这些爬虫大部分是由于决策失误导致的。

    哭笑不得的决策思路

    举个例子,这个世界存在 3 家公司,售卖相同的电商产品,三家公司的名字分别是 A,B,C。

    这个时候,客户去 A 公司查询了下某商品的价格,看了下发现价格不好,于是他不打算买了,他对整个行业的订单贡献为 0。

    然而 A 公司的后台会检测到,我们有个客户流失了,原因是他来查询了一个商品,这个商品我们的价格不好,没关系,我去爬爬别人试试。

    于是他分别爬取了 B 公司和 C 公司,B 公司的后台检测到有人来查询价格,但是呢,最终没有下单。

    他会认为,嗯,我们流失了一个客户。怎么办呢?我可以爬爬看,别人什么价格。

    于是他爬取了 A 和 C,C 公司的后台检测到有人来查询价格。。。。。

    过了一段时间,三家公司的服务器分别报警,访问量过高。三家公司的 CTO 也很纳闷,没有生成任何订单啊,怎么访问量这么高?

    一定是其他两家禽兽写的爬虫没有限制好频率。妈的,老子要报仇!于是分别做反爬虫,不让对方抓自己的数据。

    然后进一步强化自己的爬虫团队抓别人的数据。一定要做到:宁叫我抓天下人,休叫天下人抓我。

    然后,做反爬虫的就要加班天天研究如何拦截爬虫,做爬虫的被拦截了,就要天天研究如何破解反爬虫策略。

    大家就这么把资源全都浪费在没用的地方了,直到大家合并了,才会心平气和的坐下来谈谈,都少抓点。

    最近国内的公司有大量的合并,我猜这种“心平气和”应该不少吧?

    爬虫反爬虫技术现状

    下面我们谈谈,爬虫和反爬虫分别都是怎么做的。

    为 Python 平反

    首先是爬虫,爬虫教程你到处都可以搜的到,大部分是 Python 写的。

    我曾经在一篇文章提到过:用 Python 写的爬虫是最薄弱的,因为天生并不适合破解反爬虫逻辑,因为反爬虫都是用 JavaScript 来处理。

    然而慢慢的,我发现这个理解有点问题(当然我如果说我当时是出于工作需要而有意黑 Python,你们信吗。。。)。

    Python 的确不适合写反爬虫逻辑,但是 Python 是一门胶水语言,他适合捆绑任何一种框架。

    而反爬虫策略经常会变化的翻天覆地,需要对代码进行大刀阔斧的重构,甚至重写。这种情况下,Python 不失为一种合适的解决方案。 

    举个例子,你之前是用 selenium 爬取对方的站点,后来你发现自己被封了,而且封锁方式十分隐蔽,完全搞不清到底是如何封的,你会怎么办?你会跟踪 selenium 的源码来找到出错的地方吗?

    你不会,你只会换个框架,用另一种方式来爬取,然后你就把两个框架都浅尝辄止地用了下,一个都没有深入研究过。

    因为没等你研究好,也许人家又换方式了,你不得不再找个框架来爬取。毕竟,老板等着明天早上开会要数据呢。

    老板一般都是早上八九点开会,所以你七点之前必须搞定。等你厌倦了,打算换个工作的时候,简历上又只能写“了解 n 个框架的使用”,仅此而已。 

    这就是爬虫工程师的宿命,爬虫工程师比外包还可怜。外包虽然不容易积累技术,但是好歹有正常上下班时间,爬虫工程师连这个权利都没有。 

    然而反爬虫工程师就不可怜了吗?也不是的,反爬虫有个天生的死穴,就是:误伤率。 

    无法绕开的误伤率

    我们首先谈谈,面对对方的爬虫,你的第一反应是什么?

    如果限定时间的话,大部分人给我的答案都是:封杀对方的 IP。

    然而,问题就出在,IP 不是每人一个的,大的公司有出口 IP,ISP 有的时候会劫持流量让你们走代理,有的人天生喜欢挂代理,有的人为了FQ 24 小时挂 VPN。

    最坑的是,现在是移动互联网时代,你如果封了一个 IP?不好意思,这是中国联通的 4G 网络,5 分钟之前还是别人,5 分钟之后就换人了哦!

    因此,封 IP 的误伤指数最高,并且,效果又是最差的,因为现在即使是最菜的新手,也知道用代理池了。

    你们可以去淘宝看下,几十万的代理价值多少钱?我们就不谈到处都有的免费代理了。

    也有人说:我可以扫描对方端口,如果开放了代理端口,那就意味着是个代理,我就可以封杀了呀。 

    事实是残酷的,我曾经封杀过一个 IP,因为他开放了一个代理端口,而且是个很小众的代理端口。

    不出一天就有人来报事件,说我们一个分公司被拦截了,我一查 IP,还真是我封的 IP。

    我就很郁闷地问他们 IT,开这个端口干什么?他说做邮件服务器啊。我说为啥要用这么奇怪的端口?他说,这不是怕别人猜出来么?我就随便取了个。

    扫描端口的进阶版,还有一种方式,就是去订单库查找这个 IP 是否下过订单,如果没有,那么就是安全的;如果有,那就不安全,有很多网站会使用这个方法。

    然而这只是一种自欺欺人的办法而已,只需要下一单,就可以永久洗白自己的 IP,天下还有比这更便宜的生意吗?

    因此,封 IP,以及封 IP 的进阶版:扫描端口再封 IP,都是没用的。根本不要考虑从 IP 下手,因为对手会用大量的时间考虑如何躲避 IP 封锁,你干嘛和人家硬碰呢?这没有任何意义。

    那么,下一步你会考虑到什么?很多站点的工程师会考虑:既然没办法阻止对方,那我就让它变的不可读吧。我会用图片来渲染关键信息,比如价格。这样,人眼可见,机器识别不出来。 

    这个想法曾经是正确的,然而,坑爹的技术发展,带给我们一个坑爹的技术,叫机器学习。顺便带动了一个行业的迅猛发展,叫 OCR。

    很快,识别图像就不再是任何难题了,甚至连人眼都很难识别的验证码,有的 OCR 都能搞定,比我肉眼识别率都高。更何况,现在有了打码平台,用资本都可以搞定,都不需要技术。

    那么,下一步你会考虑什么?这个时候,后端工程师已经没有太多的办法可以搞了。 

    不过后端搞不定的事情,一般都推给前端啊,前端从来都是后端搞不定问题时的背锅侠。

    多少年来我们都是这么过来的,前端工程师这个时候就要勇敢地站出来了:“都不要得瑟了,来比比谁的前端知识牛逼,你牛逼我就让你爬。”

    我不知道这篇文章的读者里有多少前端工程师,我只是想顺便提一下:你们以后将会是更加抢手的人才。

    前端工程师的逆袭

    我们知道,一个数据要显示到前端,不仅仅是后端输出就完事了,前端要做大量的事情,比如取到 json 之后,至少要用 template 转成 html 吧?

    这已经是步骤最少最简单的了,然后你总要用 css 渲染下吧? 这也不是什么难事。

    等等,你还记得自己第一次做这个事情的时候的经历吗?真的,不是什么难事吗?

    有没有经历过,一个 html 标签拼错,或者没有闭合,导致页面错乱?一个 css 没弄好,导致整个页面都不知道飘到哪去了?

    这些事情,你是不是很想让别人再经历一次?

    这件事情充分说明了:让一个资深的前端工程师来把事情搞复杂一点,对方如果配备了资深前端工程师来破解,也需要耗费 3 倍以上的时间。

    毕竟是读别人的代码,别人写代码用了一分钟,你总是要读两分钟,然后骂一分钟吧?这已经算很少的了。如果对方没有配备前端工程师。。。那么经过一段时间,他们会成长为前端工程师。

    之后,由于前端工程师的待遇比爬虫工程师稍好一些,他们很快会离职做前端,既缓解了前端人才缺口,又可以让对方缺人,重招。

    而他们一般是招后端做爬虫,这些人需要再接受一次折磨,再次成长为前端工程师,这不是很好的事情吗?

    所以,如果你手下的爬虫工程师离职率很高,请仔细思考下,是不是自己的招聘方向有问题。

    那么前端最坑爹的技术是什么呢?前端最坑爹的,也是最强大的,就是我们的:JavaScript。

    JavaScript 有大量的花样可以玩,毫不夸张的说,一周换一个 feature(Bug)给对方学习,一年不带重样的。这个时候你就相当于一个面试官,对方要通过你的面试才行。

    举个例子,在 Array.prototyp e里,有没有 map 啊?什么时候有啊?你说你是 xx 浏览器,那你这个应该是有还是应该没有啊?你说这个可以有啊?可是这个真没有啊。

    那[]能不能在 string 里面获取字符啊?哪个浏览器可以哪个不行啊?咦!你为什么支持 WebKit 前缀啊?等等,刚刚你还支持怎么现在不支持了啊?你声明的不对啊。

    这些对于前端都是简单的知识,已经习以为常了,但是对于后端来说简直就是噩梦。

    然而,前端人员自己作死,研究出了一个东西,叫:Nodejs。基于 V8,秒杀所有的 js 运行。

    不过 Nodejs 实现了大量的 feature,都是浏览器不存在的,你随随便便访问一些东西(比如你为什么会支持 process.exit),都会把 node 坑的好惨好惨。

    而且浏览器里的 js,你拉到后台用 Nodejs 跑,你是不是想到了什么安全漏洞?这个是不是叫,代码与数据混合?如果他在 js 里跑点恶心的代码,浏览器不支持但是 node 支持怎么办?

    还好,爬虫工程师还有 phantomjs。但是,你怎么没有定位啊? 哈哈,你终于模拟出了定位。

    但是不对啊,根据我当前设置的安全策略你现在不应该能定位啊?你是怎么定出来的?连 phantomjs 的作者自己都维护不下去了,你真的愿意继续用吗?

    当然了,最终,所有的反爬虫策略都逃不脱被破解的命运。但是这需要时间,反爬虫需要做的就是频繁发布,拖垮对方。

    如果对方两天可以破解你的系统,你就一天一发布,那么你就是安全的。这个系统甚至可以改名叫做“每天一道反爬题,轻轻松松学前端”。

    误伤,还是误伤

    这又回到了我们开始提到的“误伤率”的问题了。我们知道,发布越频繁,出问题的概率越高。那么,如何在频繁发布的情况下,还能做到少出问题呢?

    此外还有一个问题,我们写了大量的“不可读代码”给对方,的确能给对方造成大量的压力,但是,这些代码我们自己也要维护啊。

    如果有一天忽然说,没人爬我们了,你们把代码下线掉吧。这个时候写代码的人已经不在了,你们怎么知道如何下线这些代码呢?

    这两个问题我暂时不能公布我们的做法,但是大家都是聪明人,应该都是有自己的方案的,软件行业之所以忙的不得了,无非就是在折腾两件事,一个是如何将代码拆分开,一个是如何将代码合并起来。

    关于误伤率,我只提一个小的 tip:你可以只开启反爬虫,但是不拦截,先放着,发统计信息给自己,相当于模拟演练。

    等统计的差不多了,发现真的开启了也不会有什么问题,那就开启拦截或者开启造假。

    这里就引发了一个问题,往往一个公司的各个频道,爬取难度是不一样的。原因就是,误伤检测这种东西与业务相关,公司的基础部门很难做出通用的,只能各个部门自己做,甚至有的部门做了有的没做。

    因此引发了爬虫界一个奇葩的通用做法:如果 PC 页面爬不到,就去 H5 试试,如果 H5 很麻烦,就去 PC 碰碰运气。

    爬虫反爬虫套路现状

    那么一旦有发现对方数据造假怎么办?

    早期的时候,大家都是要抽查数据,通过数据来检测对方是否有造假,这个需要人工核对,成本非常高。

    可是那已经是洪荒时代的事情了。如果你们公司还在通过这种方式来检测,说明你们的技术还比较落伍。

    之前我们的竞争对手是这么干的:他们会抓取我们两次,一次是他们解密出来 key 之后,用正经方式来抓取,这次的结果定为 A。

    一次是不带 key,直接来抓,这次的结果定为 B。根据前文描述,我们可以知道,B 一定是错误的。那么如果 A 与 B 相等,说明自己中招了,这个时候会停掉爬虫,重新破解。

    不要回应

    所以之前有一篇关于爬虫的文章,说如何破解我们的。一直有人要我回复下,我一直觉得没什么可以回复的。

    第一,反爬虫被破解了是正常的。这个世界上有个万能的爬虫手段,叫“人肉爬虫”。

    假设我们就是有钱,在印度开个分公司,每天雇便宜的劳动力用鼠标直接来点,你能拿我怎么办?

    第二,我们真正关心的是后续的这些套路。而我读了那篇文章,发现只是调用了selenium并且拿到了结果,就认为自己成功了。

    我相信你读到这里,应该已经明白为什么我不愿意回复了。我们最重要的是工作,而不是谁打谁的脸。

    大家如果经常混技术社区就会发现,每天热衷于打别人脸的,一般技术都不是很好。

    当然这并不代表我们技术天下第一什么的,我们每天面对大量的爬虫,还是遇到过很多高手的。

    就如同武侠小说里一样,高手一般都比较低调,他们默默地拿走数据,很难被发现,而且频率极低,不会影响我们的考评。你们应该明白,这是智商与情商兼具的高手了。

    我们还碰到拉走我们 js,砍掉无用的部分直接解出 key,相当高效不拖泥带水的爬虫,一点废请求都没有(相比某些爬虫教程,总是教你多访问,写没用的 url 免得被发现,真的不知道高到哪里去了。这样做除了会导致机器报警,导致对方加班封锁以外,对你自己没有任何好处)。

    而我们能发现这一点仅仅是是因为他低调地写了一篇博客,通篇只介绍技术,没有提任何没用的东西。

    这里我只是顺便发了点小牢骚,就是希望后续不要总是有人让我回应一些关于爬虫的文章。

    线下我认识很多爬虫工程师,水平真的很好,也真的很低调(不然你以为我是怎么知道如何对付爬虫的。。。),大家都是一起混的,不会产生“一定要互相打脸”的情绪。

    进化

    早期我们和竞争对手打的时候,双方的技术都比较初级。后来慢慢的,爬虫在升级,反爬虫也在升级,这个我们称为“进化”。

    我们曾经给对方放过水,来试图拖慢他们的进化速度,然而,效果不是特别理想。爬虫是否进化,取决于爬虫工程师自己的 KPI,而不是反爬虫的进化速度。

    后期打到白热化的时候,用的技术越来越匪夷所思。举个例子,很多人会提,做反爬虫会用到 canvas 指纹,并认为是最高境界。

    其实这个对于反爬虫来说也只是个辅助,canvas 指纹的含义是,因为不同硬件对 canvas 支持不同,因此你只要画一个很复杂的 canvas,那么得出的 image,总是存在像素级别的误差。

    考虑到爬虫代码都是统一的,就算起 selenium,也是 Ghost 的,因此指纹一般都是一致的,因此绕过几率非常低。

    但是!这个东西天生有两个缺陷。

    第一是,无法验证合法性。当然了,你可以用非对称加密来保证合法,但是这个并不靠谱。

    其次,canvas 的冲突概率非常高,远远不是作者宣称的那样,冲突率极低。也许在国外冲突是比较低,因为国外的语言比较多。但是国内公司通常是 IT 统一装机,无论是软件还是硬件都惊人的一致。

    我们测试 canvas 指纹的时候,在携程内部随便找了 20 多台机器,得出的指纹都完全一样,一丁点差别都没有。因此,有些“高级技巧”一点都不实用。

    法律途径

    此外就是大家可能都考虑过的:爬虫违法吗?能起诉对方让对方不爬吗?法务给的答案到是很干脆,可以,前提是证据。

    遗憾的是,这个世界上大部分的爬虫爬取数据是不会公布到自己网站的,只是用于自己的数据分析。

    因此,即使有一些关于爬虫的官司做为先例,并且已经打完了,依然对我们没有任何帮助。反爬虫,在对方足够低调的情况下,注定还是个技术活。

    搞事情,立 Flag

    到了后来,我们已经不再局限于打打技术了,反爬虫的代码里我们经常埋点小彩蛋给对方,比如写点注释给对方。双方通过互相交战,频繁发布,居然聊的挺 high 的。

    比如问问对方,北京房价是不是很高啊?对方回应,欧巴,我可是凭本事吃饭哦。继续问,摇到号了吗?诸如此类等等。

    这样的事情你来我往的,很容易动摇对方的军心,还是很有作用的。试想一下,如果你的爬虫工程师在大年三十还苦逼加班的时候,看到对方留言说自己拿到了 n 个月的年终奖,你觉得你的工程师,离辞职还远吗?

    最后,我们终于搞出了大动作,觉得一定可以坑对方很久了。我们还特意去一家小火锅店吃了一顿,庆祝一下,准备明天上线。

    大家都知道,一般立 Flag 的下场都比较惨的,两个小时的自助火锅,我们刚吃五分钟,就得到了我们投资竞争对手的消息。

    后面的一个多小时,团队气氛都很尴尬,谁也说不出什么话。我们组有个实习生,后来鼓足勇气问了我一个问题:“我还能留下来吗?”

    毕竟,大部分情况下,技术还是要屈服于资本的力量。

    爬虫反爬虫的未来

    与竞争对手和解之后,我们去拜访对方,大家坐在了一起。之前网上自称妹子的,一个个都是五大三粗的汉子,这让我们相当绝望。

    在场唯一的一个妹子还是我们自己带过去的(就是上面提到的实习生),感觉套路了这么久,最终还是被对方套路了。

    好在,吃的喝的都很好,大家玩的还是比较 high 的。后续就是和平年代啦,大家不打仗了,反爬虫的逻辑扔在那做个防御,然后就开放白名单允许对方爬取了。

    群里经常叫的就是:xxx 你怎么频率这么高,xxx 你为什么这个接口没给我开放,为什么我爬的东西不对我靠你是不是把我封了啊,诸如此类的。

    和平年代的反爬虫比战争年代还难做,因为战争年代,误伤率只要不是太高,公司就可以接受。

    和平年代大家不能搞事情,误伤率稍稍多一点,就会有人叫:好好的不赚钱,瞎搞什么搞。

    此外,战争年代只要不拦截用户,就不算误伤。和平年代还要考虑白名单,拦截了合作伙伴也是误伤,因此各方面会更保守一些。

    不过,总体来说还是和平年代比较 happy,毕竟,谁会喜欢没事加班玩呢。

    然而和平持续的不是很久,很快就有了新的竞争对手选择爬虫来与我们打,毕竟,这是一个利益驱使的世界。

    只要有大量的利润,资本家就会杀人放火,这不是我们这些技术人员可以决定的,我们希望天下无虫,但是我们又有什么权利呢。

    好在,这样可以催生更多的职位,顺便提高大家的身价,也算是个好事情吧。

    转载于:https://www.cnblogs.com/yibutian/p/9667641.html

    展开全文
  • 前言不多逼逼,这个安卓社区就是酷安,以前想过要爬这软件,但是都忘了,几天前抓了下它的包,发现请求 headers 里有一个 token 验证,果断就给破了分析过程先抓个包...
        

    前言

    不多逼逼,这个安卓社区就是酷安,以前想过要爬这软件,但是都忘了,几天前抓了下它的包,发现请求 headers 里有一个 token 验证,果断就给破了

    分析过程

    先抓个包

    640?wx_fmt=png

    可以看到其中有个请求头 X-App-Token,这就是验证,至于X-App-Device这玩意儿应该是获取你手机信息的,不管它,先看看软件源代码,找到请求方法

    1、jeb分析

    没加固,好像也没混淆,舒服

    640?wx_fmt=jpeg

    搜索关键字:X-App-Token

    640?wx_fmt=png

    很明显找到了我们要的东西了,(jeb3.0按tab键反编译)

    640?wx_fmt=png

    这个 X-App-Token 是变量 v21,v21是,一个AuthUtils类里的getAS方法返回的

    640?wx_fmt=jpeg

    640?wx_fmt=jpeg

    跟进可以发现这是一个native方法,lib是native-lib

    640?wx_fmt=png

    到这里就没法用jeb分析了,我们先看看参数2 deviceId 是个什么玩意儿

    可以看到是一个 SystemUtils 类里的 getDeviceID方法返回的,传入一个context参数

    640?wx_fmt=png

    我们去app的application hook这个方法,在里面输出一下这个device id

    640?wx_fmt=png

    我找到一个代码量最少的方法,这样可以帮助我们不破坏原逻辑的情况下hook

    640?wx_fmt=png

    hook的代码很简单

    Java.perform(function() {	
        var CoolMarket = Java.use('com.coolapk.market.CoolMarketApplication');	
        CoolMarket.onLog.implementation = function() {	
            var deviceId = Java.use('com.coolapk.market.util.SystemUtils').getDeviceId(this);	
            console.log('Device Id: ', deviceId);	
            var app_token = Java.use('com.coolapk.market.util.AuthUtils').getAS(this, deviceId);	
            console.log('App Token: ', app_token);	
            console.log('----------');	
            return 1;	
        }	
    })

    拿到 deviceId 后分析so

    ida分析

    解压apk拿到 native-lib.so,用ida打开

    640?wx_fmt=png

    我们已知方法名和参数个数,那么就先搜索方法名

    Function Window 按 option+t 搜索 getAS,可以看到,毛都没有

    640?wx_fmt=png

    640?wx_fmt=png

    那我们就到 IDA View 里搜索,快捷键一样

    640?wx_fmt=png

    找到了这个,参数是两个,但这个不是方法,没法 F5 反编译

    640?wx_fmt=png

     不瞒你们,这个DCB是个什么玩意儿我也不知道.

    但是我在 Function Window 瞎翻想找一些我能看得懂的方法名时看到了这个

    640?wx_fmt=png

    我一看,这个方法好像和 getAS 有点关系就顺手 F5 了

    简单看了看里面的代码,我估计我要找的是这个方法,为什么是这个方法而不是其他的

    我分析了 X-App-Token 这个验证的组成,它长这样:f2c29a109fde487e9350d3e6b881036a8513efac-09ea-3709-b214-95b366f1a1850x5d024391

    我之前就获取到了我的 Device Id,我无意间看到了我的 device id就在里面,然后我把它拆分成了这样:

    • f2c29a109fde487e9350d3e6b881036a

    • 8513efac-09ea-3709-b214-95b366f1a185

    • 0x5d024391

    第一项很明显是md5密文,第二部分就是device id,最后是一个十六进制,不知道什么玩意儿,但我在那个 getAuthString 代码里看到了这段

    640?wx_fmt=png

    这是一个字符串拼接的过程,其中 v82 是md5密文,也是字符串的头部,后面接着是 v43(device id)、字符串0x、最后是 hex_time (这是我改了后的命名),所以我就能确定这个方法就是我想要的;

    上面说的也就是接下来要分析的,其中那个十六进制的东西就是时间戳,我们只需要分析出md5是怎么来的就行了,我们知道md5是 v61v61 的加密代码在这

    640?wx_fmt=png

    加密的内容是v58,v58是一个经过base64编码后的变量

    640?wx_fmt=png

    我懒得去看它是什么了,我直接hook了md5加密类,有三个方法,一个是md5(应该是构造方法把)、update、finalize,hook 代码如下

    // 这里算基址是学的四哥的	
    var JNI_LOAD_POINTER = Module.getExportByName('libnative-lib.so', 'JNI_OnLoad'); // 首先拿到 JNI_OnLoad方法的地址	
    // 这里减去的是从so中得到的JNI_OnLoad的地址 0x31A04	
    var BASE_ADDR = parseInt(JNI_LOAD_POINTER) - parseInt('0x31A04'); // 用程序运行中JNI_OnLoad的绝对地址减去它的相对地址得到基址	
    // MD5::MD5	
    Java.perform(function() {	
        //  然后用基址 + 要hook的方法的相对地址就得到了绝对地址	
        var hookpointer = '0x' + parseInt(BASE_ADDR + parseInt('0x32168')).toString(16) // 获取要hook方法的地址	
        var pointer = new NativePointer(hookpointer) // 根据方法地址构建NativePointer	
        console.log('[MD5::MD5] hook pointer: ', pointer)	
        var arg0, arg1, arg2, arg3	
        Interceptor.attach(pointer, {	
                onEnter: function(args) {	
                    arg0 = args[0]	
                    arg1 = args[1]	
                    console.log('\n')	
                    console.log('=====> [MD5::MD5] -> [方法调用前]')	
                    console.log('参数1: {0} => {1}'.format(arg0, Memory.readCString(arg0))) // Memory.readCString 是读取地址为字符串,类似的还有readUtf8String、readUtf16String等	
                    console.log('参数2: {0} => {1}'.format(arg1, Memory.readCString(arg1)))	
                    console.log('\n')	
                },	
                onLeave: function(retval) {	
                    console.log('\n')	
                    console.log('=====> [MD5::MD5] -> [方法调用后]:')	
                    console.log('返回值: ', retval)	
                    console.log('参数1: {0} => {1}'.format(arg0, Memory.readCString(arg0)))	
                    console.log('参数2: {0} => {1}'.format(arg1, Memory.readCString(arg1)))	
                    console.log('\n')	
                }	
            }   	
        )	
    })	
    // MD5::update	
    Java.perform(function() {	
        var hookpointer = '0x' + parseInt(BASE_ADDR + parseInt('0x329AC')).toString(16) // 获取要hook方法的地址	
        var pointer = new NativePointer(hookpointer) // 根据方法地址构建NativePointer	
        console.log('[MD5::update] hook pointer: ', pointer)	
        var arg0, arg1, arg2, arg3	
        Interceptor.attach(pointer, {	
                onEnter: function(args) {	
                    arg0 = args[0]	
                    arg1 = args[1]	
                    arg2 = args[2]	
                    console.log('\n')	
                    console.log('=====> [MD5::update] -> [方法调用前]')	
                    console.log('参数1: {0} => {1}'.format(arg0, Memory.readCString(arg0)))	
                    console.log('参数2: {0} => {1}'.format(arg1, Memory.readCString(arg1)))	
                    console.log('参数3: {0} => {1}'.format(arg2, Memory.readCString(arg2)))	
                    console.log('\n')	
                },	
                onLeave: function(retval) {	
                    console.log('\n')	
                    console.log('=====> [MD5::update] -> [方法调用后]:')	
                    console.log('返回值: ', retval)	
                    console.log('参数1: {0} => {1}'.format(arg0, Memory.readCString(arg0)))	
                    console.log('参数2: {0} => {1}'.format(arg1, Memory.readCString(arg1)))	
                    console.log('参数3: {0} => {1}'.format(arg2, Memory.readCString(arg2)))	
                    console.log('\n')	
                }	
            }   	
        )	
    })	
    // MD5::finalize	
    Java.perform(function() {	
        var hookpointer = '0x' + parseInt(BASE_ADDR + parseInt('0x321C4')).toString(16) // 获取要hook方法的地址	
        var pointer = new NativePointer(hookpointer) // 根据方法地址构建NativePointer	
        console.log('[MD5::finalize] hook pointer: ', pointer)	
        var arg0, arg1, arg2, arg3	
        Interceptor.attach(pointer, {	
                onEnter: function(args) {	
                    arg0 = args[0]	
                    arg1 = args[1]	
                    arg2 = args[2]	
                    arg3 = args[3]	
                    console.log('\n')	
                    console.log('=====> [MD5::finalize] -> [方法调用前]')	
                    console.log('参数1: {0} => {1}'.format(arg0, Memory.readCString(arg0)))	
                    console.log('参数2: {0} => {1}'.format(arg1, Memory.readCString(arg1)))	
                    console.log('参数3: {0} => {1}'.format(arg2, Memory.readCString(arg2)))	
                    console.log('参数4: {0} => {1}'.format(arg3, Memory.readCString(arg3)))	
                    console.log('\n')	
                },	
                onLeave: function(retval) {	
                    console.log('\n')	
                    console.log('=====> [MD5::finalize] -> [方法调用后]:')	
                    console.log('返回值: ', retval)	
                    console.log('参数1: {0} => {1}'.format(arg0, Memory.readCString(arg0)))	
                    console.log('参数2: {0} => {1}'.format(arg1, Memory.readCString(arg1)))	
                    console.log('参数3: {0} => {1}'.format(arg2, Memory.readCString(arg2)))	
                    console.log('参数4: {0} => {1}'.format(arg3, Memory.readCString(arg3)))	
                    console.log('\n')	
                }	
            }   	
        )	
    })

    运行后得到了那个base64编码过的内容:

    dG9rZW46Ly9jb20uY29vbGFway5tYXJrZXQvYzY3ZWY1OTQzNzg0ZDA5NzUwZGNmYmIzMTAyMGYwYWI/MzgyMzIxNWQ5MWQyOWQ5ODg3ZWJjMDVmMGQ3ZmQzMGQkODUxM2VmYWMtMDllYS0zNzA5LWIyMTQtOTViMzY2ZjFhMTg1JmNvbS5jb29sYXBrLm1hcmtldA==

    经过解码后:

    token://com.coolapk.market/c67ef5943784d09750dcfbb31020f0ab?3823215d91d29d9887ebc05f0d7fd30d$8513efac-09ea-3709-b214-95b366f1a185&com.coolapk.market

    在我看到这段代码后,注:这里的第三个注释里说的猜测是我的错,我一开始分析的时候因为不知道那个字符串是固定的就以为是"?",现在实锤了,截图的时候忘了改

    640?wx_fmt=png

    上面解码后的内容可以拆分为:

    token://com.coolapk.market/c67ef5943784d09750dcfbb31020f0ab?3823215d91d29d9887ebc05f0d7fd30d

    $

    8513efac-09ea-3709-b214-95b366f1a185

    &

    com.coolapk.market

    据我分析,只需要的到第二部分的md5加密的来历就行了,继续分析,找到了加密的地方

    640?wx_fmt=png

    根据这图的画线,可以明确的知道这md5就是时间戳,在我hook的输出中也可以看到这个就是时间戳

    640?wx_fmt=png

    640?wx_fmt=png

    至于 token://com.coolapk.market/c67ef5943784d09750dcfbb31020f0ab? 这个是不变的

    结论

    token://com.coolapk.market/c67ef5943784d09750dcfbb31020f0ab? + md5加密后的时间戳 + $ + device id + & + com.coolapk.market(包名),将其md5加密后得到 第一部分

    token的来历就是:第一部分 + deivce id + 0x + 十六进制转换后的时间戳

    简单的测试代码:

    import requests	
    import time	
    import hashlib	
    import base64	
    DEVICE_ID = "8513efac-09ea-3709-b214-95b366f1a185"	
    def get_app_token():	
        t = int(time.time())	
        hex_t = hex(t)	
        # 时间戳加密	
        md5_t = hashlib.md5(str(t).encode('utf-8')).hexdigest()	
        # 不知道什么鬼字符串拼接	
        a = 'token://com.coolapk.market/c67ef5943784d09750dcfbb31020f0ab?{}${}&com.coolapk.market' \	
            .format(md5_t, DEVICE_ID)	
        # 不知道什么鬼字符串拼接 后的字符串再次加密	
        md5_a = hashlib.md5(base64.b64encode(a.encode('utf-8'))).hexdigest()	
        token = '{}{}{}'.format(md5_a, DEVICE_ID, hex_t)	
        print(token)	
        return token	
    def request():	
        url = "https://api.coolapk.com/v6/main/indexV8?page=1"	
        headers = {	
            "User-Agent": "Dalvik/2.1.0 (Linux; U; Android 9; MI 8 SE MIUI/9.5.9) (#Build; Xiaomi; MI 8 SE; PKQ1.181121.001; 9) +CoolMarket/9.2.2-1905301"	
        }	
        headers = {	
            "User-Agent": "Dalvik/2.1.0 (Linux; U; Android 9; MI 8 SE MIUI/9.5.9) (#Build; Xiaomi; MI 8 SE; PKQ1.181121.001; 9) +CoolMarket/9.2.2-1905301",	
            "X-App-Id": "com.coolapk.market",	
            "X-Requested-With": "XMLHttpRequest",	
            "X-Sdk-Int": "28",	
            "X-Sdk-Locale": "zh-CN",	
            "X-Api-Version": "9",	
            "X-App-Version": "9.2.2",	
            "X-App-Code": "1903501",	
            "X-App-Device": "QRTBCOgkUTgsTat9WYphFI7kWbvFWaYByO1YjOCdjOxAjOxEkOFJjODlDI7ATNxMjM5MTOxcjMwAjN0AyOxEjNwgDNxITM2kDMzcTOgsTZzkTZlJ2MwUDNhJ2MyYzM",	
            "Host": "api.coolapk.com",	
            "X-Dark-Mode": "0",	
            "X-App-Token": get_app_token(),	
        }	
        resp = requests.get(url, headers=headers)	
        print(resp.text)	
    if __name__ == '__main__':	
        request()

    最后

    代码啥的都提交到Github了,CoolapkTokenCrack

    展开全文
  • 自有网络以来,就一直存在爬虫和反爬虫,越是大网站,越是成熟的网站,其反爬虫机制越完善,最初的IP限制,验证码限制,还有其他的限制,今天小编跟大家一起去了解下网站在哪些地方设置反爬虫,而爬虫又是怎么应对的...
  • 1. 什么是爬虫? 就是在互联网上一直爬行的蜘蛛, 如果遇到需要的资源, 那么它就会抓取下来(html内容); 模拟浏览器快速访问页面的内容. 2. 浏览网页的过程中发生了什么? 浏览器输入http://www.baidu.com/bbs/; 1). ...
  • 概念定义  ► 网络爬虫:使用任意技术手法批量获取网站站点网页信息的1种方法。... ► 误伤:在网络爬虫过程中,错误地将一般正常用户识别为网络爬虫的行为。  ► 拦截:成功阻止网络爬虫访...
  • 信息校验型反爬虫主要出现在网络请求阶段,这个阶段的反爬虫理念以预防为主要目的,尽可能拒绝爬虫程序的请求。动态渲染和文本混淆则出现在文本获取及数据提取阶段,这个夹断的反爬虫理念以保护数据为主要目的,尽...
  • 最近在梳理之前工作中遇到的场景,在互联网技术日益竞争激烈的情况下,公司的业务数据非常重要,爬虫与反爬虫的对抗,也显得异常重要。比如京东、淘宝等页面上的商品销量、价格,旅游网站上门票的价格、销量。 APP...
  • 爬虫软件介绍?大数据抓取软件?什么是Python爬虫?Python爬虫又叫网络爬虫关于Python爬虫,我们需要知道的有:1. Python基础语法2. HTML页面的内容抓取(数据抓取)3. HTML页面的数据提取(数据清洗)4. Scrapy框架以及...
  • python-反爬虫

    2019-02-18 00:57:18
    1. 什么是爬虫? 就是在互联网上一直爬行的蜘蛛, 如果遇到需要的资源, 那么它就会抓取下来(html内容); 模拟浏览器快速访问页面的内容. 2. 浏览网页的过程中发生了什么? 浏览器输入http://www.baidu.com/bbs/; 1). ...
  • 先要准备一个浏览器,然后会解析头,当然,其他软件(如burpsuit也行)。 然后选择一个网站。 二、正式开始 选好了网站: 2. 我们尝试直接用普通的代码爬一下: from bs4 import BeautifulSoup import requests ...
  • Software Engineering 电子技术与软件工程 • 187 【关键词】Scrapy 爬虫 微博 微博自诞生之日起就获得迅猛发展。截至2017年9月,新浪微博的活跃用户高达3.76亿,较之去年同期增长 27%。微博作为网民交流互动的平台...
  • 前两天朋友发给我了一篇文章,是携程网反爬虫组的技术经理写的,大概讲的是如何用他的超高智商通过(挑衅、怜悯、嘲讽、猥琐)的方式来完美碾压爬虫开发者。今天我就先带大家开发一个最简单低端的爬虫,突破携程网...
  • 什么是爬虫? 就是在互联网上一直爬行的蜘蛛, 如果遇到需要的资源, 那么它就会抓取下来(html内容); 模拟浏览器快速访问页面的内容. 浏览网页的过程中发生了什么? 浏览器输入http://www.baidu.com/bbs/; 1). ...
  • 伴随着大数据行业的迅速发展,人们对IP的需求量也日渐猛增,所以,如果要大批量的抓取信息,就不能避免的使用IP池,针对Python爬虫使用的IP池,是如何搭建起来的呢? 环境说明 为了实现代理IP池,我们如下的软件环境...
  • 【摘要】在这个科学技术高速发展的时代,越来越多的人都开始选择学习编程软件,那么首先被大家选择的编程软件就是python,也用在各行各业之中,并被大家所熟知,所以也有越来越多的python学习者关注反爬虫机制的处理...
  • 1. 什么是爬虫? 就是在互联网上一直爬行的蜘蛛,如果遇到需要的资源,那么它就会抓取下来(html内容); 模拟浏览器快速访问页面的内容。 2. 浏览网页的过程中发生了什么? 浏览器输入http://www.baidu.com/bbs/; 1)....
  • 一个不错的基于Spring boot+Security+Redis+MySql实现权限登录和反爬虫的脚手架介绍软件架构安装教程使用说明请求示例登录接口请求链接请求参数响应参数退出登录接口请求链接请求参数响应参数正常接口请求链接请求...
  • Python爬虫实例教程 讲师日月光华 使用代理IP 答疑群945189407 什么是代理IP 所谓代理IP就是代理用户去取得网络信息的IP地址代理IP可以帮助爬虫掩藏真实身份突破IP访问限制隐藏爬虫的真实IP从而避免被网站反爬虫禁止...
  • 依靠文字矩阵变换来提高蜘蛛爬虫软件抓取的代价. -------------------------------------------- 1:依靠文字矩阵变换 什么是文字矩阵变换?  线性变换/非线性变换  让传输文字和显示文字有差异,使得所见不容易...
  • 150讲轻松搞定Python网络爬虫

    万人学习 2019-05-16 15:30:54
    另外在爬虫过程中,经常容易遇到被反爬虫,比如字体反爬、IP识别、验证码等,如何层层攻克难点拿到想要的数据,这门课程,你都能学到!        2、如果是作为一个其他行业的开发者,比如app开发...
  • 之前也抓过一些app,数据都比较好取,也没有研究的太深,毕竟还有android模拟器+appium的方法。直到遇见了一款app ,具体名字就不说了,它安装在模拟器上竟然打不开 !...软件用手机代理抓包发送r...
  • 15000左右良性软件和5万左右恶意软件反编译好的权限xml文件。 注意是编译好的XML文件不是APK本体。如果需要本体我有恶意软件的下载链接,请联系我。良性软件自己写个爬虫爬吧。
  • 反爬虫机制主要有: (1)分析用户请求的Headers信息进行反爬虫------反爬虫会对用户请求的Headers信息的“User-Agent”进行检测;反爬虫网站还会对“Referer”字段进行检测 (2)检测用户行为,ip在短时间内是否...
  • 从零开始学scrapy网络爬虫

    千人学习 2020-01-22 16:10:17
    由于目标网站可能会对页面进行改版或者升级反爬虫措施,如果发现视频中的方法无法成功爬取数据,敬请按照页面实际情况修改XPath的路径表达式。视频教程主要提供理论、方法支撑。我们也会在第一时间更新源代码,谢谢...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 144
精华内容 57
关键字:

反爬虫软件

爬虫 订阅