社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二

梦想橡皮擦 • 6 年前 • 641 次点击  
阅读 1

Python爬虫入门教程 64-100 反爬教科书级别的网站-汽车之家,字体反爬之二

说说这个网站

汽车之家,反爬神一般的存在,字体反爬的鼻祖网站,这个网站的开发团队,一定擅长前端吧,2019年4月19日开始写这篇博客,不保证这个代码可以存活到月底,希望后来爬虫coder,继续和汽车之间对抗。

CSDN上关于汽车之家的反爬文章千千万万了,但是爬虫就是这点有意思,这一刻写完,下一刻还能不能用就不知道了,所以可以一直不断有人写下去。希望今天的博客能帮你学会一个反爬技巧。

今天要爬去的网页

car.autohome.com.cn/config/seri… 我们要做的就是爬取汽车参数配置

具体的数据如下

在这里插入图片描述
查看页面源代码发现,一个好玩的事情,源代码中使用了大量的CSS3的语法 下图,我标注的部分就是关键的一些数据了,大概在600行之后。
在这里插入图片描述

反爬措施展示

源文件数据

刹车/<span class='hs_kw86_baikeIl'></span>安全系统
复制代码

页面显示数据

在这里插入图片描述
一些关键数据被处理过了。

爬取关键信息

我们要把源代码中的关键信息先获取到,即使他数据是存在反爬的。获取数据是非常简单的。通过request模块即可

def get_html():
    url = "https://car.autohome.com.cn/config/series/59.html#pvareaid=3454437"
    headers = {
        "User-agent": "你的浏览器UA"
    }
    with requests.get(url=url, headers=headers, timeout=3) as res:
        html = res.content.decode("utf-8")
    
    return html
复制代码

找关键因素

在html页面中找到关键点:

  • var config
  • var levelId
  • var keyLink
  • var bag
  • var color
  • var innerColor
  • var option

这些内容你找到之后,你下手就用重点了,他们是什么?数据啊,通过简单的正则表达式就可以获取到了

def get_detail(html):
    
    config = re.search("var config = (.*?)};", html, re.S)  
    option = re.search("var option = (.*?)};", html, re.S)
    print(config,option)
复制代码

输出结果


>python e:/python/demo.py
<re.Match object; span=(167291, 233943), match='var config = {"message":"<span class=\'hs_kw50_co>

>python e:/python/demo.py
<re.Match object; span=(167291, 233943), match='var config = {"message":"<span class=\'hs_kw50_co> <re.Match object; span=(233952, 442342), match='var option = {"message":"<span class=\'hs_kw16_op>

复制代码

处理汽车参数

通过正则表达式的search方法,匹配数据,然后调用group(0) 即可得到相关的数据

def get_detail(html):
    
    config = re.search("var config = (.*?)};", html, re.S)  
    option = re.search("var option = (.*?)};", html, re.S)
    
    # 处理汽车参数
    car_info = "" 
    if config and option :
        car_info = car_info + config.group(0) + option.group(0)

    print(car_info)
复制代码

拿到数据之后,没有完,这是混淆之后的数据,需要解析回去,继续关注网页源代码,发现一段奇怪的JS。这段JS先不用管,留点印象即可~

在这里插入图片描述

关键字破解

在这里插入图片描述
注意到

<span class="hs_kw28_configfH"></span>
复制代码

hs_kw数字_configfH是一个span的class

我选中span之后的::before

在这里插入图片描述
对应的css为
在这里插入图片描述
发现实测两个字出现了,对应的class请记住

.hs_kw28_configfH::before
复制代码

全局搜索一下

在这里插入图片描述
双击找到来源

在这里插入图片描述
确定数据就在html源码当中。

格式化html源码,在内部搜索hs_kw,找到关键函数

在这里插入图片描述

                function $GetClassName$($index$) {
                    return '.hs_kw' + $index$ + '_baikeCt';
                }
复制代码

这段JS的来源就是我们刚才保留的那个JS代码段,复制所有的JS源码,到source里面新建一个 snippet,然后我们运行一下。

在这里插入图片描述
在里面代码最后添加一个断点,ctrl+enter运行
在这里插入图片描述
运行到断点,在右侧就能看到一些参数出现

在这里插入图片描述

  • ruleDict:
  • rulePosList
    在这里插入图片描述
    通过参数去查找,核心的替换方法

在这里插入图片描述

接下来,我们进行替换操作,这部流程需要用到selenium进行替换

核心代码如下,主要的注释,我写在了代码内部,希望能帮助你看懂

def write_html(js_list,car_info):
    # 运行JS的DOM -- 这部破解是最麻烦的,非常耗时间~参考了互联网上的大神代码
    DOM = ("var rules = '2';"
       "var document = {};"
       "function getRules(){return rules}"
       "document.createElement = function() {"
       "      return {"
       "              sheet: {"
       "                      insertRule: function(rule, i) {"
       "                              if (rules.length == 0) {"
       "                                      rules = rule;"
       "                              } else {"
       "                                      rules = rules + '#' + rule;"
       "                              }"
       "                      }"
       "              }"
       "      }"
       "};"
       "document.querySelectorAll = function() {"
       "      return {};"
       "};"
       "document.head = {};"
       "document.head.appendChild = function() {};"

       "var window = {};"
       "window.decodeURIComponent = decodeURIComponent;")

    # 把JS文件写入到文件中去
    for item in js_list:
        DOM = DOM + item
    html_type = "<html><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /><head></head><body>    <script type='text/javascript'>"
    # 拼接成一个可以运行的网页
    js = html_type + DOM + " document.write(rules)</script></body></html>"    
    # 再次运行的时候,请把文件删除,否则无法创建同名文件,或者自行加验证即可
    with open("./demo.html", "w", encoding="utf-8") as f:
        f.write(js)

    # 通过selenium将数据读取出来,进行替换
    driver = webdriver.PhantomJS()
    driver.get("./demo.html")
    # 读取body部分
    text = driver.find_element_by_tag_name('body').text   
    # 匹配车辆参数中所有的span标签
    span_list = re.findall("<span(.*?)></span>", car_info)  # car_info 是我上面拼接的字符串

    # 按照span标签与text中的关键字进行替换
    for span in span_list:
        # 这个地方匹配的是class的名称  例如 <span class='hs_kw7_optionZl'></span> 匹配   hs_kw7_optionZl 出来
        info = re.search("'(.*?)'", span)
        if info:
            class_info = str(info.group(1)) + "::before { content:(.*?)}"  # 拼接为  hs_kw7_optionZl::before { content:(.*?)}             
            content = re.search(class_info, text).group(1)   # 匹配文字内容,返回结果为 "实测""油耗""质保"
                                    
            car_info = car_info.replace(str("<span class='" + info.group(1) + "'></span>"),
                                        re.search("\"(.*?)\"", content).group(1))
    print(car_info)
复制代码

运行结果

在这里插入图片描述
对比一下原来数据,发现问题不大,完成任务。
在这里插入图片描述

入库操作

剩下的步骤就是数据持久化了,数据拿到之后,其他的都是比较简单的,希望你可以直接搞定。

小扩展:格式化JS

碰到这种JS,直接找到格式化工具处理它

tool.oschina.net/codeformat/…

格式完成之后,代码具备一定的阅读能力

思路汇总

汽车之家用CSS隐藏了部分真实的字体,在解决的过程中,需要首先针对class去查找,当找到JS位置的时候,必须要搞定它的加密规则,顺着规则之后,只需要完成基本的key、value替换就可以拿到真实的数据了。

关注公众账号:非本科程序员

关注之后,发送【汽车】获取源码

在这里插入图片描述

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/32238
 
641 次点击