Git Product home page Git Product logo

generalnewsextractor's Introduction

GNE

Star History

Star History Chart

项目起源

开发这个项目,源自于我在知网发现了一篇关于自动化抽取新闻类网站正文的算法论文——《基于文本及符号密度的网页正文提取方法》

这篇论文中描述的算法看起来简洁清晰,并且符合逻辑。但由于论文中只讲了算法原理,并没有具体的语言实现,所以我使用 Python 根据论文实现了这个抽取器。并分别使用今日头条、网易新闻、游民星空、观察者网、凤凰网、腾讯新闻、ReadHub、新浪新闻做了测试,发现提取效果非常出色,几乎能够达到100%的准确率。

项目现状

在论文中描述的正文提取基础上,我增加了标题、发布时间和文章作者的自动化探测与提取功能。

目前这个项目是一个非常非常早期的 Demo,不能保证每个版本向下兼容,升级之前请特别注意。发布出来是希望能够尽快得到大家的使用反馈,从而能够更好地有针对性地进行开发。

本项目取名为抽取器,而不是爬虫,是为了规避不必要的风险,因此,本项目的输入是 HTML,输出是一个字典。请自行使用恰当的方法获取目标网站的 HTML。

本项目现在不会,将来也不会提供主动请求网站 HTML 的功能。

如何使用

在线体验

如果你想先体验 GNE 的提取效果,那么你可以访问http://gne.kingname.info/。 一般情况下,你只需要把网页粘贴到最上面的多行文本框中,然后点提取按钮即可。通过附加更多的参数,可以让提取更精确。具体 参数的写法与作用,请参阅 API

使用环境

如果你想体验 GNE 的功能,请按照如下步骤进行:

安装 GNE

# 以下两种方案任选一种即可

# 使用 pip 安装
pip install --upgrade gne

# 使用 pipenv 安装
pipenv install gne

使用 GNE

提取正文
>>> from gne import GeneralNewsExtractor

>>> html = '''经过渲染的网页 HTML 代码'''

>>> extractor = GeneralNewsExtractor()
>>> result = extractor.extract(html, noise_node_list=['//div[@class="comment-list"]'])
>>> print(result)

{"title": "xxxx", "publish_time": "2019-09-10 11:12:13", "author": "yyy", "content": "zzzz", "images": ["/xxx.jpg", "/yyy.png"]}

更多使用说明,请参阅 GNE 的文档

提取列表页(测试版)
>>> from gne import ListPageExtractor
>>> html = '''经过渲染的网页 HTML 代码'''
>>> list_extractor = ListPageExtractor()
>>> result = list_extractor.extract(html,
                                    feature='列表中任意元素的 XPath")
>>> print(result)

开发环境

如果你需要参与本项目的开发,请按照如下步骤进行。

如果你只想阅读源代码,请现在直接按下键盘上的句号键(就是问号左边那个),可以获得更好的阅读体验。

本项目使用 Pipenv管理 Python 的第三方库。如果你不知道 Pipenv 是什么,请点我跳转

安装完成Pipenv以后,按照如下步骤运行代码:

git clone https://github.com/kingname/GeneralNewsExtractor.git
cd GeneralNewsExtractor
pipenv install
pipenv shell
python3 example.py

特别说明

项目代码中的example.py提供了本项目的基本使用示例。

  • 本项目的测试代码在tests文件夹中
  • 本项目的输入 HTML 为经过 JavaScript 渲染以后的 HTML,而不是普通的网页源代码。所以无论是后端渲染、Ajax 异步加载都适用于本项目。
  • 如果你要手动测试新的目标网站或者目标新闻,那么你可以在 Chrome 浏览器中打开对应页面,然后开启开发者工具,如下图所示:

Elements标签页定位到<html>标签,并右键,选择Copy-Copy OuterHTML,如下图所示

  • 当然,你可以使用 Puppeteer/Pyppeteer、Selenium 或者其他任何方式获取目标页面的JavaScript渲染后的源代码。

  • 获取到源代码以后,通过如下代码提取信息:

from gne import GeneralNewsExtractor

extractor = GeneralNewsExtractor()
html = '你的目标网页正文'
result = extractor.extract(html)
print(result)
  • 如果标题自动提取失败了,你可以指定 XPath:
from gne import GeneralNewsExtractor

extractor = GeneralNewsExtractor()
html = '你的目标网页正文'
result = extractor.extract(html, title_xpath='//h5/text()')
print(result)

对大多数新闻页面而言,以上的写法就能够解决问题了。

但某些新闻网页下面会有评论,评论里面可能存在长篇大论,它们会看起来比真正的新闻正文更像是正文,因此extractor.extract()方法还有一个默认参数noise_node_list,用于在网页预处理时提前把评论区域整个移除。

noise_mode_list的值是一个列表,列表里面的每一个元素都是 XPath,对应了你需要提前移除的,可能会导致干扰的目标标签。

例如,观察者网下面的评论区域对应的Xpath 为//div[@class="comment-list"]。所以在提取观察者网时,为了防止评论干扰,就可以加上这个参数:

result = extractor.extract(html, noise_node_list=['//div[@class="comment-list"]'])
  • 提取新闻列表页的功能是测试功能,请勿用于生产环境。你可以通过Chrome 浏览器开发者工具中的 Copy XPath 来复制列表中任意一项的XPath,如下图所示。

GNE 会根据这一项的 XPath,自动找到这个列表里面其他行的数据。

运行截图

网易新闻

今日头条

新浪新闻

凤凰网

网易新闻首页列表

项目文档

GNE 常见问题 Q&A

已知问题

  1. 目前本项目只适用于新闻页的信息提取。如果目标网站不是新闻页,或者是今日头条中的相册型文章,那么抽取结果可能不符合预期。
  2. 可能会有一些新闻页面出现抽取结果中的作者为空字符串的情况,这可能是由于文章本身没有作者,或者使用了已有正则表达式没有覆盖到的情况。

Todo

  • 使用一个配置文件来存放常量数据,而不是直接 Hard Code 写在代码中。
  • 允许自定义时间、作者的提取Pattern
  • 新闻文章列表页提取
  • 对于多页的新闻,允许传入一个 HTML 列表,GNE 解析以后,自动拼接为完整的新闻正文
  • 优化内容提取速度
  • 测试更多新闻网站
  • ……

交流沟通

如果您觉得GNE对您的日常开发或公司有帮助,请加作者微信 mekingname(或扫描下方二维码) 并注明"GNE",作者会将你拉入群。

验证消息:GNE

如果你不用微信,那么可以加入 Telegram 群:https://t.me/joinchat/Bc5swww_XnVR7pEtDUl1vw

论文修订

在使用 Python 实现这个抽取器的过程中,我发现论文里面的公式和方法存在一些纰漏,会导致部分节点报错。我将会单独写几篇文章来介绍这里的修改。请关注我的微信公众号:未闻Code:

generalnewsextractor's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

generalnewsextractor's Issues

关于你提到的这篇论文

天下文章一大抄,没想到现在抄的这么明目张胆,你看的论文中写的算法,最早是由哈尔滨工业大学社会计算与 信息检索研究中心的陈鑫在2009年提出的,这篇2019年武汉的论文里他改了个标题,内容上甚至连程序流程图都和2009年陈鑫的文章中的一模一样(另外这种画法不是严格意义上的流程图,学过软件工程的人都知道流程图长啥样)另外,关于这种算法的实现已经有无数人做过同样的事情。
image

百家号文章较大概率抽取正文失败

bug的现象
参考文章:http://baijiahao.baidu.com/s?id=1661494452861348726

  1. 你期望的返回是?
    正文:美联储的零利率和7000亿元的量化宽松了。美联储的降息比较突然。原本按照正常的时间进程,是美联储在本月18日进行议息。市场预期本月18日美联储降息75个基点的概率是32%,100个基点的概率是68%。但是这一次美联储不按常理出牌,突然间就取消了18日正常的议息会议,在16日便宣布了降息100个基点到零利率。

  2. 实际GNE给你的返回是?
    "content": "百度首页\n登录\n个人中心\n帐号设置\n意见反馈\n退出",
    如何复现

  3. 目标网址
    http://baijiahao.baidu.com/s?id=1661494452861348726

  4. 你怎么调用GNE的
    http://122.51.39.219/
    屏幕截图

使用环境:

  • OS: [e.g. Ubuntu 19.04/Windows 10/macOS ]
  • Python版本 [e.g. 3.7.1]
  • GNE版本 [e.g. 0.1.4]

[讨论] 对于MD类文章的支持

看到作者的这个工具后,因为刚好在学Rust,就尝试按照论文用rust也写了个类似的工具。但是感觉还是有点瑕疵。

论文主要针对的是标准的新闻页面,所以最后打分的时候会加入p标签的权重来打分,因为标准新闻页面分段必然是p标签,所以正文的p标签密度会影响到分数。

然后我就想着试试技术类文章页面呢?我尝试了掘金和简书,发现几乎无法提取到有效内容。对比html后发现,这两个都是将MD转换成html来的,所以内容中p标签极少,大部分都是li、code等标签。段落分段也是直接使用的div标签。

所以我尝试把div的直接文本子元素包裹一层p标签,发现效果没有什么提升。

然后我又尝试把li、code等能直接包裹文本的块级文本标签直接当成p标签计数,发现也没有什么提升。

再检查所有标签的打分数据后,发现最主要的影响元素是因为MD转换的html文章,正文内部包裹了太多的标签了,正文长度26523的一篇文章,内部标签有接近2700个,导致实际的正文标签的文本密度极低,如果有一个p标签内容较长,那么他的文本密度就会极高,最后打分也会远高于真正的正文标签。

所以,我在想是否有什么方法可以更好的支持MD的这种正文提取?

测试用的文章:<https://juejin.im/post/5d9bf530518825427b27639d>

正文标签数据:article(score:5.696602582296532, p_tag_num:67, td:10, sd: 0 , link_tag_num: 17, link_tag_text_length:214,tag_num:2526, text_length:26199)

部分p标签数据:p(score:5.977026284633939, p_tag_num:1, td:90, sd:0 , link_tag_num: 1, link_tag_text_length:9,tag_num:2, text_length:99):

多个作者用 、连接无法提取

PATTERN = [
'(作者[:|:| |丨|/]\s*[\u4E00-\u9FA5a-zA-Z、 ]{2,20})[)】)]]?[^\u4E00-\u9FA5|:|:]',
'(记者[:|:| |丨|/]\s*[\u4E00-\u9FA5a-zA-Z、 ]{2,20})[)】)]]?[^\u4E00-\u9FA5|:|:]',
'(原创[:|:| |丨|/]\s*[\u4E00-\u9FA5a-zA-Z、 ]{2,20})[)】)]]?[^\u4E00-\u9FA5|:|:]',
'(撰文[:|:| |丨|/]\s*[\u4E00-\u9FA5a-zA-Z、 ]{2,20})[)】)]]?[^\u4E00-\u9FA5|:|:]',
'(文/图[:|:| |丨|/]?\s*[\u4E00-\u9FA5a-zA-Z、 ]{2,20})[)】)]]?[^\u4E00-\u9FA5|:|:]',
]

标题抽取逻辑应当调整

bug的现象

  1. 你期望的返回是?
    完整标题,例如:本赛季暂停 斯波:联盟做出了正确举措
  2. 实际GNE给你的返回是?
    网站Title:NBA资讯速看网

如何复现

  1. 目标网址
    答:不用网址,上面的举例可以说明情况
  2. 你怎么调用GNE的
    答:按照文档调用

屏幕截图

补充:不用在意截图的细节,其实上面的举例也可以说明情况

使用环境:

  • OS: [macOS ]
  • Python版本 [e.g. 3.6]
  • GNE版本 [忘记了]

建议:调整标题抽取规则顺序,TitleExtractor 中的 extract_by_title 方法优先级不应该是最高的,可以考虑 extract_by_htag 或者 extract_by_xpath。当用户传入 title_xpath 时 extract_by_xpath 的优先级应该最高,反之则 extract_by_htag 最高,例如

title = self.extract_by_xpath(element, title_xpath) or self.extract_by_htag(element)  or self.extract_by_title(element)

百家号文章正文提取不到

bug的现象
百家号文章html源代码当天中正文内容,正文提取不到

  1. 你期望的返回是?
    正文内容

  2. 实际GNE给你的返回是?
    'content': '百度首页\n登录\n个人中心\n帐号设置\n意见反馈\n退出'
    如何复现

  3. 目标网址
    https://baijiahao.baidu.com/s?id=1655696407716538005

  4. 你怎么调用GNE的
    url = 'https://baijiahao.baidu.com/s?id=1655696407716538005'
    html = requests.get(url,headers,timeout=50).content.decode('utf-8')
    print(html)
    extractor = GeneralNewsExtractor()
    result = extractor.extract(html)

使用环境:

  • OS: [Windows 10]
  • Python版本 [e.g. 3.7.1]
  • GNE版本 [e.g. 0.1.4]

对那个论文有个疑问 关于符合密度

根据论文的公式:
Ti - LTi
SbDi = --------------
Sbi + 1

    SbDi: 符号密度
    Sbi:符号数量

如果一个节点里面的文本的符号出现次数越多,符号密度SbDi的值就越小,但是文档里说会越大,如何解 ?

关于标准差的作用calc_standard_deviation

作者您好,
标准差是根据所有节点的密码算得的。而在计算每个节点的分数时,都要与之相乘,对每个节点来说该值都是一样的固定值,除了会影响每个节点的分数,并不会对最终的分数排名产生影响,是不是我的理解有问题?

[Bug report] 澎湃新闻提取只有一小段

bug的现象

  1. 你期望的返回是?
    正确提取澎湃新闻的正文内容

  2. 实际GNE给你的返回是?
    只有一小段正文内容被提取出来
    据我观察似乎是图注和小标题对提取的影响比较大
    如何复现

  3. 目标网址
    https://www.thepaper.cn/newsDetail_forward_5420361

  4. 你怎么调用GNE的

extractor = GeneralNewsExtractor()
extractor.extract(theHtmlString)

屏幕截图
图片
图片

使用环境:

  • OS: [e.g. Ubuntu 19.04/Windows 10/macOS ]
    Arch Linux on WIndows 10 (WSL)
  • Python版本 [e.g. 3.7.1]
    3.8.1
  • GNE版本 [e.g. 0.1.4]
    0.1.4

gne提取36kr新闻无法获取title

bug的现象

  1. 你期望的返回是?
  2. 实际GNE给你的返回是?

如何复现

  1. 目标网址
    https://36kr.com/p/5288922
  2. 你怎么调用GNE的
    import requests
    from gne import GeneralNewsExtractor
    resp = requests.get(url, headers=headers)
    extractor = GeneralNewsExtractor()
    result = extractor.extract(resp.text)
    print(result)
    屏幕截图
    image

使用环境:

  • OS: [e.g. Ubuntu 19.04/Windows 10/macOS ]
  • Python版本 [e.g. 3.7.1]
  • GNE版本 [e.g. 0.1.4]

提取Title的新思路

从h1-h5中提取文字,然后与<title>标签中的文字对比。如果是子集且较长,一般就是新闻标题。

感谢 @止水 提的建议

百家号提取content字段不正确

http://baijiahao.baidu.com/s?id=1646796218135408573&wfr=spider&for=pc
http://baijiahao.baidu.com/s?id=1646116705759028486&wfr=spider&for=pc
http://baijiahao.baidu.com/s?id=1646397256193648043&wfr=spider&for=pc
http://baijiahao.baidu.com/s?id=1646299231611696619&wfr=spider&for=pc

比如:
http://baijiahao.baidu.com/s?id=1646116705759028486&wfr=spider&for=pc
提取出来是{'title': '日本最后一家传呼机公司停止服务,殡仪馆为BB机送终', 'publish_time': '9月30日', 'author': '', 'content': '百度首页\n登录\n个人中心\n帐号设置\n意见反馈\n退出'} 这种

微信公众号很不准,并且可否保留正文标签?

bug的现象

  1. 你期望的返回是?
  2. 实际GNE给你的返回是?

如何复现

  1. 目标网址
    https://mp.weixin.qq.com/s?__biz=MzA3NDUwODkwNw==&mid=2650242384&idx=1&sn=499db9c82139967172021f96f9691138&chksm=877d6254b00aeb42e6c4a1f47d72cf41e75af879908e9d9ef1a39f7eb68fc77166babe551dc5&token=848504089&lang=zh_CN#rd
  2. 你怎么调用GNE的
html = requests.get('https://mp.weixin.qq.com/s?__biz=MzA3NDUwODkwNw==&mid=2650242384&idx=1&sn=499db9c82139967172021f96f9691138&chksm=877d6254b00aeb42e6c4a1f47d72cf41e75af879908e9d9ef1a39f7eb68fc77166babe551dc5&token=848504089&lang=zh_CN#rd').text
extractor = GeneralNewsExtractor()
result = extractor.extract(html)
print(result)

屏幕截图

使用环境:

  • OS: [e.g. Ubuntu 19.04/Windows 10/macOS ]
    MacOS
  • Python版本 [e.g. 3.7.1]
    3.7
  • GNE版本 [e.g. 0.1.4]

新浪科技 无法正常获取正文

# http://tech.sina.com.cn/t/2019-09-11/doc-iicezzrq4972166.shtml
from pprint import pprint

from gne import GeneralNewsExtractor
html = """ html 正文"""
extractor = GeneralNewsExtractor()
result = extractor.extract(html)
pprint(result)

image

提取正文异常

bug的现象
{'title': '5月20日至31日,京沪高速无锡至江阴大桥至广陵枢纽段封闭!', 'author': '无锡交警', 'publish_time': '5月20日', 'content': '特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。\nNotice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.', 'images': []}

  1. 目标网址 http://dy.163.com/v2/article/detail/EFDAIN1E054550F0.html
  2. 你怎么调用GNE的
    import requests
    from gne import GeneralNewsExtractor

url = 'http://dy.163.com/v2/article/detail/EFDAIN1E054550F0.html'
r = requests.get(url)
r.encoding = 'gbk'
extractor = GeneralNewsExtractor()
auto_result = extractor.extract(r.text)
print(auto_result)
屏幕截图

使用环境:

  • OS: [e.g. Ubuntu 19.04/Windows 10/macOS ]
  • Python版本 [e.g. 3.7.1]
  • GNE版本 [e.g. 0.1.4]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.