抓取网页生成电子书(目录各种尝试生成PDF提取文章内容选择文|李晓飞总结)

优采云 发布时间: 2022-02-14 18:04

  抓取网页生成电子书(目录各种尝试生成PDF提取文章内容选择文|李晓飞总结)

  目录各种尝试生成PDF提取文章内容选择优化总结参考正文 | 李小飞来源:Python技术“ID:pythonall”爬虫程序大家一定不陌生,只要写一个就可以获取网页上的信息,甚至可以通过请求自...

  目录选择最佳摘要参考

  

  正文 | 李晓飞

  来源:python科技《ID:pythonall》

  爬虫程序想必大家都不陌生。您可以通过编写一个获取网页信息,甚至可以通过请求自动生成 Python 脚本 [1]。

  最近在网上遇到一个爬虫项目,需要爬取文章。感觉没什么特别的,但问题是没有限制爬取范围,也就是说没有清晰的页面结构。

  对于一个页面,除了核心的文章内容外,还有页眉、拖尾、左右列表栏等。有的页框使用div布局,有的使用table,即使使用了div,样式和网站 的布局不同。

  但问题必须解决。我想,既然各种网页的核心内容都是搜索引擎抓取的,那我们应该也能做到,拿起Python,说到做到!

  各种尝试

  如何解决?

  生成 PDF

  我开始想一个比较棘手的方法,就是使用一个工具(wkhtmltopdf[2])从目标网页生成一个PDF文件。

  好处是不用关心页面的具体形式,就像给页面拍照一样,文章结构就完整了。

  虽然可以在源代码级别搜索 PDF,但生成 PDF 有很多缺点:

  它消耗大量计算资源,效率低,错误率高,体积太大。

  数万条数据已经超过200GB。如果数据量增加,只有存储将是一个大问题。

  提取 文章 内容

  有一种简单的方法可以通过 xpath[3] 提取页面上的所有文本,而不是生成 PDF。

  但是内容会失去结构并且可读性降低。更糟糕的是,网页上有很多不相关的内容,比如侧边栏、广告、相关链接等,也会被提取出来,影响内容的准确性。

  为了保证一定的结构和识别核心内容,只能识别和提取文章部分的结构。就像搜索引擎学习一样,就是想办法找出页面的核心内容。

  我们知道,一般情况下,页面上的核心内容(比如文章部分)是比较集中的,我们可以从这个地方入手分析。

  所以我写了一段代码。我使用 Scrapy[4] 作为爬虫框架。这里我只截取了提取 文章 部分的代码:

  

divs = response.xpath("body//div")

sel = None

maxvalue = 0

for d in divs:

ds = len(d.xpath(".//div"))

ps = len(d.xpath(".//p"))

value = ps - ds

if value > maxvalue:

sel = {

"node": d,

"value": value

}

maxvalue = value

print("".join(sel['node'].getall()))

  简单明了,测试了几页确实不错。

  但是,在大量提取过程中,发现很多页面无法提取数据。仔细观察会发现有两种情况。

  再次调整策略,不再区分div,查看所有元素。

  另外,p多是首选,在它的基础上看到的div少。调整后的代码如下:

  

divs = response.xpath("body//*")

sels = []

maxvalue = 0

for d in divs:

ds = len(d.xpath(".//div"))

ps = len(d.xpath(".//p"))

if ps >= maxvalue:

sel = {

"node": d,

"ps": ps,

"ds": ds

}

maxvalue = ps

sels.append(s编程客栈el)

sels.sort(lambda x: x.ds)

sel = sels[0]

print("".join(sel['node'].getall()))

  经过这次修改,确实在一定程度上弥补了之前的问题,但是引入了一个比较麻烦的问题。

  即发现的文章体是不稳定的,特别容易受到其他部分的一些p的影响。

  选最好的

  由于不适合直接计算,因此需要重新设计算法。

  我发现文字集中的地方往往是文章的主体,而之前的方法没有考虑到这一点,只是机械地找了最大的p。

  还有一点,网页结构是一棵DOM树[6]

  

  那么离p标签越近的地方应该越有可能是文章主题,也就是说计算是离p越近的节点权重应该越大,离p越远的节点有一个很多 p 及时,但权重也应该更小。

  经过反复试验,最终代码如下:

  

def find(node, sel):

value = 0

for n in node.xpath("*"):

if n.xpath("local-name()").get() == "p":

t = "".join([s.strip() for s in (n.xpath('text()').getall() + n.xpath("*/text()").getall())])

value += len(t)

else:

value += find(n, a)*0.5

if value > sel["value"]:

sel["node"] = node

sel["value"] = value

return value

sel = {

'value': 0,

'node': None

}

find(response.xpath("body"), sel)

  经过这次改造,效果特别好。

  为什么?其实就是利用了密度的原理,即越靠近中心,密度就越高,远离中心的地方密度呈指数下降,这样就可以把密度中心筛掉。

  50%的斜率是怎么来的?

  事实上,它是通过实验确定的。一开始我设置为90%,但是body节点最后总是最好的,因为body收录了所有的文本内容。

  经过反复试验,确定 50% 是一个不错的值,如果不适合您的应用,请进行调整。

  总结

  在描述了我如何选择 文章 主题之后,我发现它实际上并不是一个非常简单的方法。而这次解题的经历,让我感受到了数学的魅力。

  我一直认为,只要你理解了处理问题的常规方式,处理日常编程就足够了。当遇到不确定的问题,没有办法提取简单的模型时,常规思维显然是不够的。

  因此,我们通常应该看一些数学强,解决不确定问题的方法,以提高我们的编程适应性,扩大我们的技能范围。

  希望这篇短文能对你有所启发,欢迎在留言区交流讨论,对比你的心!

  参考

  [1]

  卷曲到 Python:

  [2]

  wkhtmltopdf:

  [3]

  路径:

  [4]

  刮擦:

  [5]

  jQuery:

  [6]

  DOM 树:%20Tree/6067246

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线