2024年最全python爬虫智能解析库详解_python智能解析列表 标题 url 时间

总之,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>网易科技讯 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">责任编辑:王凤枝_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,}/'),


做了那么多年开发,自学了很多门编程语言,我很明白学习资源对于学一门新语言的重要性,这些年也收藏了不少的Python干货,对我来说这些东西确实已经用不到了,但对于准备自学Python的人来说,或许它就是一个宝藏,可以给你省去很多的时间和精力。



别在网上瞎学了,我最近也做了一些资源的更新,只要你是我的粉丝,这期福利你都可拿走。

我先来介绍一下这些东西怎么用,文末抱走。

* * *



**(1)Python所有方向的学习路线(新版)**

这是我花了几天的时间去把Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。



最近我才对这些路线做了一下新的更新,知识体系更全面了。



![在这里插入图片描述](https://img-blog.csdnimg.cn/8fc093dcfa1f476694c574db1242c05b.png)



**(2)Python学习视频**



包含了Python入门、爬虫、数据分析和web开发的学习视频,总共100多个,虽然没有那么全面,但是对于入门来说是没问题的,学完这些之后,你可以按照我上面的学习路线去网上找其他的知识资源进行进阶。



![在这里插入图片描述](https://img-blog.csdnimg.cn/d66e3ad5592f4cdcb197de0dc0438ec5.png#pic_center)



**(3)100多个练手项目**

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了,只是里面的项目比较多,水平也是参差不齐,大家可以挑自己能做的项目去练练。



![在这里插入图片描述](https://img-blog.csdnimg.cn/f5aeb4050ab547cf90b1a028d1aacb1d.png#pic_center)



**(4)200多本电子书**  

  

这些年我也收藏了很多电子书,大概200多本,有时候带实体书不方便的话,我就会去打开电子书看看,书籍可不一定比视频教程差,尤其是权威的技术书籍。



基本上主流的和经典的都有,这里我就不放图了,版权问题,个人看看是没有问题的。



**(5)Python知识点汇总**

知识点汇总有点像学习路线,但与学习路线不同的点就在于,知识点汇总更为细致,里面包含了对具体知识点的简单说明,而我们的学习路线则更为抽象和简单,只是为了方便大家只是某个领域你应该学习哪些技术栈。



![在这里插入图片描述](https://img-blog.csdnimg.cn/c741a91b05a542ba9dc8abf2f2f4b1af.png)



**(6)其他资料**



还有其他的一些东西,比如说我自己出的Python入门图文类教程,没有电脑的时候用手机也可以学习知识,学会了理论之后再去敲代码实践验证,还有Python中文版的库资料、MySQL和HTML标签大全等等,这些都是可以送给粉丝们的东西。



![在这里插入图片描述](https://img-blog.csdnimg.cn/9fa77af248b84885a6ec779b2ead064d.png)

**这些都不是什么非常值钱的东西,但对于没有资源或者资源不是很好的学习者来说确实很不错,你要是用得到的话都可以直接抱走,关注过我的人都知道,这些都是可以拿到的。**




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值