vb抓取网页内容(如何识别页面的核心内容[4]作为一种怎样的体验)
优采云 发布时间: 2021-11-01 11:03vb抓取网页内容(如何识别页面的核心内容[4]作为一种怎样的体验)
目录选择的最佳总结
正文|李小飞
来源:Python技术《ID:pythonall》
每个人都必须熟悉爬虫程序。随便写一个获取网页信息,甚至通过请求自动生成Python脚本[1]。
最近在网上遇到一个爬虫项目,需要爬取文章。感觉没什么特别的,但是问题是没有抓取范围的限制,也就是说没有清晰的页面结构。
对于一个页面来说,除了核心的文章内容,还有head、tail、左右列表列等等。有的页框使用div布局,有的使用table。即使两者都使用div,less网站的样式和布局是不同的。
但问题必须解决。我想,既然搜索引擎已经抓取了各种网页的核心内容,我们应该也能应付。拿起 Python 去做吧!
各种尝试
如何解决?
生成PDF
我开始想到一个棘手的方法,就是使用工具(wkhtmltopdf[2])生成目标网页的PDF文件。
好处是不需要关心页面的具体形式,就像给页面拍照一样,文章结构完整。
虽然可以在源码级别检索PDF,但是生成PDF有很多缺点:
计算资源消耗大,效率低,错误率高,体积过大。
数以万计的数据已超过两百千兆字节。如果数据量达到存储,那将是一个大问题。
提取 文章 内容
有一种简单的方法可以通过 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(sel)
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
以上就是python实现精准搜索和提取网页核心内容的详细过程。关于python搜索和提取网页内容的更多信息,请关注云海天教程和其他相关文章!