抓取网页新闻(一个典型的新闻网页包括几个不同区域:html代码部分千差万别)

优采云 发布时间: 2022-01-23 00:10

  抓取网页新闻(一个典型的新闻网页包括几个不同区域:html代码部分千差万别)

  我们之前实现的新闻爬虫,运行后可以快速爬取大量新闻网页。网页的所有html代码都存储在数据库中,这不是我们想要的最终结果。最终结果应该是结构化数据,至少包括url、title、发布时间、body内容、来源网站等。

  

  提取网页正文的方法

  所以爬虫不仅要做好下载的工作,还要做好数据的清洗和提取工作。所以,写爬虫是综合能力的体现。

  一个典型的新闻页面由几个不同的区域组成:

  

  新闻页面区

  我们要提取的新闻元素收录在:

  导航栏区域和相关链接区域的文字不属于新闻元素。

  新闻的标题、发布时间、正文内容一般都是从我们爬取的html中提取出来的。如果只是网站的新闻页面,提取这三个内容非常简单,写三个正则表达式就可以完美提取。但是,我们的爬虫会爬取数百个 网站 页面。为这么多不同格式的网页写正则表达式会很累,一旦网页稍作修改,表达式可能会失效,维护这些表达式也会很累。

  当然,累死人的做法是想不通的,我们要探索一个好的算法来实现。

  1. 标题提取

  标题基本出现在html标签中,只是附加了频道名称、网站名称等信息;

  标题也出现在网页的“标题区域”中。

  那么在这两个地方,哪里更容易提取title呢?

  网页的“header area”没有明确标识,不同网站的“header area”的html代码部分差异很大。所以这个区域不容易提取。

  然后就只剩下标签了。这个标签很容易提取,不管是正则表达式还是lxml解析。不容易的是如何去除频道名称、网站名称等信息。

  我们先来看看,标签中的附加信息是长什么样子的:

  观察这些标题不难发现,新闻标题与频道名称和网站名称之间存在一些联系符号。然后我可以通过这些连接器拆分标题,发现最长的部分是新闻标题。

  这个想法也很容易实现,所以这里就不写代码了,留给小猿作为思考练习自己实现吧。

  2. 发布时间提取

  发布时间是指页面在网站上启动的时间。一般会出现在文本标题下方——元数据区。从html代码来看,这个区域并没有什么特别的特征可供我们定位,尤其是面对大量的网站布局,几乎不可能定位到这个区域。这需要我们采取不同的方法。

  和标题一样,我们来看看一些网站的发布时间是怎么写的:

  这些写在网页上的发布时间有一个共同的特点,就是一个字符串代表时间,年、月、日、时、分、秒,无非就是这些元素。通过正则表达式,我们列出了一些具有不同时间表达式的正则表达式(只是几个),然后我们可以通过匹配从网页文本中提取发布时间。

  这也是一个容易实现的想法,但是细节很多,表达方式要尽可能多的涵盖。编写这样一个函数来提取发布时间并不是那么容易。小猿们充分发挥动手能力,看看能写出什么样的函数实现。这也是对小猿猴的一种锻炼。

  3. 提取文本

  文字(包括新闻图片)是新闻网页的主要部分。它在视觉上占据中间位置,是新闻内容的主要文本区域。提取文本的方法很多,实现复杂简单。本文介绍的方法是基于老猿多年的实践经验和思考的一种简单快速的方法,称为“节点文本密度法”。

  我们知道,网页的HTML代码是由不同的标签(tags)组成的,形成一棵树状的结构树,每个标签都是树的一个节点。通过遍历这个树形结构的每个节点,找到文本最多的节点,也就是文本所在的节点。按照这个思路,我们来实现代码。

  3.1 实现源码

<p>#!/usr/bin/env python3

#File: maincontent.py

#Author: veelion

import re

import time

import traceback

import cchardet

import lxml

import lxml.html

from lxml.html import HtmlComment

REGEXES = {

'okMaybeItsACandidateRe': re.compile(

'and|article|artical|body|column|main|shadow', re.I),

'positiveRe': re.compile(

('article|arti|body|content|entry|hentry|main|page|'

'artical|zoom|arti|context|message|editor|'

'pagination|post|txt|text|blog|story'), re.I),

'negativeRe': re.compile(

('copyright|combx|comment||contact|foot|footer|footnote|decl|copy|'

'notice|'

'masthead|media|meta|outbrain|promo|related|scroll|link|pagebottom|bottom|'

'other|shoutbox|sidebar|sponsor|shopping|tags|tool|widget'), re.I),

}

class MainContent:

def __init__(self,):

self.non_content_tag = set([

'head',

'meta',

'script',

'style',

'object', 'embed',

'iframe',

'marquee',

'select',

])

self.title = ''

self.p_space = re.compile(r'\s')

self.p_html = re.compile(r'

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线