开源一个网页智能解析算法库 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
NightTeam
V2EX    分享创造

开源一个网页智能解析算法库

  •  6
     
  •   NightTeam 2020-07-07 16:29:38 +08:00 5039 次点击
    这是一个创建于 1935 天前的主题,其中的信息可能已经有所发展或是发生改变。

    文章作者:「 夜幕团队 NightTeam 」 - 崔庆才

    本文首发于「 崔庆才|静觅 」微信公众号,如需转载请在微信端发消息告知。

    文中提取效果部分由于触发了 V2EX 的敏感词过滤,已全部进行替换,提取效果请前往项目 GitHub 仓库查看。


    之前我写过几篇文章介绍过有关爬虫的智能解析算法,包括商业化应用 Diffbot 、Readability 、Newspaper 这些库,另外我有一位朋友之前还专门针对新闻正文的提取算法 GeneralNewsExtractor,这段时间我也参考和研究了一下这些库的算法,同时参考一些论文,也写了一个智能解析库,在这里就做一个非正式的介绍。

    引入

    那首先说说我想做的是什么。

    比如这里有一个网站,网易新闻,https://news.163.com/rank/,这里有个新闻列表,预览图如下:

    image-20200705212920277

    任意点开一篇新闻,看到的结果如下:

    image-20200705213058853

    我现在需要做到的是在不编写任何 XPath 、Selector 的情况下实现下面信息的提取:

    对于列表页来说,我要提取新闻的所有标题列表和对应的链接,它们就是图中的红色区域:

    image-20200705213401471

    这里红色区域分了多个区块,比如这里一共就是 40 个链接,我都需要提取出来,包括标题的名称,标题的 URL 。

    我们看到页面里面还有很多无用的链接,如上图绿色区域,包括分类、内部导航等,这些需要排除掉。

    对于详情页,我主要关心的内容有标题、发布时间、正文内容,它们就是图中红色区域:

    image-20200705213723198

    其中这里也带有一些干扰项,比如绿色区域的侧边栏的内容,无用的分享链接等。

    总之,我想实现某种算法,实现如上两大部分的智能化提取。

    框架

    之前我开发了一个叫做 Gerapy https://github.com/Gerapy/Gerapy 的框架,是一个基于 Scrapy 、Scrapyd 的分布式爬虫管理框架,属 1.x 版本。现在正在开发 Gerapy 2.x 版本,其定位转向了 Scrapy 的可视化配置和调试、智能化解析方向,放弃支持 Scraypd,转而支持 Docker 、Kubernetes 的部署和监控。

    对于智能解析来说,就像刚才说的,我期望的就是上述的功能,在不编写任何 XPath 和 Selector 的情况下实现页面关键内容的提取。

    框架现在发布了第一个初步版本,名称叫做 Gerapy Auto Extractor,名字 Gerapy 相关,也会作为 Gerapy 的其中一个模块。

    GitHub 链接: https://github.com/Gerapy/GerapyAutoExtractor

    现在已经发布了 PyPi,https://pypi.org/project/gerapy-auto-extractor/,可以使用 pip3 来安装,安装方式如下:

    pip3 install gerapy-auto-extractor 

    安装完了之后我们就可以导入使用了。

    功能

    下面简单介绍下它的功能,它能够做到列表页和详情页的解析。

    列表页:

    • 标题内容
    • 标题链接

    详情页:

    • 标题
    • 正文
    • 发布时间

    先暂时实现了如上内容的提取,其他字段的提取暂时还未实现。

    使用

    要使用 Gerapy Auto Extractor,前提我们必须要先获得 HTML 代码,注意这个 HTML 代码是我们在浏览器里面看到的内容,是整个页面渲染完成之后的代码。在某些情况下如果我们简单用「查看源代码」或 requests 请求获取到的源码并不是真正渲染完成后的 HTML 代码。

    要获取完整 HTML 代码可以在浏览器开发者工具,打开 Elements 选项卡,然后复制你所看到的 HTML 内容即可。

    先测试下列表页,比如我把 https://news.163.com/rank/ 这个保存为 list.html,

    image-20200705220428754

    然后编写提取代码如下:

    import json from gerapy_auto_extractor.extractors.list import extract_list html = open('list.html', encoding='utf-8').read() print(json.dumps(extract_list(html), indent=2, ensure_ascii=False, default=str)) 

    就是这么简单,核心代码就一行,就是调用了一个 extract_list 方法。

    运行结果如下:

    [ { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://news.163.com/20/0705/05/FGOFE1HJ0001875P.html" }, { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://news.163.com/20/0705/02/FGO66FU90001899O.html" }, { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://news.163.com/20/0705/08/FGOPG3AM0001899O.html" }, { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://news.163.com/20/0705/01/FGO42EK90001875O.html" }, { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://home.163.com/20/0705/07/FGOLER1200108GL2.html" }, { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://sports.163.com/20/0704/12/FGML920300058782.html" }, { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://home.163.com/20/0705/07/FGOLEL1100108GL2.html" }, { "title": "内容中疑似包含敏感话题,请修改或者放弃", "url": "https://money.163.com/20/0705/07/FGON5T7B00259DLP.html" }, ... ] 

    可以看到想要的内容就提取出来了,结果是一个列表,包含标题内容和标题链接两个字段,由于内容过长,这里就省略了一部分。

    接着我们再测试下正文的提取,随便打开一篇文章,比如 https://news.ifeng.com/c/7xrdz0kysde,保存下 HTML,命名为 detail.html 。

    image-20200705222433951

    编写测试代码如下:

    import json from gerapy_auto_extractor.extractors import extract_detail html = open('detail.html', encoding='utf-8').read() print(json.dumps(extract_detail(html), indent=2, ensure_ascii=False, default=str)) 

    运行结果如下:

    { "title": "内容中疑似包含敏感话题,请修改或者放弃", "datetime": "2020-07-05 18:54:15", "content": "balabalabala\nbalabalabala" } 

    成功输出了标题、正文、发布时间等内容。

    这里就演示了基本的列表页、详情页的提取操作。

    算法

    整个算法的实现比较杂,我看了几篇论文和几个项目的源码,然后经过一些修改实现的。

    其中列表页解析的参考论文:

    详情页解析的参考论文和项目:

    这些都是不完全参考,然后加上自己的一些修改最终才形成了现在的结果。

    算法在这里就几句话描述一下思路,暂时先不展开讲了。

    列表页解析:

    • 找到具有公共父节点的连续相邻子节点,父节点作为候选节点。
    • 根据节点特征进行聚类融合,将符合条件的父节点融合在一起。
    • 根据节点的特征、文本密度、视觉信息(尚未实现)挑选最优父节点。
    • 从最优父节点内根据标题特征提取标题。

    详情页解析:

    • 标题根据 meta 、title 、h 节点综合提取
    • 时间根据 meta 、正则信息综合提取
    • 正文根据文本密度、符号密度、视觉信息(尚未实现)综合提取。

    后面等完善了之后再详细介绍算法的具体实现,现在如感兴趣可以去看源码。

    说明

    本框架仅仅发布了最初测试版本,测试覆盖度比较少,目前仅仅测试了有限的几个网站,尚未大规模测试和添加对比实验,因此准确率现在还没有标准的保证。

    参考:关于详情页正文的提取我主要参考了 GeneralNewsExtractor 这个项目,原项目据测试可以达到 90% 以上的准确率。

    列表页我测试了腾讯、网易、知乎等都是可以顺利提取的,如:

    19841593922229_.pic_hd

    image-20200705224404571

    image-20200705224419759

    后面会有大规模测试和修正。

    项目初版,肯定存在很多不足,希望大家可以多发 Issue 和提 PR 。

    另外这里建立了一个 Gerapy 开发交流群,之前在 QQ 群的也欢迎加入,以后交流就在微信群了,大家在使用过程遇到关于 Gerapy 、Gerapy Auto Extractor 的问题欢迎交流。

    这里放一个临时二维码,后期可能会失效,失效后大家可以到公众号「进击的 Coder 」获取加群方式。

    image-20200705225922008

    待开发功能

    • 视觉信息的融合
    • 文本相似度的融合
    • 分类模型的融合
    • 下一页翻页的信息提取
    • 正文图片、视频的提取
    • 对接 Gerapy

    最后感谢大家的支持!

    6 条回复    2021-09-04 17:53:40 +08:00
    NightTeam
        1
    NightTeam  
    OP
       2020-07-07 16:44:08 +08:00
    Gerapy 开发交流群满 200 人了,要进群的话直接加微信 CQCcqc 吧。
    Austin2035
        2
    Austin2035  
       2020-07-07 20:21:15 +08:00
    有点通用爬虫内味了,表现如何先不说,性能也是不可忽略的一环。
    jones2000
        3
    jones2000  
       2020-07-08 01:21:45 +08:00
    1. 抓取的最麻烦的就是抓的页面格式变了, 原来配的页面的东西就需要重新配置过, 才能定位到需要的内容。
    是否可以考虑 使用 AI 训练来过滤内容。比如我希望抓取财经类新闻, 通过大量财经类新闻训练让 AI 识别这类内容,后续通过 AI 就可以准确过滤。
    2. 另外一个是版权问题, 是否可以考虑把抓取的内容提取中心内容,这样就可以和原始的内容不一样,规避版权问题。

    不知道楼主有什么这方面的建议吗?
    cqcreer
        4
    cqcreer  
       2020-07-09 21:34:15 +08:00
    @jones2000 1. 这个是可行的,可以通过 NLP 、视觉和 DOM 综合计算得出,这个库是无监督的,更轻量级一些。
    2. 这个其实不是抓取的问题了,涉及到语义改写,可以看下 NLP 相关 Task 。
    cqcreer
        5
    cqcreer  
       2020-07-09 21:35:13 +08:00
    @lookcos 性能没有具体测试,基本上 1-2s 内就出结果了,相比爬虫本身延迟还是可以接受的。
    gancl
        6
    gancl  
       2021-09-04 17:53:40 +08:00
    path = "logs/生成过内容的记录表单.csv" # 文件保存路径
    WebSite = "sohu.com" # 网站主页链接
    Url = "https://www.sohu.com/a/419892530_603537" # 具体内容链接
    Title = extract_detail(requests.get(Url).text)["title"] # 文章的标题
    报错了 AttributeError: 'backports.zoneinfo.ZoneInfo' object has no attribute 'localize'
    @cqcreer
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2487 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 15:04 PVG 23:04 LAX 08:04 JFK 11:04
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86