爬虫智能解析库 Readability 和 Newspaper 的用法

共 15628字,需浏览 32分钟

 ·

2019-09-09 23:20

阅读本文大概需要 10 分钟。


舆情爬虫是网络爬虫一个比较重要的分支,舆情爬虫往往需要爬虫工程师爬取几百几千个新闻站点。比如一个新闻页面我们需要爬取其标题、正文、时间、作者等信息,如果用传统的方式来实现,每一个站点都要配置非常多的规则,如果要维护一个几百上千的站点,那人力成本简直太高了。

如果有一种方式可以在保证差不多的准确率的前提下,大幅提高提取效率的话,就需要用到智能文本提取了。

本文首先介绍一下智能文本提取的基本原理,让大家对智能提取有基本的了解。然后介绍几个比较基础的工具包,准确率并不是很高,可以尝试一用。最后再介绍几篇比较前沿的技术供大家参考。

智能文本提取

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

  • 基于网页文档内容的提取方法

  • 基于 DOM 结构信息的提取方法

  • 基于视觉信息的提取方法

基于网页文档的提取方法将 HTML 文档视为文本进行处理,适用于处理含有大量文本信息且结构简单易于处理的单记录网页,或者具有实时要求的在线分析网页应用。这种方式主要利用自然语言处理相关技术实现,通过理解 文本语义、分析上下文、设定提取规则等,实现对大段网页文档的快速处理。其中,较为知名的方法有TSIMMIS、Web-OQL、Serrano、FAR-SW 和 FOREST,但这些方法由于通常需要人工的参与,且存在耗时长、效率低的弊端。

基于 DOM 结构信息的方法将 HTML 文档解析为相应的 DOM 树,然后根据 DOM 树的语法结构创建提取规则, 相对于以前的方法而言有了更高的性能和准确率。W4F 和 XWRAP 将 HTML 文档解析成 DOM 树,然后通过组件化引导用户通过人工选择或者标记生成目标包装器代码。Omini、IEPAD 和 ITE 提取 DOM 树上的关键路径, 获取其中存在的重复模式。MDR 和 DEPTA 挖掘了页面中的数据区域,得到数据记录的模式。CECWS 通过聚类算法从数据库中提取出自同一网站的一组页面,并进行 DOM 树结构的对比,删除其中的静态部分,保留动态内容作为信息提取的结果。虽然此类方法相对于上一类方法 具有较高的提取精度,且克服了对大段连续文本的依赖, 但由于网页的 DOM 树通常较深,含有大量 DOM 节点, 因此基于 DOM 结构信息的方法具有较高的时间和空间消耗。目前来说,大部分原理还是基于 DOM 节点的文本密度、标点符号密度等计算的,其准确率还是比较可观的。今天所介绍的 Readability 和 Newspaper 的库的实现原理就是类似。

目前比较先进的是基于视觉信息的网页信息提取方法,通过浏览器接口或者内核对目标网页预渲染,然后基于网页的视觉规律提取网页数据记录。经典的 VIPS 算法首先从 DOM 树中提取出所有合适的页面区域,然后根据这些页面和分割条重新构建 Web 页面的语义结构。作为对 VIPS 的拓展,ViNT、ViPER、ViDE 也成功利用了网页的视觉特征来实现数据提取。CMDR 为通过神经网络学习多记录型页面中的特征,结合基于 DOM 结构信息的 MDR 方法,挖掘社区论坛页面的数据区域。与上述方法不同,VIBS 将图像领域的 CNN 卷积神经网络运用于网页的截图,同时通过类 VIPS 算法生成视觉块,最后结合两个阶段的结果识别网页的正文区域。另外还有最新的国内提出的 VBIE 方法,基于网页视觉的基础上改进,可以实现无监督的网页信息提取。

以上内容主要参考自论文:《王卫红等:基于可视块的多记录型复杂网页信息提取算法》,算法可从该论文参考文献查阅。

下面我们来介绍两个比较基础的工具包 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,其页面截图如下:

57bc228417a4ce950cd47d22f9e902b7.webp页面示例

我们的目的就是它的正文、标题等内容。下面我们用 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,返回的结果则不会再带有 标签。

看下运行结果:

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>网易科技讯 9月9日消息,据国外媒体报道,和过去的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">责任编辑:王凤枝_NT2541span>
                        div>
                div
div>

可以看到,标题提取是正确的。正文其实也是正确的,不过这里还包含了一些 HTML 标签,比如

等,我们可以进一步通过一些解析库来解析。

看下源码吧,比如提取标题的方法:

def normalize_entities(cur_title):
    entities = {
        u'\u2014':'-',
        u'\u2013':'-',
        u'—''-',
        u'–''-',
        u'\u00A0'' ',
        u'\u00AB''"',
        u'\u00BB''"',
        u'"''"',
    }
    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 只解析了 </code> 标签里面的内容,别的没了。如果没有,那就返回 <code style="font-size:inherit;color:rgb(233,105,0);">[no-title]</code>。</p><pre style="font-size:inherit;color:inherit;"><code class="python language-python hljs" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);"><span class="hljs-function" style="font-size:inherit;color:rgb(248,35,117);"><span class="hljs-keyword" style="font-size:inherit;">def</span> <span class="hljs-title" style="font-size:inherit;color:rgb(165,218,45);">summary</span><span class="hljs-params" style="font-size:inherit;color:rgb(255,152,35);">(self, html_partial=False)</span>:</span><br />    ruthless = <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">True</span><br />    <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">while</span> <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">True</span>:<br />        self._html(<span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">True</span>)<br />        <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">for</span> i <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> self.tags(self.html, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'script'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'style'</span>):<br />            i.drop_tree()<br />        <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">for</span> i <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> self.tags(self.html, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'body'</span>):<br />            i.set(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'id'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'readabilityBody'</span>)<br />        <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">if</span> ruthless:<br />            self.remove_unlikely_candidates()<br />        self.transform_misused_divs_into_paragraphs()<br />        candidates = self.score_paragraphs()<br /><br />        best_candidate = self.select_best_candidate(candidates)<br /><br />        <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">if</span> best_candidate:<br />            article = self.get_article(candidates, best_candidate,<br />                                       html_partial=html_partial)<br />        <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">else</span>:<br />            <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">if</span> ruthless:<br />                ruthless = <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">False</span><br />                <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">continue</span><br />            <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">else</span>:<br />                article = self.html.find(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'body'</span>)<br />                <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">if</span> article <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">is</span> <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">None</span>:<br />                    article = self.html<br />        cleaned_article = self.sanitize(article, candidates)<br />        article_length = len(cleaned_article <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">or</span> <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">''</span>)<br />        retry_length = self.retry_length<br />        of_acceptable_length = article_length >= retry_length<br />        <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">if</span> ruthless <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">and</span> <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">not</span> of_acceptable_length:<br />            ruthless = <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">False</span><br />            <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">continue</span><br />        <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">else</span>:<br />            <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">return</span> cleaned_article<br /></code></pre><p style="font-size:inherit;color:inherit;">这里我删除了一些冗余的调试的代码,只保留了核心的代码,其核心实现就是先去除一些干扰内容,然后找出一些疑似正文的 candidates,然后再去寻找最佳匹配的 candidates 最后提取其内容返回即可。</p><p style="font-size:inherit;color:inherit;">然后再找到获取 candidates 方法里面的 score_paragraphs 方法,又追踪到一个 score_node 方法,就是为每一个节点打分的,其实现如下:</p><pre style="font-size:inherit;color:inherit;"><code class="python language-python hljs" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);"><span class="hljs-function" style="font-size:inherit;color:rgb(248,35,117);"><span class="hljs-keyword" style="font-size:inherit;">def</span> <span class="hljs-title" style="font-size:inherit;color:rgb(165,218,45);">score_node</span><span class="hljs-params" style="font-size:inherit;color:rgb(255,152,35);">(self, elem)</span>:</span><br />    content_score = self.class_weight(elem)<br />    name = elem.tag.lower()<br />    <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">if</span> name <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> [<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"div"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"article"</span>]:<br />        content_score += <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">5</span><br />    <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">elif</span> name <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> [<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"pre"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"td"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"blockquote"</span>]:<br />        content_score += <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">3</span><br />    <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">elif</span> name <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> [<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"address"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"ol"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"ul"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"dl"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"dd"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"dt"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"li"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"form"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"aside"</span>]:<br />        content_score -= <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">3</span><br />    <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">elif</span> name <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> [<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"h1"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"h2"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"h3"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"h4"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"h5"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"h6"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"th"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"header"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"footer"</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">"nav"</span>]:<br />        content_score -= <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">5</span><br />    <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">return</span> {<br />        <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'content_score'</span>: content_score,<br />        <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'elem'</span>: elem<br />    }<br /></code></pre><p style="font-size:inherit;color:inherit;">这什么意思呢?你看如果这个节点标签是 div 或者 article 等可能表征正文区块的话,就加 5 分,如果是 aside 等表示侧栏的内容就减 3 分。这些打分也没有什么非常标准的依据,可能是根据经验累积的规则。</p><p style="font-size:inherit;color:inherit;">另外还有一些方法里面引用了一些正则匹配来进行打分或者替换,其定义如下:</p><pre style="font-size:inherit;color:inherit;"><code class="python language-python hljs" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);">REGEXES = {<br />    <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'unlikelyCandidatesRe'</span>: re.compile(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'combx|comment|community|disqus|extra|foot|header|menu|remark|rss|shoutbox|sidebar|sponsor|ad-break|agegate|pagination|pager|popup|tweet|twitter'</span>, re.I),<br />    <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'okMaybeItsACandidateRe'</span>: re.compile(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'and|article|body|column|main|shadow'</span>, re.I),<br />    <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'positiveRe'</span>: re.compile(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'article|body|content|entry|hentry|main|page|pagination|post|text|blog|story'</span>, re.I),<br />    <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'negativeRe'</span>: re.compile(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget'</span>, re.I),<br />    <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'divToPElementsRe'</span>: re.compile(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'<(a|blockquote|dl|div|img|ol|p|pre|table|ul)'</span>, re.I),<br />    <span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">#'replaceBrsRe': re.compile('(<br[^>]*>[ \n\r\t]*){2,}',re.I),</span><br />    <span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">#'replaceFontsRe': re.compile('<(\/?)font[^>]*>',re.I),</span><br />    <span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">#'trimRe': re.compile('^\s+|\s+$/'),</span><br />    <span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">#'normalizeRe': re.compile('\s{2,}/'),</span><br />    <span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">#'killBreaksRe': re.compile('(<br\s*\/?>(\s| ?)*){1,}/'),</span><br />    <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'videoRe'</span>: re.compile(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'https?:\/\/(www\.)?(youtube|vimeo)\.com'</span>, re.I),<br />    <span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">#skipFootnoteLink:      /^\s*(\[?[a-z0-9]{1,2}\]?|^|edit|citation needed)\s*$/i,</span><br />}<br /></code></pre><p style="font-size:inherit;color:inherit;">比如这里定义了 unlikelyCandidatesRe,就是不像 candidates 的 pattern,比如 foot、comment 等等,碰到这样的标签或 pattern 的话,在计算分数的时候都会减分,另外还有其他的 positiveRe、negativeRe 也是一样的原理,分别对匹配到的内容进行加分或者减分。</p><p style="font-size:inherit;color:inherit;">这就是 Readability 的原理,是基于一些规则匹配的打分模型,很多规则其实来源于经验的累积,分数的计算规则应该也是不断地调优得出来的。</p><p style="font-size:inherit;color:inherit;">另外其他的就没了,Readability 并没有提供提取时间、作者的方法,另外此种方法的准确率也是有限的,但多少还是省去了一些人工成本。</p><h2 style="color:inherit;font-weight:bold;font-size:1.4em;"><span style="font-size:inherit;color:inherit;">Newspaper</span></h2><p style="font-size:inherit;color:inherit;">另外还有一个智能解析的库,叫做 Newspaper,提供的功能更强一些,但是准确率上个人感觉和 Readability 差不太多。</p><p style="font-size:inherit;color:inherit;">这个库分为 Python2 和 Python3 两个版本,Python2 下的版本叫做 newspaper,Python3 下的版本叫做 newspaper3k,这里我们使用 Python3 版本来进行测试。</p><p style="font-size:inherit;color:inherit;">其 GitHub 地址是:https://github.com/codelucas/newspaper,官方文档地址是:https://newspaper.readthedocs.io。</p><p style="font-size:inherit;color:inherit;">在安装之前需要安装一些依赖库,可以参考官方的说明:https://github.com/codelucas/newspaper#get-it-now。</p><p style="font-size:inherit;color:inherit;">安装好必要的依赖库之后,就可以使用 pip 安装了:</p><pre style="font-size:inherit;color:inherit;"><code class="hljs nginx" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);"><span class="hljs-attribute" style="font-size:inherit;color:rgb(238,220,112);">pip3</span> install newspaper3k<br /></code></pre><p style="font-size:inherit;color:inherit;">安装成功之后便可以导入使用了。</p><p style="font-size:inherit;color:inherit;">下面我们先用官方提供的实例来过一遍它的用法,官方提供的示例是使用了这个链接:https://fox13now.com/2013/12/30/new-year-new-laws-obamacare-pot-guns-and-drones/,其页面截图如下:</p><img src="https://filescdn.proginn.com/43918d2b3087a6fab418a091997d624c/08b5866adf53951af7455d1fb9bc5f81.webp" style="font-size:inherit;color:inherit;" alt="08b5866adf53951af7455d1fb9bc5f81.webp" />官方示例<p style="font-size:inherit;color:inherit;">下面用一个实例来感受一下:</p><pre style="font-size:inherit;color:inherit;"><code class="python language-python hljs" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);"><span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">from</span> newspaper <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">import</span> Article<br /><br />url = <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'https://fox13now.com/2013/12/30/new-year-new-laws-obamacare-pot-guns-and-drones/'</span><br />article = Article(url)<br />article.download()<br /><span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);"># print('html:', article.html)</span><br /><br />article.parse()<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'authors:'</span>, article.authors)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'date:'</span>, article.publish_date)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'text:'</span>, article.text)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'top image:'</span>, article.top_image)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'movies:'</span>, article.movies)<br /><br />article.nlp()<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'keywords:'</span>, article.keywords)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'summary:'</span>, article.summary)<br /></code></pre><p style="font-size:inherit;color:inherit;">这里从 newspaper 库里面先导入了 Article 这个类,然后直接传入 url 即可,首先需要调用它的 download 方法,将网页爬取下来,否则直接进行解析会抛出错误的。</p><blockquote style="font-size:.9em;color:rgb(129,145,152);"><p style="font-size:inherit;color:inherit;">但我总感觉这个设计挺不友好的,parse 方法不能判断下,如果没执行 download 就自动执行 download 方法吗?如果不 download 其他的不什么都干不了吗?</p></blockquote><p style="font-size:inherit;color:inherit;">好的,然后我们再执行 parse 方法进行网页的智能解析,这个功能就比较全了,能解析 authors、publish_date、text 等等,除了正文还能解析作者、发布时间等等。</p><p style="font-size:inherit;color:inherit;">另外这个库还提供了一些 NLP 的方法,比如获取关键词、获取文本摘要等等,在使用前需要先执行以下 nlp 方法。</p><p style="font-size:inherit;color:inherit;">最后运行结果如下:</p><pre style="font-size:inherit;color:inherit;"><code class="hljs delphi" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);">authors: [<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'Cnn Wire'</span>]<br />date: <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">2013</span>-<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">12</span>-<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">30</span> <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">00</span>:<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">00</span>:<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">00</span><br />text: By Leigh Ann Caldwell<br /><br />WASHINGTON (CNN) — <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">Not</span> everyone subscribes <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> a New Year’s resolution, but Americans will be required <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> follow new laws <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">2014</span>.<br /><br />Some <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">40</span>,<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">000</span> measures taking effect range from sweeping, national mandates under Obamacare <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> marijuana legalization <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> Colorado, drone prohibition <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> Illinois <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">and</span> transgender protections <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> California.<br /><br />Although many new laws are controversial, they made it through legislatures, <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">public</span> referendum <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">or</span> city councils <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">and</span> represent the shifting composition <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">of</span> American beliefs.<br />...<br />...<br />Colorado: Marijuana becomes legal <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> the state <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">for</span> buyers over <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">21</span> at a licensed retail dispensary.<br /><br />(Sourcing: much <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">of</span> this list was obtained from the National Conference <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">of</span> State Legislatures).<br />top image: https:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//localtvkstu.files.wordpress.com/2012/04/national-news-e1486938949489.jpg?quality=85&strip=all</span><br />movies: []<br />keywords: [<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'drones'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'national'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'guns'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'wage'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'law'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'pot'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'leave'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'family'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'states'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'state'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'latest'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'obamacare'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'minimum'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'laws'</span>]<br />summary: Oregon: Family leave <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> Oregon has been expanded <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> allow eligible employees two weeks <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">of</span> paid leave <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> handle the death <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">of</span> a family member.<br />Arkansas: The state becomes the latest state requiring voters show a picture ID at the voting booth.<br />Minimum wage <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">and</span> former felon employmentWorkers <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">13</span> states <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">and</span> four cities will see increases <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> the minimum wage.<br />New Jersey residents voted <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">raise</span> the state’s minimum wage by $<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">1</span> <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> $<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">8.25</span> per hour.<br />California <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">is</span> also raising its minimum wage <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> $<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">9</span> per hour, but workers must wait <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">until</span> July <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">to</span> see the addition.<br /></code></pre><p style="font-size:inherit;color:inherit;">这里省略了一些输出结果。</p><p style="font-size:inherit;color:inherit;">可以看到作者、日期、正文、关键词、标签、缩略图等信息都被打印出来了,还算是不错的。</p><p style="font-size:inherit;color:inherit;">但这个毕竟是官方的实例,肯定是好的,我们再测试一下刚才的例子,看看效果如何,网址还是:https://tech.163.com/19/0909/08/EOKA3CFB00097U7S.html,改写代码如下:</p><pre style="font-size:inherit;color:inherit;"><code class="python language-python hljs" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);"><span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">from</span> newspaper <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">import</span> Article<br /><br />url = <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'https://tech.163.com/19/0909/08/EOKA3CFB00097U7S.html'</span><br />article = Article(url, language=<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'zh'</span>)<br />article.download()<br /><span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);"># print('html:', article.html)</span><br /><br />article.parse()<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'authors:'</span>, article.authors)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'title:'</span>, article.title)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'date:'</span>, article.publish_date)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'text:'</span>, article.text)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'top image:'</span>, article.top_image)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'movies:'</span>, article.movies)<br /><br />article.nlp()<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'keywords:'</span>, article.keywords)<br />print(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'summary:'</span>, article.summary)<br /></code></pre><p style="font-size:inherit;color:inherit;">这里我们将链接换成了新闻的链接,另外在 Article 初始化的时候还加了一个参数 language,其值为 zh,代表中文。</p><p style="font-size:inherit;color:inherit;">然后我们看下运行结果:</p><pre style="font-size:inherit;color:inherit;"><code class="hljs sql" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);">Building prefix dict from /usr/local/lib/python3.7/site-packages/jieba/dict.txt ...<br />Dumping model to file <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">cache</span> /<span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">var</span>/folders/<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">1</span>g/l2xlw12x6rncs2p9kh5swpmw0000gn/T/jieba.cache<br />Loading <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">model</span> <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">cost</span> <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">1.7178938388824463</span> seconds.<br />Prefix dict has been built succesfully.<br /><span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">authors</span>: []<br />title: 今年iPhone只有小改进?分析师:还有其他亮点<br /><span class="hljs-built_in" style="font-size:inherit;color:rgb(248,35,117);">date</span>: <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">2019</span><span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">-09</span><span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">-09</span> <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">08</span>:<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">10</span>:<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">26</span>+<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">08</span>:<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">00</span><br /><span class="hljs-built_in" style="font-size:inherit;color:rgb(248,35,117);">text</span>: (原标题:Apple Bets More Cameras Can <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">Keep</span> iPhone Humming)<br /><br />图示:苹果首席执行官蒂姆·库克(Tim Cook)在<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">6</span>月份举行的苹果全球开发者大会上。<br /><br />网易科技讯 <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">9</span>月<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">9</span>日消息,据国外媒体报道,和过去的<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">12</span>个年头一样,新款iPhone将成为苹果公司本周所举行年度宣传活动的主角。但人们的注意力正转向需要推动增长的其他苹果产品和服务。<br />...<br />...<br />Strategy Analytics的尼尔·莫斯顿(Neil Mawston)表示,可穿戴设备和服务的结合将是苹果业务超越iPhone的关键。他说,上一家手机巨头诺基亚公司在试图进行类似业务转型时就陷入了困境之中。(辰辰)<br /><br />相关报道:<br /><br />iPhone <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">11</span>背部苹果Logo改为居中:为反向无线充电<br /><br /><span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">2019</span>年新iPhone传言汇总,你觉得哪些能成真<br />top image: https://www<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">.163</span>.com/favicon.ico<br />movies: []<br />keywords: [<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'trust高级投资组合经理丹摩根dan'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'iphone'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'mawston表示可穿戴设备和服务的结合将是苹果业务超越iphone的关键他说上一家手机巨头诺基亚公司在试图进行类似业务转型时就陷入了困境之中辰辰相关报道iphone'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'xs的销售疲软状况迫使苹果在1月份下调了业绩预期这是逾15年来的第一次据贸易公司susquehanna'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'xs机型发布后那种令人失望的业绩重演iphone'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'今年iphone只有小改进分析师还有其他亮点'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'more'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'xr和iphone'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'morgan说他们现在没有任何真正深入的进展只是想继续让iphone这款业务继续转下去他乐观地认为今年发布的新款手机将有足够多的新功能为一个非常成熟的产品增加额外的功能让火车继续前进这种仅限于此的态度说明了苹果自2007年发布首款iphone以来所面临的挑战iphone销售占苹果公司总营收的一半以上这让苹果陷入了一个尴尬的境地既要维持核心产品的销量另一方面又需要减少对它的依赖瑞银ubs今年5月份对8000名智能手机用户进行了相关调查其发布的年度全球调查报告显示最近iphone在人脸识别技术等方面的进步并没有引起一些消费者的共鸣他们基本上都认为苹果产品没有过去几年那么独特或者惊艳品牌也没有过去几年那么有吸引力很多人使用老款手机的时间更长自己认为也没有必要升级到平均售价949美元的新款iphone苹果需要在明年销售足够多的iphone以避免像去年9月份iphone'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'keep'</span>, <span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'原标题apple'</span>]<br />summary: (原标题:Apple Bets More Cameras Can <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">Keep</span> iPhone Humming)图示:苹果首席执行官蒂姆·库克(Tim Cook)在<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">6</span>月份举行的苹果全球开发者大会上。网易科技讯 <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">9</span>月<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">9</span>日消息,据国外媒体报道,和过去的<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">12</span>个年头一样,新款iPhone将成为苹果公司本周所举行...亚公司在试图进行类似业务转型时就陷入了困境之中。(辰辰)相关报道:iPhone <span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">11</span>背部苹果Logo改为居中:为反向无线充电<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">2019</span>年新iPhone传言汇总,你觉得哪些能成真<br /></code></pre><p style="font-size:inherit;color:inherit;">中间正文很长省略了一部分,可以看到运行时首先加载了一些中文的库包,比如 jieba 所依赖的词表等等。</p><p style="font-size:inherit;color:inherit;">解析结果中,日期的确是解析对了,因为这个日期格式的的确比较规整,但这里还自动给我们加了东八区的时区,贴心了。作者没有提取出来,可能是没匹配到 <code style="font-size:inherit;color:rgb(233,105,0);">来源</code> 两个字吧,或者词库里面没有,标题、正文的提取还算比较正确,也或许这个案例的确是比较简单。</p><p style="font-size:inherit;color:inherit;">另外对于 NLP 部分,获取的关键词比较迷,长度有点太长了。summary 也有点冗余。</p><p style="font-size:inherit;color:inherit;">另外 Newspaper 还提供了一个较为强大的功能,就是 build 构建信息源。官方的介绍其功能就是构建一个新闻源,可以根据传入的 URL 来提取相关文章、分类、RSS 订阅信息等等。</p><p style="font-size:inherit;color:inherit;">我们用实例感受一下:</p><pre style="font-size:inherit;color:inherit;"><code class="python language-python hljs" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);"><span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">import</span> newspaper<br /><br />source = newspaper.build(<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'http://www.sina.com.cn/'</span>, language=<span class="hljs-string" style="font-size:inherit;color:rgb(238,220,112);">'zh'</span>)<br /><span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">for</span> category <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> source.category_urls():<br />    print(category)<br /><br /><span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">for</span> article <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> source.articles:<br />    print(article.url)<br />    print(article.title)<br /><br /><span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">for</span> feed_url <span class="hljs-keyword" style="font-size:inherit;color:rgb(248,35,117);">in</span> source.feed_urls():<br />    print(feed_url)<br /></code></pre><p style="font-size:inherit;color:inherit;">在这里我们传入了新浪的官网,调用了 build 方法,构建了一个 source,然后输出了相关的分类、文章、RSS 订阅等内容,运行结果如下:</p><pre style="font-size:inherit;color:inherit;"><code class="hljs cpp" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);">http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//cul.news.sina.com.cn</span><br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//www.sina.com.cn/</span><br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//sc.sina.com.cn</span><br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//jiangsu.sina.com.cn</span><br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//gif.sina.com.cn</span><br />....<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//tj.sina.com.cn</span><br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//travel.sina.com.cn</span><br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//jiaoyi.sina.com.cn</span><br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//cul.sina.com.cn</span><br />https:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//finance.sina.com.cn/roll/2019-06-12/doc-ihvhiqay5022316.shtml </span><br />经参头版:激发微观主体活力加速国企改革<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//eladies.sina.com.cn/feel/xinli/2018-01-25/0722/doc-ifyqwiqk0463751.shtml </span><br />我们别再联系了<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//finance.sina.com.cn/roll/2018-05-13/doc-ihamfahx2958233.shtml </span><br />新违约时代到来!违约“常态化”下的市场出清与换血<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//sports.sina.com.cn/basketball/2019worldcup/2019-09-08/doc-iicezzrq4390554.shtml </span><br />罗健儿<span class="hljs-number" style="font-size:inherit;color:rgb(174,135,250);">26</span>分韩国收首胜<br />...<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//travel.sina.com.cn/outbound/pages/2019-09-05/detail-iicezzrq3622449.shtml </span><br />菲律宾海滨大道 夜晚让人迷离<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//travel.sina.com.cn/outbound/pages/2016-08-19/detail-ifxvcnrv0334779.shtml  </span><br />关岛 用双脚尽情享受阳光与海滩<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//travel.sina.com.cn/domestic/pages/2019-09-04/detail-iicezzrq3325092.shtml </span><br />秋行查干浩特草原<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//travel.sina.com.cn/outbound/pages/2019-09-03/detail-iicezueu3050710.shtml </span><br />白羊座的土豪之城迪拜<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//travel.sina.com.cn/video/baidang/2019-08-29/detail-ihytcitn2747327.shtml </span><br />肯辛顿宫藏着维多利亚的秘密<br />http:<span class="hljs-comment" style="font-size:inherit;color:rgb(128,128,128);">//cd.auto.sina.com.cn/bdcs/2017-08-15/detail-ifyixias1051586.shtml </span><br /></code></pre><p style="font-size:inherit;color:inherit;">可以看到它输出了非常多的类别链接,另外还有很多文章列表,由于没有 RSS 订阅内容,这里没有显示。</p><p style="font-size:inherit;color:inherit;">下面把站点换成我的博客:https://cuiqingcai.com,博客截图如下:</p><p style="text-align:center;"><img class="rich_pages" src="https://filescdn.proginn.com/a5997f42ee7d07da00e227c286edef0e/99e4d4278f547a0ceab037c3a5ebbcee.webp" alt="99e4d4278f547a0ceab037c3a5ebbcee.webp" /></p><p style="font-size:inherit;color:inherit;text-align:center;"><span style="color:rgb(153,153,153);font-size:.7em;text-align:center;">博客截图</span></p><p style="font-size:inherit;color:inherit;text-align:left;">看看运行结果:</p><pre style="font-size:inherit;color:inherit;"><code class="python language-python hljs" style="font-size:14px;font-family:Consolas, Inconsolata, Courier, monospace;color:rgb(169,183,198);">https://cuiqingcai.com<br />https://cuiqingcai.com<br /></code></pre><p style="font-size:inherit;color:inherit;">似乎不太行啊,一篇文章都没有,RSS 也没有,可见其功能还有待优化。</p><p style="font-size:inherit;color:inherit;">Newspaper 的基本用法介绍到这里,更加详细的用法可以参考官方文档:https://newspaper.readthedocs.io。个人感觉其中的智能解析可以用用,不过据我的个人经验,感觉还是很多解析不对或者解析不全的,</p><p style="font-size:inherit;color:inherit;">以上便是 Readability 和 Newspaper 的介绍。</p><h2 style="color:inherit;font-weight:bold;font-size:1.4em;"><span style="font-size:inherit;color:inherit;">其他方案</span></h2><p style="font-size:inherit;color:inherit;">另外除了这两个库其实还有一些比较优秀的算法,由于我们处理的大多为中文文档,所以一些在中文上面的研究是比较有效的,在这里列几个值得借鉴的中文论文供大家参考:</p><ul class="list-paddingleft-2"><li><p><span style="font-size:inherit;color:inherit;">洪鸿辉等,基于文本及符号密度的网页正文提取方法</span></p></li><li><p><span style="font-size:inherit;color:inherit;">梁东等,基于支持向量机的网页正文内容提取方法</span></p></li><li><p><span style="font-size:inherit;color:inherit;">王卫红等,基于可视块的多记录型复杂网页信息提取算法</span></p></li></ul><p style="font-size:inherit;color:inherit;">今天还看到一位大佬「青南」根据上面第一篇论文所实现的 GeneralNewsExtractor,GitHub 地址为:https://github.com/kingname/GeneralNewsExtractor,经测试准确率还不错,比 Readability 和 Newspaper 的解析效果要好。我也跟作者进行了交流,后续可能还会基于其他的 Feature 或依赖于视觉化的方法进行优化,大家可以关注下,谢谢!</p><p><strong>崔庆才</strong></p><p><span style="font-size:12px;">静觅博客博主,</span><span style="font-size:12px;">《Python3网络爬虫开发实战》作者</span></p><p><span style="font-size:10px;">隐形字</span></p><p><span style="font-size:12px;">个人公众号:进击的Coder</span></p><img src="https://filescdn.proginn.com/8f2ef2984cf3580628f3eeb37fd8bca0/b4f71f7c41519fcf04274288487d202c.webp" alt="b4f71f7c41519fcf04274288487d202c.webp" /><img src="https://filescdn.proginn.com/3b94682d3e1cefc1e159d883b0320669/72042c2afedbe564d7443a90e39ca726.webp" alt="72042c2afedbe564d7443a90e39ca726.webp" /><p>长按识别二维码关注</p><p style="font-size:15px;font-family:Avenir, '-apple-system-font', '微软雅黑', sans-serif;color:rgb(74,74,74);text-align:left;"><br /></p><span style="color:rgb(0,0,0);">好文和朋友一起看~</span></div></div><div class="tag-list-box"><div class="tag-list"><div class="tag-list-container"></div></div></div><span class="view_num">浏览 1</span><div class="float-bar float-bar-relative" id="float-bar-relative"><div class="float-bar-body"><div class="item qinglite-zan"><i class="iconfont icon-dianzan"></i>点赞 </div><div class="gap"></div><a href="#comments" class="item"><i class="iconfont iconfont icon-pinglun1"></i><span class="com_num"></span>评论 </a><div class="item qinglite-collect"><i class="iconfont icon-shoucang"></i>收藏 </div><div class="item qinglite_share"><i class="iconfont icon-fenxiang1"></i>分享 <div class="qrcode-modal"><img src="/api/pub/ewm" alt=""><p>手机扫一扫分享</p></div></div><div class="expand"></div><a onclick="miniProgram_navigateTo_func()" class="item qinglite_share_miniapp miniapp_show"><i class="iconfont icon-fenxiang1"></i>分享 </a><div class="item jubao qinglite-jubao miniapp_hide"><i class="iconfont icon-jubao"></i> 举报 </div></div></div></div><div class="comments_wrapper comments"><div class="title">评论</div><div id="comments" class="comments"><div class="error"></div><div class="textarea-wrapper"><textarea class="comment-content" cols="30" rows="5" placeholder="输入评论"></textarea></div><div class="button"><div class="error"><div class="comment-emojis"><div class="comment-choose-img qinglite_upload"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-tupianyangshi2"></use></svg><span>图片</span></div><div class="comment-choose-img comment-emoji-btn"><svg class="icon show-emoji-list" aria-hidden="true"><use xlink:href="#icon-biaoqing"></use></svg><span class="show-emoji-list">表情</span><div class="comment-emoji-list"></div></div><div style="display: none" class="comment-choose-img"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-shipinwenjian1"></use></svg><span>视频</span></div></div></div><button class="qinglite-comment">评价</button></div><div class="medias qinglite_upload_content"></div></div></div><div style="display: none" class="comments"><div class="title">全部评论</div><div class="comments comment-item-content"></div></div><div id="recommend" class="comments hide_app"><div class="title">推荐 <a href="#qs_detail" class="iconfont icon-huidaodingbu"></a></div></div><div class="qs_post_list flow_post_list hide_app"><div class="item qinglite_item qinglite_item_news"><a href="/pedia/f0056515650c7023439ed" title="readability" class="content"><div class="qinglite_item_top_wrapper"><div class="title">readability</div><div class="right-top-icon-tag"></div></div><div class="desc">ReadabilityReadabilityisatoolforextractingandcuratingtheprimaryreadablecontentofawebpage.CheckoutThe</div></a></div><div class="item img qinglite_item"><a href="/doc/88126475f5c171537" title="细说SpringAOP的核心用法和原理解析" class="content"><div class="bg" style="background-image:url(https://filescdn.proginn.com/50c0ead46502f29c3449d61bfbffeb61/f76a1d13667212cae7d79ddbeaf74388.webp?x-oss-process=image/resize,w_300)"></div></a><a href="/doc/88126475f5c171537" title="细说SpringAOP的核心用法和原理解析" class="title_middle">细说SpringAOP的核心用法和原理解析</a><a href="https://jishu.proginn.com/u/6585647577445a29e" title="Java技术迷" class="up_info"><div style="background-image:url(https://inn.proginn.com/useralbum/575827/cps_wx_01788d3de241.jpg!mediumicon?imageMogr2/format/webp/thumbnail/!200x200r)" class="avatar"></div><div class="username">Java技术迷</div><div class="expand"></div><div class="likes"><i class="iconfont icon-dianzan"></i></div><span class="num">0</span></a></div><div class="item qinglite_item qinglite_item_news"><a href="/doc/f0055465650c61b4cf68e" title="SGMLReaderHTML 和 SGML 解析库" class="content"><div class="qinglite_item_top_wrapper"><div class="title">SGMLReaderHTML 和 SGML 解析库</div><div class="right-top-icon-tag"></div></div><div class="desc">SgmlReader 是一个敏捷的 C# .NET 库,通过 XmlReader API 解析 HT</div></a></div><div class="item img qinglite_item"><a href="/doc/326264757c2924239" title="Python解析库lxml与xpath用法总结" class="content"><div class="bg" style="background-image:url(https://filescdn.proginn.com/446712090f1edadfe8b5721b19dd347a/738fef3a0b3cefa00375328d3c45457a.webp?x-oss-process=image/resize,w_300)"></div></a><a href="/doc/326264757c2924239" title="Python解析库lxml与xpath用法总结" class="title_middle">Python解析库lxml与xpath用法总结</a><a href="https://jishu.proginn.com/u/4917646d3cc66077f" title="Python爬虫与数据挖掘" class="up_info"><div style="background-image:url(https://inn.proginn.com/useralbum/519930/cps_wx_017617091c69.jpg!mediumicon?imageMogr2/format/webp/thumbnail/!200x200r)" class="avatar"></div><div class="username">Python爬虫与数据挖掘</div><div class="expand"></div><div class="likes"><i class="iconfont icon-dianzan"></i></div><span class="num">0</span></a></div><div class="item qinglite_item qinglite_item_news"><a href="/pedia/f0051081650c61b3a6e12" title="SGMLReaderHTML 和 SGML 解析库" class="content"><div class="qinglite_item_top_wrapper"><div class="title">SGMLReaderHTML 和 SGML 解析库</div><div class="right-top-icon-tag"></div></div><div class="desc">SgmlReader是一个敏捷的C#.NET库,通过XmlReaderAPI解析HTML和SGML文件。同时提供一个命令行工具可以对这些内容进行格式化输出到XML结果。示例代码:XmlDocument</div></a></div><div class="item img qinglite_item"><a href="/doc/77546474d2df061ec" title="Python解析库lxml与xpath用法总结" class="content"><div class="bg" style="background-image:url(https://filescdn.proginn.com/bbca7ffa2ddf02caba8c908ae7196571/074a8b8e48598bcffaa5dfc3db6f25b9.webp?x-oss-process=image/resize,w_300)"></div></a><a href="/doc/77546474d2df061ec" title="Python解析库lxml与xpath用法总结" class="title_middle">Python解析库lxml与xpath用法总结</a><a href="https://jishu.proginn.com/u/4709646ef83610820" title="IT共享之家" class="up_info"><div style="background-image:url(https://inn.proginn.com/useralbum/522178/cps_wx_017660a47959.jpg!mediumicon?imageMogr2/format/webp/thumbnail/!200x200r)" class="avatar"></div><div class="username">IT共享之家</div><div class="expand"></div><div class="likes"><i class="iconfont icon-dianzan"></i></div><span class="num">0</span></a></div><div class="item qinglite_item qinglite_item_news"><a href="/pedia/f0057338651506de96e3b" title="J-TMXTMX 解析和渲染库" class="content"><div class="qinglite_item_top_wrapper"><div class="title">J-TMXTMX 解析和渲染库</div><div class="right-top-icon-tag"></div></div><div class="desc">J-TMX是一个用来解析和渲染TMX(TranslationMemoryeXchange)文件的Java库。使用JavaSAX解析器来解析TMX。示例代码://Create New Map Insta</div></a></div><div class="item qinglite_item qinglite_item_news"><a href="/doc/f0056422651506df9605c" title="J-TMXTMX 解析和渲染库" class="content"><div class="qinglite_item_top_wrapper"><div class="title">J-TMXTMX 解析和渲染库</div><div class="right-top-icon-tag"></div></div><div class="desc">J-TMX 是一个用来解析和渲染 TMX (Translation Memory eXchange)</div></a></div><div class="item qinglite_item qinglite_item_news"><a href="/doc/f00532886517ce66127b9" title="PegdownJava 的 Markdown 解析库" class="content"><div class="qinglite_item_top_wrapper"><div class="title">PegdownJava 的 Markdown 解析库</div><div class="right-top-icon-tag"></div></div><div class="desc">Pegdown 是基于 parboiled (PEG parser) 完全使用 Java 实现的轻量</div></a></div><div class="item qinglite_item qinglite_item_news"><a href="/pedia/f005721565155549dac24" title="FlankerPython 的 Email 解析库" class="content"><div class="qinglite_item_top_wrapper"><div class="title">FlankerPython 的 Email 解析库</div><div class="right-top-icon-tag"></div></div><div class="desc">Flanker是一个用来解析电子邮件和MIME的Python库。示例代码:>>>fromflanker.addresslibimportaddress>>>></div></a></div><i></i><i></i><i></i><i></i><i></i></div><div class="float-bar" id="float-bar"><div class="float-bar-body"><div class="item qinglite-zan"><i class="iconfont icon-dianzan"></i>点赞 </div><div class="gap"></div><a href="#comments" class="item"><i class="iconfont iconfont icon-pinglun1"></i><span class="com_num"></span>评论 </a><div class="item qinglite-collect"><i class="iconfont icon-shoucang"></i>收藏 </div><div class="item qinglite_share"><i class="iconfont icon-fenxiang1"></i>分享 <div class="qrcode-modal"><img src="/api/pub/ewm" alt=""><p>手机扫一扫分享</p></div></div><div class="expand"></div><a onclick="miniProgram_navigateTo_func()" class="item qinglite_share_miniapp miniapp_show"><i class="iconfont icon-fenxiang1"></i>分享 </a><div class="item jubao qinglite-jubao miniapp_hide"><i class="iconfont icon-jubao"></i> 举报 </div><a href="#recommend" class="item iconfont icon-huidaodingbu"></a></div></div></article></div></main><script> let act_type = 1; let act_pro_id="11746"; let act_point = 0; let act_kind = 0; let act_time =210000; let act_page_id=""; </script><footer id="footer"><div class="container"><div class="links"><i class="copyright">2023©技术圈</i><a href="https://jishu.proginn.com">隐私协议</a><a href="https://jishu.proginn.com">用户协议</a><a href="https://jishu.proginn.com/about">关于我们</a></div></div></footer><link href="https://qinglite-1253448069.cos.ap-shanghai.myqcloud.com/css/layui/css/layui.css" rel="stylesheet"><script src="https://qinglite-1253448069.cos.ap-shanghai.myqcloud.com/css/layui/layui.js?v=v202311290135"></script><script> var $ = layui.jquery; </script><script src="https://cdn.qinglite.cn/js/pub.js?v=v202311290135"></script><script src="https://cdn.qinglite.cn/js/news_info.js?v=v202311290135"></script><link rel="stylesheet" href="https://qinglite-1253448069.cos.ap-shanghai.myqcloud.com/css/icon/iconfont.css?v=v202311290135"><script src="https://qinglite-1253448069.cos.ap-shanghai.myqcloud.com/css/icon/iconfont.js?v=v202311290135"></script></body></html>