如何智能分辨列表页和详情页
在前面几节,我们介绍了详情页和列表页的内容提取方案,传入对应的 HTML 代码就能获取对应的提取结果了。但这里有个问题,就是在调用提取方法之前,需要先分辨哪种页面是列表页,哪种是详情页。
这自然而然引出了一个问题:能否用一个算法来区分列表页和详情页,直接根据算法返回的结果调用对应的提取方法,从而省掉很多麻烦?
问题分析
我们首先分析这个问题属于什么问题。其实很明显,既然要返回分类结果(要么是列表页,要么是详情页),那么就可以把它归为二分类问题。
|
这里我们不考虑特殊页面(例如登录页面、注册页面等),并把非列表页和详情页的页面一 律归为其他页面,如果把此类页面也考虑进去,本节的问题就是三分类问题,在此为了方便,仅分析二分类问题。 |
二分类问题怎么解决呢?实现一个基本的分类模型就好了,大范围是传统机器学习和现在比较流行的深度学习。总体上讲,深度学习的精度要高一点,处理能力也强一点。想想我们的应用场景,要追求精度的话可能需要更多的标注数据,而我们也有比较不错的易用模型,例如SVM。
所以,不妨先用 SVM 模型实现一个基本的二分类模型试试看,如果效果已经很好或者提升空间不大了,就直接用;如果效果比较差,再选用其他模型做优化。
数据标注
既然要实现分类模型,最重要的当然是数据标注,这里分两组数据,一组是列表页数据,一组是详情页数据。先手工配合爬虫找一些列表页和详情页的HTML代码(例如新闻网站、博客网站的列表页和详情页,覆盖的网站越多,训练得到的分类器就越准确),然后将它们保存下来。
经过一些收集和处理,将列表页和详情页的HTML代码保存在两个文件夹中,分别取名为list和 detail,结果类似图14-22这样。
图14-22list文件夹和detail文件夹
每个文件夹里保存几百份 HTML 代码就行了,不用太多。接下来从这些代码里提取特征,然后实现一个二分类模型。
特征提取
选用 SVM 模型,首先得想清楚一件事:要分清两个类别,需要哪些特征。既然是特征,就要选 出各自独有的特征,才更有区分度。
这里总结了几个可以用来区分列表页和详情页的特征。
-
文本密度:详情页通常包含密集的文字,例如一个P节点内部就包含几十甚至上百个文字,如果用单个节点内的文字数量表示文本密度,那么详情页的文本密度会很高。
-
超链接节点的数量和比例:列表页通常包含多个超链接,而且有很大一部分是超链接文本;详情贞则包含更多的文字超链接很少。
-
符号密度:列表页通常相当于标题导航页,很少包含句号,而详情页的正文内容普遍包含句号,如果用单位文字包含的句号数量来表示符号密度,那么详情页的符号密度会很高。
-
列表族的数量:列表页常常包含多组具有共同父节点的条目,多个条目构成一个列表簇。虽说详情页的侧栏也会有一些列表,但至少这个数量和列表页的相比,是可以分清的。
-
meta信息:有一些特殊的meta信息是列表页独有的,例如详情页往往包含发布时间,列表页则通常没有。
-
正文标题和 title 内容的相似度:一般来说,详情页的正文标题和 title 内容很可能相同,而列表页的 title 内容通常是网站名称。
以上便是几个基本的特征,此外其他一些特征也可以自行挖掘并使用,例如视觉信息、节点大小。
模型实现
代码实现的过程就是对现有的HTML代码做预处理,提取出上面的基本特征,然后声明一个SVM 分类模型。先声明一个特征列表和特征对应的获取方法:
然后就是关键部分一处理数据和训练模型:
这里首先对数据做预处理,将特征保存到 x_data 中,将标注结果保存到 y_data 中。接着使用 StandardScaler 对数据进行标准化处理,并进行随机切分。最后使用 Grid Search 训练了一个 SVM 模型并保存下来。
以上便是基本的模型训练过程,具体代码可以自己再完善一下。
使用
将保存的模型用于分类处理就好了。我已经把使用流程放在 GerapyAutoExtractor 包里面了,大家可以使用 pip3 工具安装:
pip3 install gerapy-auto-extractor
这个包针对于以上算法提供了 4 个方法。
-
is_detail:判断一个页面是否是详情页。
-
islist:判断一个页面是否是列表页。
-
probability_of_detail:一个页面是详情页的概率,返回结果是 0~1。
-
probability_of_list:一个页面是列表页的概率,返回结果是 0~1。
例如,随便找个网址,把列表页和详情页的HTML代码分别保存为 list.html 文件和 detail.html 文件。然后用如下代码做测试:
这里就调用上述 4 个方法判断了两个页面的类型和置信度。
运行结果如下:
可以看出,我们得到了正确的页面类型和置信度。