通常的网页内容抽取须要针对特定的网站进行特定的检查定位正文标签,指定抽取规则。可是若是须要抽取100个不一样内容结构的网站正文,须要的就是100个不一样的规则。
有没有一种通用的内容抽取呢。能够只基于网页正文内容的变化而变化的规则f(x).
本文实现的是针对于通常的长文本正文类网站(博客、新闻、小说类)实现的通用正文内容抽取。像那种须要抽取的正文内容C长度与网页内容W长度比例C/W<0.5的可能会出现不适用的状况。(好比正文是一句话几个字,整个页面内容的文字长度超过了正文的2倍,那最好使用DOM标签规则抽取)python
如下的“网页”均指长文本类型的网页
通常的网页正文都是属于段落类型的文本,所属标签不一,其余的无用信息(如网页版权、站点通知、导航内容等)也占据了必定的页面内容,若是单纯的把网页内容文字所有抽取出来,
这很简单,可是会夹杂不少的无用内容,干扰太大,因此针对正文抽取获得页面的真正有用信息是主要目的。能够利用正文内容进行网页类似度的计算。git
抽取正文要找到正文的分布特征,将爬取到的网页去除全部标签,获得每一行的内容后,能够根据(行号,字符数)制做图表查看二者的关联:
下图是腾讯新闻一则新闻页面的行号-行字数关系图表:github
下图是CSDN的两则博文正文行号-行字数关系图表:算法
《中文编码相关,python处理gbk编码的xml文件方法》:
![]()
《python抓取gb2312gbk编码网页乱码问题》:
![]()
下图是segmentfault的一篇博文正文行号-行字数关系图表:segmentfault
《解决 ScriptError的另类思路》:
![]()
能够看到,正文的内容通常是连续行的块,所以咱们能够设置阈值来过滤一些非正文的干扰行,可是针对某些连续行并非有效正文的状况,就须要看这个连续行组成的块的总字符数。
若是字数少于一个阈值,就不属于正文,也就是正文的字符密度,因而可知,正文能够基于连续行字符密度来进行提取。网站
假设咱们已经爬取了网页内容WebContent,而且将W的全部标签去除获得了纯文本保留行格式的文字内容LinesContent.接下来:编码
#三个可控变量,自由调整使抽取达到理想效果 #连续行阈值:连续多少行则认为是一个正文内容块 threshold = 5 #正文内空行阈值:容许正文内容 段落或正文行 之间有多少空行 gap = 3 #正文字符密度阈值:每一行的字符数达到多少则认为属于正文内容 density = 45 #********初始化设置#******** #保留抽取结果字典,格式:{<连续块字符总数>:<块文字内容>,...} results={} #已经达到先后连续的次数 comobo_num =0 #当前连续块的总字符数 combo_len = 0 #当前连续空行数 combo_null=0 #当前连续块的文字内容 combo_text = '' #当前行/前一行的字符数 pre_len = 0 for i in LinesContent: #当前行非空 if i.strip(): pre_len = len(i) comobo_num += 1 combo_null = 0 combo_len += pre_len #叠加非空行内容到连续内容中 combo_text = combo_text+i+ os.linesep #针对单行文本状况 if len(a)==1 and pre_len >= density*threshold: results[pre_len]=combo_text else: combo_null +=1 #若是前一行非空 if pre_len: #连续空行阈值判断 if combo_null > gap: #连续块判断 if combo_len >= density*threshold \ and comobo_num >= threshold: results[combo_len]=combo_text else: continue #非正文连续块则所有参数复位 comobo_num = 0 combo_len = 0 if combo_null > gap else combo_len pre_len = 0 combo_text = '' if combo_null > gap else combo_text
通过对多个长文本类型网站的抓取抽取,正文抽取成功率达到了90%以上。spa
源码地址:GitHubcode