zoukankan      html  css  js  c++  java
  • 爬虫技能之内容提取:如何从有不可见元素混淆的页面中抽取数据

    概述

    之前在知乎上看到有人分享的一个有趣的反爬策略:

    image

    那个变态混淆页面源码是这个样子的,正文内容穿插在混淆元素中:

    image

    看到这么变态的页面结构很感兴趣于是就尝试解析了一下。

    知乎分享地址:有哪些有趣的反爬虫手段? - 阿阿聪的回答 - 知乎

    微信变态混淆页面地址:过年同学聚会,到底该不该去?

    分析 & 实现

    对于这种一般都是在选择器中过滤掉不可见的元素就可以了,对于不可见元素目前遇到过并解决掉的两种情况:

    1. 通过display:none;来隐藏(全网代理公开ip爬取(隐藏元素混淆+端口加密)

    2. 通过透明度和偏移来隐藏,比如opacity: 0;虽然元素透明了但是在盒子模型中还是占用了空间的,会把旁边挤开太明显了所以就需要再margin偏移一下将其占用空间释放掉。

    实际上两种方式还是有区别的,display:none;的内容复制不会被影响,复制到的是看到的内容,opacity:0; 并偏移的复制的话会把混淆元素的内容也带上,复制到的并不是看到的内容。

    这个微信页面就是第二种方式,来看下它的套路:

    <span style="margin-right: -1em; max- 100%; opacity: 0; box-sizing: border-box !important; word-wrap: break-word !important;">钔</span>

    先通过opacity:0;将自己变成透明的,然后使用margin-right:-1em;将占用的位置腾出来。

    思路就是遍历整个DOM树手动过滤收集,下面是一个简单的实现,只是将文本内容抓取没有保存样式和图片:

    """
    微信不可见元素混淆页面内容解析
    https://mp.weixin.qq.com/s?__biz=MzI0MDYwNjk2OA==&mid=2247484365&idx=4&sn=291a93e8a4ce6e90d3b6ef8b98fe09c4&chksm=e919085ade6e814cc037ecf6a873f22da0e492911a4e539e6f8fdeff022806b4d248c4d54194&scene=4
    """
    import requests
    import bs4
    
    
    def get_html(url):
        return requests.get(url).content.decode('UTF-8')
    
    
    def dfs_extract_text(tag):
        result_content = ''
        for child in tag.contents:
            if type(child) == bs4.NavigableString:
                result_content += child
            elif 'style' not in child.attrs or 'opacity: 0;' not in child.attrs['style']:
                # 过滤掉透明元素,要么没有style属性,要么style属性中不包含透明样式,否则认为是透明元素直接忽视掉
                result_content += dfs_extract_text(child)
        return result_content
    
    
    def parse(url):
        html_content = get_html(url)
        page = bs4.BeautifulSoup(html_content, 'html.parser')
        content_panel = page.find(id='js_content')
        return dfs_extract_text(content_panel)
    
    
    if __name__ == '__main__':
        target_url = 'https://mp.weixin.qq.com/s?__biz=MzI0MDYwNjk2OA==&mid=2247484365&idx=4&sn=291a93e8a4ce6e90d3b6ef8b98fe09c4&chksm=e919085ade6e814cc037ecf6a873f22da0e492911a4e539e6f8fdeff022806b4d248c4d54194&scene=4'
        content = parse(target_url)
        print(content)

    程序运行结果:

    昨晚回来晚了,是因为我去参加了一个同学聚会,回来后已经夜里十一点多了。这个聚会:并没有想象中那么亲近,也没有传说中的那么美好,更没有当年时的那种纯粹。给我整体的感觉就是六个字:人很累,心很悲 !原因有三个:第一个原因: 你念念不忘的过去,别人已经忘得一干二净了。我和一个女同学上学时很要好(也许只是我的以为,她未必这么认为),那时因为学校离家远,中午放学我们都不回家,就在学校里吃点从家里带来的饭菜。多年以来,和她之间在我脑海中最清晰的画面,就是吃过简单凑合的午饭,我们手牵手围着硕大的操场一圈又一圈的走,有时谈笑,有时打闹,有时就那么静静,静静的牵手走着……昨晚,我向她提起了这段对于我来说,最难忘最深刻最眷恋的记忆。她却给了我最具杀伤力最具毁灭性的一个回答:我都忘了!!!瞬间,我再也没有聊下去的欲望,索然无味……第二个原因: 我们都被经历戴上了面具,被现实披上了虚伪,再也没有上学时的纯粹!尽管是高档的饭店,晶亮的酒杯,我却觉得抵不上年少时你用零花钱买给我的一颗两毛钱的雪糕,一份自己笨手笨脚做的生日礼物。聚会里面有一个同学经历非常坎坷(我们都知道),他却笑得没心没肺,我们明白他在坚强面对。如果和一群老同学,都要装,都要扛,都要说自己无所谓,那还有什么时候,什么朋友,能让一个人打开心扉 ? ?莫名的感到悲哀:曾经的感情只能留给曾经,过去的记忆只能住在过去。老同学之间,没有共同的未来 !第三个原因: 我们都还是原来的那个人,却没有了原来的那颗心。漫长的岁月肯定改变了我们的容貌,不过仔细分辨,我们都能认出来彼此,眉眼,笑容,举止,习惯,年少时的记忆总是那么的深刻,那么的不可磨灭。最可怕的事:不是岁月让一个人变胖了,变老了,变得外表不一样了,而是,它改变了一个人是非分明的心,一个人错对分清的心,一个人向善护弱的心!混得好的,高谈阔论,一大群人追捧围绕着;混得不好的,沉默不语,一大群人敷衍冷淡着!上学时的我们,没有层次,没有高低,没有等级之分的,因为我们是处在同一个起跑线的。现在的我们,再不是当初了……别再妄想着:彼此亲密无间,没有距离,别再奢望着:彼此畅所欲言,没有顾忌!我们说着交际的话,喝着应酬的酒,带着应付的笑,却再也走不进彼此的心……如今的同学聚会,聚的只能是一群的人,而不是一众的心了;如今的同学聚会,聚的只能是外放的笑声,而不是内在的心声了;如今的同学聚会,聚的只能是重逢的酒菜飘香,散场后的感触凄凉 !—《END》—
    

    优点 & 缺点

    使用这种方式渲染出的页面,当我复制网页内容并粘贴到别处的时候:

    image 

    悲剧啊,我复制出来的内容包括了不可见元素的内容,这可以说是一把双刃剑吧,如果作为一个遵纪守法的正常用户我感觉很无辜,为毛我复制到的内容不是我看到的内容呢,这啥破网站啊,这是网站方不希望看到的。但是如果对面的是爬虫的话,一个不小心就会造成这种后果:
    image 

    这恐怕是网站方喜闻乐见的…

    具有同样特性的还有自定义字体反爬,欲知详情且听下回分析。

    .

  • 相关阅读:
    CSRF和XSS的区别
    xss攻击与防范
    GAN基础
    (转载)深度学习数据集
    Python问题解决记录
    Spark Mllib源码分析
    Spark MLlib框架详解
    Spark Structured Streaming框架(5)之进程管理
    Spark Structured Streaming框架(4)之窗口管理详解
    Spark Structured Streaming框架(3)之数据输出源详解
  • 原文地址:https://www.cnblogs.com/cc11001100/p/8766632.html
Copyright © 2011-2022 走看看