python爬虫智能解析库详解_python智能解析列表 标题 url 时间-程序员宅基地

技术标签: Newspaper  Diffbot  Readability  python爬虫  智能解析  爬虫(urllib)  

文章很长 请耐心阅读

什么是爬虫

爬虫是做什么的?是帮助我们来快速获取有效信息的。然而做过爬虫的人都知道,解析是个麻烦事。比如一篇新闻吧,链接是这个:
https://news.ifeng.com/c/7kQcQG2peWU,页面预览图如下:
在这里插入图片描述
我们需要从页面中提取出标题、发布人、发布时间、发布内容、图片等内容。一般情况下我们需要怎么办?写规则。

那么规则都有什么呢?怼正则,怼 CSS 选择器,怼 XPath。我们需要对标题、发布时间、来源等内容做规则匹配,更有甚者再需要正则表达式来辅助一下。我们可能就需要用 re、BeautifulSoup、pyquery 等库来实现内容的提取和解析。

但如果我们有成千上万个不同样式的页面怎么办呢?它们来自成千上万个站点,难道我们还需要对他们一一写规则来匹配吗?这得要多大的工作量啊。另外这些万一弄不好还会解析有问题。比如正则表达式在某些情况下匹配不了了,CSS、XPath 选择器选错位了也会出现问题。

想必大家可能见过现在的浏览器有阅读模式,比如我们把这个页面用 Safari 浏览器打开,然后开启阅读模式,看看什么效果:
在这里插入图片描述

页面一下子变得非常清爽,只保留了标题和需要读的内容。原先页面多余的导航栏、侧栏、评论等等的统统都被去除了。它怎么做到的?难道是有人在里面写好规则了?那当然不可能的事。其实,这里面就用到了智能化解析了。那么本篇文章,我们就来了解一下页面的智能化解析的相关知识。

智能化解析

所谓爬虫的智能化解析,顾名思义就是不再需要我们针对某一些页面来专门写提取规则了,我们可以利用一些算法来计算出来页面特定元素的位置和提取路径。比如一个页面中的一篇文章,我们可以通过算法计算出来,它的标题应该是什么,正文应该是哪部分区域,发布时间是什么等等。

其实智能化解析是非常难的一项任务,比如说你给人看一个网页的一篇文章,人可以迅速找到这篇文章的标题是什么,发布时间是什么,正文是哪一块,或者哪一块是广告位,哪一块是导航栏。但给机器来识别的话,它面临的是什么?仅仅是一系列的 HTML 代码而已。那究竟机器是怎么做到智能化提取的呢?其实这里面融合了多方面的信息。

比如标题。一般它的字号是比较大的,而且长度不长,位置一般都在页面上方,而且大部分情况下它应该和 title 标签里的内容是一致的。

比如正文。它的内容一般是最多的,而且会包含多个段落 p 或者图片 img 标签,另外它的宽度一般可能会占用到页面的三分之二区域,并且密度(字数除以标签数量)会比较大。

比如时间。不同语言的页面可能不同,但时间的格式是有限的,如 2019-02-20 或者 2019/02/20 等等,也有的可能是美式的记法,顺序不同,这些也有特定的模式可以识别。

比如广告。它的标签一般可能会带有 ads 这样的字样,另外大多数可能会处于文章底部、页面侧栏,并可能包含一些特定的外链内容。

另外还有一些特点就不再一一赘述了,这其中包含了区块位置、区块大小、区块标签、区块内容、区块疏密度等等多种特征,另外很多情况下还需要借助于视觉的特征,所以说这里面其实结合了算法计算、视觉处理、自然语言处理等各个方面的内容。如果能把这些特征综合运用起来,再经过大量的数据训练,是可以得到一个非常不错的效果的。

目前来说,智能文本提取可以分为三类:

  • 基于网页文档内容的提取方法
  • 基于 DOM 结构信息的提取方法
  • 基于视觉信息的提取方法
业界进展

未来的话,页面也会越来越多,页面的渲染方式也会发生很大的变化,爬虫也会越来越难做,智能化爬虫也将会变得越来越重要。

目前工业界,其实已经有落地的算法应用了。经过我的一番调研,目前发现有这么几种算法或者服务对页面的智能化解析做的比较好:

  • Diffbot,国外的一家专门来做智能化解析服务的公司,https://www.diffbot.com

  • Boilerpipe,Java 语言编写的一个页面解析算法,https://github.com/kohlschutter/boilerpipe

  • Embedly,提供页面解析服务的公司,https://embed.ly/extract

  • Readability,是一个页面解析算法,但现在官方的服务已经关闭了,https://www.readability.com/

  • Mercury,Readability 的替代品,https://mercury.postlight.com/

  • Goose,Java 语音编写的页面解析算法,https://github.com/GravityLabs/goose

那么这几种算法或者服务到底哪些好呢,Driffbot 官方曾做过一个对比评测,使用 Google 新闻的一些文章,使用不同的算法依次摘出其中的标题和文本,然后与真实标注的内容进行比较,比较的指标就是文字的准确率和召回率,以及根据二者计算出的 F1 分数。

其结果对比如下:
在这里插入图片描述
经过对比我们可以发现,Diffbot 的准确率和召回率都独占鳌头,其中的 F1 值达到了 0.97,可以说准确率非常高了。另外接下来比较厉害的就是 Boilerpipe 和 Readability,Goose 的表现则非常差,F1 跟其他的算法差了一大截。下面是几个算法的 F1 分数对比情况:
在这里插入图片描述
有人可能好奇为什么 Diffbot 这么厉害?我也查询了一番。Diffbot 自 2010 年以来就致力于提取 Web 页面数据,并提供许多 API 来自动解析各种页面。其中他们的算法依赖于自然语言技术、机器学习、计算机视觉、标记检查等多种算法,并且所有的页面都会考虑到当前页面的样式以及可视化布局,另外还会分析其中包含的图像内容、CSS 甚至 Ajax 请求。另外在计算一个区块的置信度时还考虑到了和其他区块的关联关系,基于周围的标记来计算每个区块的置信度。

总之,Diffbot 也是一直致力于这一方面的服务,整个 Diffbot 就是页面解析起家的,现在也一直专注于页面解析服务,准确率高也就不足为怪了。

但它们的算法开源了吗?很遗憾,并没有,而且我也没有找到相关的论文介绍它们自己的具体算法。

所以,如果想实现这么好的效果,那就使用它们家的服务就好了。

Diffbot 页面解析

首先我们需要注册一个账号,它有 15 天的免费试用,注册之后会获得一个 Developer Token,这就是使用 Diffbot 接口服务的凭证。

接下来切换到它的测试页面中,链接为:https://www.diffbot.com/dev/home/,我们来测试一下它的解析效果到底是怎样的。

这里我们选择的测试页面就是上文所述的页面,链接为:https://news.ifeng.com/c/7kQcQG2peWU,API 类型选择 Article API,然后点击 Test Drive 按钮,接下来它就会出现当前页面的解析结果:
结果
这时候我们可以看到,它帮我们提取出来了标题、发布时间、发布机构、发布机构链接、正文内容等等各种结果。而且目前来看都十分正确,时间也自动识别之后做了转码,是一个标准的时间格式。

接下来我们继续下滑,查看还有什么其他的字段,这里我们还可以看到有 html 字段,它和 text 不同的是,它包含了文章内容的真实 HTML 代码,因此图片也会包含在里面,如图所示:
在这里插入图片描述
另外最后面还有 images 字段,他以列表形式返回了文章套图及每一张图的链接,另外还有文章的站点名称、页面所用语言等等结果,如图所示:
在这里插入图片描述
当然我们也可以选择 JSON 格式的返回结果,其内容会更加丰富,例如图片还返回了其宽度、高度、图片描述等等内容,另外还有各种其他的结果如面包屑导航等等结果,如图所示:

在这里插入图片描述
经过手工核对,发现其返回的结果都是完全正确的,准确率相当之高!

所以说,如果你对准确率要求没有那么非常非常严苛的情况下,使用 Diffbot 的服务可以帮助我们快速地提取页面中所需的结果,省去了我们绝大多数的手工劳动,可以说是非常赞了。

但是,我们也不能总在网页上这么试吧。其实 Diffbot 也提供了官方的 API 文档,让我们来一探究竟。

Diffbot API

Driffbot 提供了多种 API,如 Analyze API、Article API、Disscussion API 等。

下面我们以 Article API 为例来说明一下它的用法,其官方文档地址为:https://www.diffbot.com/dev/docs/article/,API 调用地址为:

https://api.diffbot.com/v3/article

我们可以用 GET 方式来进行请求,其中的 Token 和 URL 都可以以参数形式传递给这个 API,其必备的参数有:

  • token:即 Developer Token

  • url:即要解析的 URL 链接

另外它还有几个可选参数:

  • fields:用来指定返回哪些字段,默认已经有了一些固定字段,这个参数可以指定还可以额外返回哪些可选字段

  • paging:如果是多页文章的话,如果将这个参数设置为 false 则可以禁止多页内容拼接

  • maxTags:可以设置返回的 Tag 最大数量,默认是 10 个

  • tagConfidence:设置置信度的阈值,超过这个值的 Tag 才会被返回,默认是 0.5

  • discussion:如果将这个参数设置为 false,那么就不会解析评论内容

  • timeout:在解析的时候等待的最长时间,默认是 30 秒

  • callback:为 JSONP 类型的请求而设计的回调

这里大家可能关注的就是 fields 字段了,在这里我专门做了一下梳理,首先是一些固定字段:

  • type:文本的类型,这里就是 article 了

  • title:文章的标题

  • text:文章的纯文本内容,如果是分段内容,那么其中会以换行符来分隔

  • html:提取结果的 HTML 内容

  • date:文章的发布时间,其格式为 RFC 1123

  • estimatedDate:如果日期时间不太明确,会返回一个预估的时间,如果文章超过两天或者没有发布日期,那么这个字段就不会返回

  • author:作者

  • authorUrl:作者的链接

  • discussion:评论内容,和 Disscussion API 返回结果一样

  • humanLanguage:语言类型,如英文还是中文等

  • numPages:如果文章是多页的,这个参数会控制最大的翻页拼接数目

  • nextPages:如果文章是多页的,这个参数可以指定文章后续链接

  • siteName:站点名称

  • publisherRegion:文章发布地区

  • publisherCountry:文章发布国家

  • pageUrl:文章链接

  • resolvedPageUrl:如果文章是从 pageUrl 重定向过来的,则返回此内容

  • tags:文章的标签或者文章包含的实体,根据自然语言处理技术和 DBpedia 计算生成,是一个列表,里面又包含了子字段:

  • label:标签名

  • count:标签出现的次数

  • score:标签置信度

  • rdfTypes:如果实体可以由多个资源表示,那么则返回相关的 URL

  • type:类型

  • uri:Diffbot Knowledge Graph 中的实体链接

  • images:文章中包含的图片

  • videos:文章中包含的视频

  • breadcrumb:面包屑导航信息

  • diffbotUri:Diffbot 内部的 URL 链接

以上的预定字段就是如果可以返回那就会返回的字段,是不能定制化配置的,另外我们还可以通过 fields 参数来指定扩展如下可选字段:

  • quotes:引用信息

  • sentiment:文章的情感值,-1 到 1 之间

  • links:所有超链接的顶级链接

  • querystring:请求的参数列表

好,以上便是这个 API 的用法,大家可以申请之后使用这个 API 来做智能化解析了。

下面我们用一个实例来看一下这个 API 的用法,代码如下:

import requests, json

url = 'https://api.diffbot.com/v3/article'
params = {
    
    'token': '77b41f6fbb24495113d52836528fa',
    'url': 'https://news.ifeng.com/c/7kQcQG2peWU',
    'fields': 'meta' 
}
response = requests.get(url, params=params)
print(json.dumps(response.json(), indent=2, ensure_ascii=False))

这里首先定义了 API 的链接,然后指定了 params 参数,即 GET 请求参数。

参数中包含了必选的 token、url 字段,也设置了可选的 fields 字段,其中 fields 为可选的扩展字段 meta 标签。

我们来看下运行结果,结果如下:

{
    
  "request": {
    
    "pageUrl": "https://news.ifeng.com/c/7kQcQG2peWU",
    "api": "article",
    "fields": "sentiment, meta",
    "version": 3
  },
  "objects": [
    {
    
      "date": "Wed, 20 Feb 2019 02:26:00 GMT",
      "images": [
        {
    
          "naturalHeight": 460,
          "width": 640,
          "diffbotUri": "image|3|-1139316034",
          "url": "http://e0.ifengimg.com/02/2019/0219/1731DC8A29EB2219C7F2773CF9CF319B3503D0A1_size382_w690_h460.png",
          "naturalWidth": 690,
          "primary": true,
          "height": 426
        },
        // ...
      ],
      "author": "中国新闻网",
      "estimatedDate": "Wed, 20 Feb 2019 06:47:52 GMT",
      "diffbotUri": "article|3|1591137208",
      "siteName": "ifeng.com",
      "type": "article",
      "title": "故宫,你低调点!故宫:不,实力已不允许我继续低调",
      "breadcrumb": [
        {
    
          "link": "https://news.ifeng.com/",
          "name": "资讯"
        },
        {
    
          "link": "https://news.ifeng.com/shanklist/3-35197-/",
          "name": "大陆"
        }
      ],
      "humanLanguage": "zh",
      "meta": {
    
        "og": {
    
          "og:time ": "2019-02-20 02:26:00",
          "og:image": "https://e0.ifengimg.com/02/2019/0219/1731DC8A29EB2219C7F2773CF9CF319B3503D0A1_size382_w690_h460.png",
          "og:category ": "凤凰资讯",
          "og: webtype": "news",
          "og:title": "故宫,你低调点!故宫:不,实力已不允许我继续低调",
          "og:url": "https://news.ifeng.com/c/7kQcQG2peWU",
          "og:description": "  “我的名字叫紫禁城,快要600岁了,这上元的夜啊,总是让我沉醉,这么久了却从未停止。”   “重"
        },
        "referrer": "always",
        "description": "  “我的名字叫紫禁城,快要600岁了,这上元的夜啊,总是让我沉醉,这么久了却从未停止。”   “重",
        "keywords": "故宫 紫禁城 故宫博物院 灯光 元宵节 博物馆 一票难求 元之 中新社 午门 杜洋 藏品 文化 皇帝 清明上河图 元宵 千里江山图卷 中英北京条约 中法北京条约 天津条约",
        "title": "故宫,你低调点!故宫:不,实力已不允许我继续低调_凤凰资讯"
      },
      "authorUrl": "https://feng.ifeng.com/author/308904",
      "pageUrl": "https://news.ifeng.com/c/7kQcQG2peWU",
      "html": "<p>“我的名字叫紫禁城,快要600岁了,这上元的夜啊,总是让我沉醉,这么久了却从未停止。...</blockquote> </blockquote>",
      "text": "“我的名字叫紫禁城,快要600岁了,这上元的夜啊,总是让我沉醉,这么久了却从未停止。”\n“...",
      "authors": [
        {
    
          "name": "中国新闻网",
          "link": "https://feng.ifeng.com/author/308904"
        }
      ]
    }
  ]
}

可见其返回了如上的内容,是一个完整的 JSON 格式,其中包含了标题、正文、发布时间等等各种内容。

可见,不需要我们配置任何提取规则,我们就可以完成页面的分析和抓取,得来全不费功夫。

下面我们来介绍两个比较基础的开源工具包 Readability 和 Newspaper 的用法,这两个包经我测试其实准确率并不是很好,主要是让大家大致对智能解析有初步的理解。后面还会介绍一些更加强大的智能化解析算法。

Readability

Readability 实际上是一个算法,并不是一个针对某个语言的库。其主要原理就是计算了 DOM 的文本密度,另外根据一些常见的 DOM 属性如 id、class 等计算了一些 DOM 的权重,最后分析得到了对应的 DOM 区块,进而提取出具体的文本内容。

现在搜索 Readability 其实已经找不到了,取而代之的是一个 JavaScript 工具包,叫做 mercury-parser,据我所知应该是 Readability 不维护了,换成了 mercury-parser。后者现在也做成了一个 Chrome 插件,大家可以下载使用一下。

回归正题,这次主要介绍的是 Python 的 Readability 实现,现在其实有很多开源版本,本文选取的是 https://github.com/buriy/python-readability,是基于最早的 Python 版本的 Readability 库 https://github.com/timbertson/python-readability 二次开发的,现在已经发布到了 PyPi,大家可以直接下载安装使用。

安装很简单,通过 pip 安装即可:

pip3 install readability-lxml

安装好了之后便可以通过导入 readability 使用了,下面我们随便从网上找一个新闻页面,比如:https://tech.163.com/19/0909/08/EOKA3CFB00097U7S.html,其页面截图如下:

在这里插入图片描述
我们的目的就是它的正文、标题等内容。下面我们用 Readability 试一下,示例如下:

import requests
from readability import Document

url = 'https://tech.163.com/19/0909/08/EOKA3CFB00097U7S.html'
html = requests.get(url).content
doc = Document(html)
print('title:', doc.title())
print('content:', doc.summary(html_partial=True))

在这里我们直接用 requests 库对网页进行了请求,获取了其 HTML 页面内容,赋值为 html。

然后引入了 readability 里的 Document 类,使用 html 变量对其进行初始化,然后我们分别调用了 title 方法和 summary 方法获得了其标题和正文内容。

这里 title 方法就是获取文章标题的,summary 就是获取文章正文的,但是它获取的正文可能包含一些 HTML 标签。这个 summary 方法可以接收一个 html_partial 参数,如果设置为 True,返回的结果则不会再带有<html><body>标签。
看下运行结果:

title: 今年iPhone只有小改进?分析师:还有其他亮点_网易科技
content: <div><div class="post_text" id="endText">           
                    <p class="otitle">
                        (原标题:Apple Bets More Cameras Can Keep iPhone Humming)
                    </p>
                    <p class="f_center"><img alt="今年iPhone只有小改进?分析师:还有其他亮点" src="http://cms-bucket.ws.126.net/2019/09/09/d65ba32672934045a5bfadd27f704bc1.jpeg"/><span>图示:苹果首席执行官蒂姆·库克(Tim Cook)6月份举行的苹果全球开发者大会上。</span></p><p>网易科技讯 99日消息,据国外媒体报道,和过去的12个年头一样,新款
... 中间省略 ...
                    <p>苹果还即将推出包括电视节目和视频游戏等内容的新订阅服务。分析师表示,该公司最早可能在本周宣布TV+和Arcade等服务的价格和上线时间。</p><p>Strategy Analytics的尼尔·莫斯顿(Neil Mawston)表示,可穿戴设备和服务的结合将是苹果业务超越iPhone的关键。他说,上一家手机巨头诺基亚公司在试图进行类似业务转型时就陷入了困境之中。(辰辰)</p><p><b>相关报道:</b></p><p><a href="https://tech.163.com/19/0908/09/EOHS53RK000999LD.html" target="_self" urlmacroreplace="false">iPhone 11背部苹果Logo改为居中:为反向无线充电</a></p><p><a href="https://tech.163.com/19/0907/08/EOF60CBC00097U7S.html" target="_self" urlmacroreplace="false">2019年新iPhone传言汇总,你觉得哪些能成真</a>  </p><p/>
                        <p/>
                        <div class="ep-source cDGray">
                            <span class="left"><a href="http://tech.163.com/"><img src="https://static.ws.126.net/cnews/css13/img/end_tech.png" alt="王凤枝" class="icon"/></a> 本文来源:网易科技报道  </span>
                            <span class="ep-editor">责任编辑:王凤枝_NT2541</span>
                        </div>
                </div> 
</div>

可以看到,标题提取是正确的。正文其实也是正确的,不过这里还包含了一些 HTML 标签,比如<img><p>等,我们可以进一步通过一些解析库来解析。
看下源码吧,比如提取标题的方法:

def normalize_entities(cur_title):
    entities = {
    
        u'\u2014':'-',
        u'\u2013':'-',
        u'&mdash;': '-',
        u'&ndash;': '-',
        u'\u00A0': ' ',
        u'\u00AB': '"',
        u'\u00BB': '"',
        u'&quot;': '"',
    }
    for c, r in entities.items():
        if c in cur_title:
            cur_title = cur_title.replace(c, r)

    return cur_title

def norm_title(title):
    return normalize_entities(normalize_spaces(title))

def get_title(doc):
    title = doc.find('.//title')
    if title is None or title.text is None or len(title.text) == 0:
        return '[no-title]'

    return norm_title(title.text)

 def title(self):
    """Returns document title"""
    return get_title(self._html(True))

title方法实际上就是调用了一个 get_title 方法,它怎么做的?实际上就是用了一个 XPath 只解析了<title>标签里面的内容,别的没了。如果没有,那就返回 [no-title]

def summary(self, html_partial=False):
    ruthless = True
    while True:
        self._html(True)
        for i in self.tags(self.html, 'script', 'style'):
            i.drop_tree()
        for i in self.tags(self.html, 'body'):
            i.set('id', 'readabilityBody')
        if ruthless:
            self.remove_unlikely_candidates()
        self.transform_misused_divs_into_paragraphs()
        candidates = self.score_paragraphs()

        best_candidate = self.select_best_candidate(candidates)

        if best_candidate:
            article = self.get_article(candidates, best_candidate,
                                       html_partial=html_partial)
        else:
            if ruthless:
                ruthless = False
                continue
            else:
                article = self.html.find('body')
                if article is None:
                    article = self.html
        cleaned_article = self.sanitize(article, candidates)
        article_length = len(cleaned_article or '')
        retry_length = self.retry_length
        of_acceptable_length = article_length >= retry_length
        if ruthless and not of_acceptable_length:
            ruthless = False
            continue
        else:
            return cleaned_article

这里我删除了一些冗余的调试的代码,只保留了核心的代码,其核心实现就是先去除一些干扰内容,然后找出一些疑似正文的 candidates,然后再去寻找最佳匹配的 candidates 最后提取其内容返回即可。

然后再找到获取 candidates 方法里面的 score_paragraphs 方法,又追踪到一个 score_node 方法,就是为每一个节点打分的,其实现如下:

def score_node(self, elem):
    content_score = self.class_weight(elem)
    name = elem.tag.lower()
    if name in ["div", "article"]:
        content_score += 5
    elif name in ["pre", "td", "blockquote"]:
        content_score += 3
    elif name in ["address", "ol", "ul", "dl", "dd", "dt", "li", "form", "aside"]:
        content_score -= 3
    elif name in ["h1", "h2", "h3", "h4", "h5", "h6", "th", "header", "footer", "nav"]:
        content_score -= 5
    return {
    
        'content_score': content_score,
        'elem': elem
    }

这什么意思呢?你看如果这个节点标签是 div 或者 article 等可能表征正文区块的话,就加 5 分,如果是 aside 等表示侧栏的内容就减 3 分。这些打分也没有什么非常标准的依据,可能是根据经验累积的规则。

另外还有一些方法里面引用了一些正则匹配来进行打分或者替换,其定义如下:

REGEXES = {
    
    'unlikelyCandidatesRe': re.compile('combx|comment|community|disqus|extra|foot|header|menu|remark|rss|shoutbox|sidebar|sponsor|ad-break|agegate|pagination|pager|popup|tweet|twitter', re.I),
    'okMaybeItsACandidateRe': re.compile('and|article|body|column|main|shadow', re.I),
    'positiveRe': re.compile('article|body|content|entry|hentry|main|page|pagination|post|text|blog|story', re.I),
    'negativeRe': re.compile('combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget', re.I),
    'divToPElementsRe': re.compile('<(a|blockquote|dl|div|img|ol|p|pre|table|ul)', re.I),
    #'replaceBrsRe': re.compile('(<br[^>]*>[ \n\r\t]*){2,}',re.I),
    #'replaceFontsRe': re.compile('<(\/?)font[^>]*>',re.I),
    #'trimRe': re.compile('^\s+|\s+$/'),
    #'normalizeRe': re.compile('\s{2,}/'),
    #'killBreaksRe': re.compile('(<br\s*\/?>(\s|&nbsp;?)*){1,}/'),
    'videoRe': re.compile('https?:\/\/(www\.)?(youtube|vimeo)\.com', re.I),
    #skipFootnoteLink:      /^\s*(\[?[a-z0-9]{1,2}\]?|^|edit|citation needed)\s*$/i,
}

比如这里定义了 unlikelyCandidatesRe,就是不像 candidates 的 pattern,比如 foot、comment 等等,碰到这样的标签或 pattern 的话,在计算分数的时候都会减分,另外还有其他的 positiveRe、negativeRe 也是一样的原理,分别对匹配到的内容进行加分或者减分。

这就是 Readability 的原理,是基于一些规则匹配的打分模型,很多规则其实来源于经验的累积,分数的计算规则应该也是不断地调优得出来的。

另外其他的就没了,Readability 并没有提供提取时间、作者的方法,另外此种方法的准确率也是有限的,但多少还是省去了一些人工成本。

Newspaper

另外还有一个智能解析的库,叫做 Newspaper,提供的功能更强一些,但是准确率上个人感觉和 Readability 差不太多。

这个库分为 Python2 和 Python3 两个版本,Python2 下的版本叫做 newspaper,Python3 下的版本叫做 newspaper3k,这里我们使用 Python3 版本来进行测试。

其 GitHub 地址是:https://github.com/codelucas/newspaper,官方文档地址是:https://newspaper.readthedocs.io。

在安装之前需要安装一些依赖库,可以参考官方的说明:https://github.com/codelucas/newspaper#get-it-now。

安装好必要的依赖库之后,就可以使用 pip 安装了:

pip3 install newspaper3k

安装成功之后便可以导入使用了。

下面我们先用官方提供的实例来过一遍它的用法,官方提供的示例是使用了这个链接:https://fox13now.com/2013/12/30/new-year-new-laws-obamacare-pot-guns-and-drones/,其页面截图如下:

在这里插入图片描述
下面用一个实例来感受一下:

from newspaper import Article

url = 'https://fox13now.com/2013/12/30/new-year-new-laws-obamacare-pot-guns-and-drones/'
article = Article(url)
article.download()
# print('html:', article.html)

article.parse()
print('authors:', article.authors)
print('date:', article.publish_date)
print('text:', article.text)
print('top image:', article.top_image)
print('movies:', article.movies)

article.nlp()
print('keywords:', article.keywords)
print('summary:', article.summary)

这里从 newspaper 库里面先导入了 Article 这个类,然后直接传入 url 即可,首先需要调用它的 download 方法,将网页爬取下来,否则直接进行解析会抛出错误的。

好的,然后我们再执行 parse 方法进行网页的智能解析,这个功能就比较全了,能解析 authors、publish_date、text 等等,除了正文还能解析作者、发布时间等等。

另外这个库还提供了一些 NLP 的方法,比如获取关键词、获取文本摘要等等,在使用前需要先执行以下 nlp 方法。

最后运行结果如下:

authors: ['Cnn Wire']
date: 2013-12-30 00:00:00
text: By Leigh Ann Caldwell

WASHINGTON (CNN) — Not everyone subscribes to a New Year’s resolution, but Americans will be required to follow new laws in 2014.

Some 40,000 measures taking effect range from sweeping, national mandates under Obamacare to marijuana legalization in Colorado, drone prohibition in Illinois and transgender protections in California.

Although many new laws are controversial, they made it through legislatures, public referendum or city councils and represent the shifting composition of American beliefs.
...
...
Colorado: Marijuana becomes legal in the state for buyers over 21 at a licensed retail dispensary.

(Sourcing: much of this list was obtained from the National Conference of State Legislatures).
top image: https://localtvkstu.files.wordpress.com/2012/04/national-news-e1486938949489.jpg?quality=85&strip=all
movies: []
keywords: ['drones', 'national', 'guns', 'wage', 'law', 'pot', 'leave', 'family', 'states', 'state', 'latest', 'obamacare', 'minimum', 'laws']
summary: Oregon: Family leave in Oregon has been expanded to allow eligible employees two weeks of paid leave to handle the death of a family member.
Arkansas: The state becomes the latest state requiring voters show a picture ID at the voting booth.
Minimum wage and former felon employmentWorkers in 13 states and four cities will see increases to the minimum wage.
New Jersey residents voted to raise the state’s minimum wage by $1 to $8.25 per hour.
California is also raising its minimum wage to $9 per hour, but workers must wait until July to see the addition.

这里省略了一些输出结果。

可以看到作者、日期、正文、关键词、标签、缩略图等信息都被打印出来了,还算是不错的。

但这个毕竟是官方的实例,肯定是好的,我们再测试一下刚才的例子,看看效果如何,网址还是:https://tech.163.com/19/0909/08/EOKA3CFB00097U7S.html,改写代码如下:

from newspaper import Article

url = 'https://tech.163.com/19/0909/08/EOKA3CFB00097U7S.html'
article = Article(url, language='zh')
article.download()
# print('html:', article.html)

article.parse()
print('authors:', article.authors)
print('title:', article.title)
print('date:', article.publish_date)
print('text:', article.text)
print('top image:', article.top_image)
print('movies:', article.movies)

article.nlp()
print('keywords:', article.keywords)
print('summary:', article.summary)

这里我们将链接换成了新闻的链接,另外在 Article 初始化的时候还加了一个参数 language,其值为 zh,代表中文。

然后我们看下运行结果:

Building prefix dict from /usr/local/lib/python3.7/site-packages/jieba/dict.txt ...
Dumping model to file cache /var/folders/1g/l2xlw12x6rncs2p9kh5swpmw0000gn/T/jieba.cache
Loading model cost 1.7178938388824463 seconds.
Prefix dict has been built succesfully.
authors: []
title: 今年iPhone只有小改进?分析师:还有其他亮点
date: 2019-09-09 08:10:26+08:00
text: (原标题:Apple Bets More Cameras Can Keep iPhone Humming)

图示:苹果首席执行官蒂姆·库克(Tim Cook)6月份举行的苹果全球开发者大会上。

网易科技讯 99日消息,据国外媒体报道,和过去的12个年头一样,新款iPhone将成为苹果公司本周所举行年度宣传活动的主角。但人们的注意力正转向需要推动增长的其他苹果产品和服务。
...
...
Strategy Analytics的尼尔·莫斯顿(Neil Mawston)表示,可穿戴设备和服务的结合将是苹果业务超越iPhone的关键。他说,上一家手机巨头诺基亚公司在试图进行类似业务转型时就陷入了困境之中。(辰辰)

相关报道:

iPhone 11背部苹果Logo改为居中:为反向无线充电

2019年新iPhone传言汇总,你觉得哪些能成真
top image: https://www.163.com/favicon.ico
movies: []
keywords: ['trust高级投资组合经理丹摩根dan', 'iphone', 'mawston表示可穿戴设备和服务的结合将是苹果业务超越iphone的关键他说上一家手机巨头诺基亚公司在试图进行类似业务转型时就陷入了困境之中辰辰相关报道iphone', 'xs的销售疲软状况迫使苹果在1月份下调了业绩预期这是逾15年来的第一次据贸易公司susquehanna', 'xs机型发布后那种令人失望的业绩重演iphone', '今年iphone只有小改进分析师还有其他亮点', 'more', 'xr和iphone', 'morgan说他们现在没有任何真正深入的进展只是想继续让iphone这款业务继续转下去他乐观地认为今年发布的新款手机将有足够多的新功能为一个非常成熟的产品增加额外的功能让火车继续前进这种仅限于此的态度说明了苹果自2007年发布首款iphone以来所面临的挑战iphone销售占苹果公司总营收的一半以上这让苹果陷入了一个尴尬的境地既要维持核心产品的销量另一方面又需要减少对它的依赖瑞银ubs今年5月份对8000名智能手机用户进行了相关调查其发布的年度全球调查报告显示最近iphone在人脸识别技术等方面的进步并没有引起一些消费者的共鸣他们基本上都认为苹果产品没有过去几年那么独特或者惊艳品牌也没有过去几年那么有吸引力很多人使用老款手机的时间更长自己认为也没有必要升级到平均售价949美元的新款iphone苹果需要在明年销售足够多的iphone以避免像去年9月份iphone', 'keep', '原标题apple']
summary: (原标题:Apple Bets More Cameras Can Keep iPhone Humming)图示:苹果首席执行官蒂姆·库克(Tim Cook)6月份举行的苹果全球开发者大会上。网易科技讯 99日消息,据国外媒体报道,和过去的12个年头一样,新款iPhone将成为苹果公司本周所举行...亚公司在试图进行类似业务转型时就陷入了困境之中。(辰辰)相关报道:iPhone 11背部苹果Logo改为居中:为反向无线充电2019年新iPhone传言汇总,你觉得哪些能成真

中间正文很长省略了一部分,可以看到运行时首先加载了一些中文的库包,比如 jieba 所依赖的词表等等。

解析结果中,日期的确是解析对了,因为这个日期格式的的确比较规整,但这里还自动给我们加了东八区的时区,贴心了。作者没有提取出来,可能是没匹配到 来源 两个字吧,或者词库里面没有,标题、正文的提取还算比较正确,也或许这个案例的确是比较简单。

以上便是 Readability 和 Newspaper 的介绍。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37275405/article/details/103225099

智能推荐

class和struct的区别-程序员宅基地

文章浏览阅读101次。4.class可以有⽆参的构造函数,struct不可以,必须是有参的构造函数,⽽且在有参的构造函数必须初始。2.Struct适⽤于作为经常使⽤的⼀些数据组合成的新类型,表示诸如点、矩形等主要⽤来存储数据的轻量。1.Class⽐较适合⼤的和复杂的数据,表现抽象和多级别的对象层次时。2.class允许继承、被继承,struct不允许,只能继承接⼝。3.Struct有性能优势,Class有⾯向对象的扩展优势。3.class可以初始化变量,struct不可以。1.class是引⽤类型,struct是值类型。

android使用json后闪退,应用闪退问题:从json信息的解析开始就会闪退-程序员宅基地

文章浏览阅读586次。想实现的功能是点击顶部按钮之后按关键字进行搜索,已经可以从服务器收到反馈的json信息,但从json信息的解析开始就会闪退,加载listview也不知道行不行public abstract class loadlistview{public ListView plv;public String js;public int listlength;public int listvisit;public..._rton转json为什么会闪退

如何使用wordnet词典,得到英文句子的同义句_get_synonyms wordnet-程序员宅基地

文章浏览阅读219次。如何使用wordnet词典,得到英文句子的同义句_get_synonyms wordnet

系统项目报表导出功能开发_积木报表 多线程-程序员宅基地

文章浏览阅读521次。系统项目报表导出 导出任务队列表 + 定时扫描 + 多线程_积木报表 多线程

ajax 如何从服务器上获取数据?_ajax 获取http数据-程序员宅基地

文章浏览阅读1.1k次,点赞9次,收藏9次。使用AJAX技术的好处之一是它能够提供更好的用户体验,因为它允许在不重新加载整个页面的情况下更新网页的某一部分。另外,AJAX还使得开发人员能够创建更复杂、更动态的Web应用程序,因为它们可以在后台与服务器进行通信,而不需要打断用户的浏览体验。在Web开发中,AJAX(Asynchronous JavaScript and XML)是一种常用的技术,用于在不重新加载整个页面的情况下,从服务器获取数据并更新网页的某一部分。使用AJAX,你可以创建异步请求,从而提供更快的响应和更好的用户体验。_ajax 获取http数据

Linux图形终端与字符终端-程序员宅基地

文章浏览阅读2.8k次。登录退出、修改密码、关机重启_字符终端

随便推点

Python与Arduino绘制超声波雷达扫描_超声波扫描建模 python库-程序员宅基地

文章浏览阅读3.8k次,点赞3次,收藏51次。前段时间看到一位发烧友制作的超声波雷达扫描神器,用到了Arduino和Processing,可惜啊,我不会Processing更看不懂人家的程序,咋办呢?嘿嘿,所以我就换了个思路解决,因为我会一点Python啊,那就动手吧!在做这个案例之前先要搞明白一个问题:怎么将Arduino通过超声波检测到的距离反馈到Python端?这个嘛,我首先想到了串行通信接口。没错!就是串口。只要Arduino将数据发送给COM口,然后Python能从COM口读取到这个数据就可以啦!我先写了一个测试程序试了一下,OK!搞定_超声波扫描建模 python库

凯撒加密方法介绍及实例说明-程序员宅基地

文章浏览阅读4.2k次。端—端加密指信息由发送端自动加密,并且由TCP/IP进行数据包封装,然后作为不可阅读和不可识别的数据穿过互联网,当这些信息到达目的地,将被自动重组、解密,而成为可读的数据。不可逆加密算法的特征是加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,只有重新输入明文,并再次经过同样不可逆的加密算法处理,得到相同的加密密文并被系统重新识别后,才能真正解密。2.使用时,加密者查找明文字母表中需要加密的消息中的每一个字母所在位置,并且写下密文字母表中对应的字母。_凯撒加密

工控协议--cip--协议解析基本记录_cip协议embedded_service_error-程序员宅基地

文章浏览阅读5.7k次。CIP报文解析常用到的几个字段:普通类型服务类型:[0x00], CIP对象:[0x02 Message Router], ioi segments:[XX]PCCC(带cmd和func)服务类型:[0x00], CIP对象:[0x02 Message Router], cmd:[0x101], fnc:[0x101]..._cip协议embedded_service_error

如何在vs2019及以后版本(如vs2022)上添加 添加ActiveX控件中的MFC类_vs添加mfc库-程序员宅基地

文章浏览阅读2.4k次,点赞9次,收藏13次。有时候我们在MFC项目开发过程中,需要用到一些微软已经提供的功能,如VC++使用EXCEL功能,这时候我们就能直接通过VS2019到如EXCEL.EXE方式,生成对应的OLE头文件,然后直接使用功能,那么,我们上篇文章中介绍了vs2017及以前的版本如何来添加。但由于微软某些方面考虑,这种方式已被放弃。从上图中可以看出,这一功能,在从vs2017版本15.9开始,后续版本已经删除了此功能。那么我们如果仍需要此功能,我们如何在新版本中添加呢。_vs添加mfc库

frame_size (1536) was not respected for a non-last frame_frame_size (1024) was not respected for a non-last-程序员宅基地

文章浏览阅读785次。用ac3编码,执行编码函数时报错入如下:[ac3 @ 0x7fed7800f200] frame_size (1536) was not respected for anon-last frame (avcodec_encode_audio2)用ac3编码时每次送入编码器的音频采样数应该是1536个采样,不然就会报上述错误。这个数字并非刻意固定,而是跟ac3内部的编码算法原理相关。全网找不到,国内音视频之路还有很长的路,音视频人一起加油吧~......_frame_size (1024) was not respected for a non-last frame

Android移动应用开发入门_在安卓移动应用开发中要在活动类文件中声迷你一个复选框变量-程序员宅基地

文章浏览阅读230次,点赞2次,收藏2次。创建Android应用程序一个项目里面可以有很多模块,而每一个模块就对应了一个应用程序。项目结构介绍_在安卓移动应用开发中要在活动类文件中声迷你一个复选框变量

推荐文章

热门文章

相关标签