如何找到一张页面的“内容区”

这本身是一个很有意思的问题,而且也很实用。

Instapaper和Pocket这样的稍后阅读类软件当然需要,各种搜索引擎的Spider也需要,甚至于SNS类网站也需要——G+、Facebook和豆瓣等都会为你添加的Link自动生成内容摘要,而如果这份摘要结果一看是Header里的Menu,这就糗大了。

这个任务对于人肉智能来说,是不足为据的——我们打开一个页面,扫一扫,事情就结束了。
  但对于电脑里的人工智能来说,这事就蛋疼了。

这里,就简要分析一下要如何获得一张页面的内容区,这么一个问题。
  PS:话说最近打算写而没有写完的文章还有很多,到底怎么会今天突然想写这个的啊。。。


我们先来想一下人是如何看一个页面,并找出其中的内容区的。
  这事其实分两部分。

第一步,就是根据以往的经验来筛选出一个页面的大致布局,从而锁定内容区的位置。

比如说,当我们打开简书页面的时候,如果不是初来乍到,那么我们的视线会先扫过整个页面,然后很自然地就知道了内容的大致布局——左面的是NavBar,右上是Menu,中间是内容,靠左是作者信息,底下是评论。
  这个我们扫一眼基本就心里有数了,而这个行为又可以分解为三个部分:根据过往经验从页面布局分析功能;根据过往经验从UI元素的形状和相对位置来分析出其功能;根据过往经验从UI元素的文字提示看出这货的功能。
  大致的筛选过程就是这样——从最大的布局,到中间层次的UI元素形状和位置,再到细致的UI元素本身。这些根据我们的经验,都可以知道大概是干嘛的。
  这放在计算机来说,就可以分解为两个不同的部分。
  第一部分就是根据页面的Tag、Class和ID做语义分析,来了解大概。
  不过这个对国内大部分网站来说是很糟糕的,因为国内网站(其实国外老网站也是如此)基本都不管语义标签,内容不用article,都是用div或者p,菜单也不用menu或者nav,依然是div或者p。所以这个也只能作为辅助,不能当真。
  第二部分就是大数据下的学习了,这个这里略过不提。

所以,以“过往经验”做判断,对机器来说基本算是死路一条。

第二步,就是文本分析了。

文本分析的基本模式,可以分解为这么几步——

首先,将文章拆分成多个节点。
  这里,对HTML文本做Parse,给出类似DOM-Tree,这就做完了第一步。
  当然,这里也会做一定的筛选——比如将前面提到的header、footer、nav、menu都去掉,iframe肯定也要去掉,video啊audio啊object啊这些统统去掉。

接着,是做Style的筛选。
  这里比较牛叉的,是从DOM-Tree生成网站的Render-Tree,然后将所有浮动元素去除——内容显然不应该是浮动的。
  但,如果是要后台服务器端批量高效处理的话,那么绘制出Render-Tree显然没戏。
  所以,我们能做的只是根据节点上的Style做出简单处理,CSS匹配这个最多就做一些简单的匹配,否则实用全套CSS匹配,就等于给出Render-Tree,这事就没谱了。
  我们将所有浮动的元素去除,所有不可见的元素去除,留下那些可见的、固定的节点,筛选这事就算完成了第一步了。

第三步,内容筛选。
  Style筛选只是将页面上铁定有问题的东西给去除,但比如简书左侧导航条这样的存在依然是无法就这么轻松地去除的。
  于是,下面就是内容筛选。
  页面上的有用的内容,大致可以分为这么三类:
  文字,图片,标题。
  这里“标题”可以更好地说成是“文档结构指示文本”,不过太麻烦了,还是用“标题”吧,足够了。
  而页面上的非内容资源,则可以有很多,包括跳转链接,导航链接,功能模组,等等。
  除了比较特殊的功能模组,前面两了链接和内容中的“文字”其实是有很大的区别的,但却和“标题”比较容易混淆。
  但这两类链接和文字也不是完全地泾渭分明,因为文本中本来就可以就某些特定的文字设置超链接,所以如果简单粗暴地将所有含有链接的节点都去除,那就没剩下什么了。
  我们先来看链接和文字是如何区分的。
  作为页面交互元素的链接(而不是文章内的超链接),其特点就是一般用的都是短语或者简单的词汇,基本不用用句子,更加不会用长句或者复杂句——一个回到主页写出一个定语从句这样的奇葩网站我也是真醉了。
  所以,如果我们发现一个节点里有一定量的句子,那么这个节点就有很高的几率是内容而非功能链接。
  但,很多时候这样的判断未必是靠谱的,比如下面这样的东西:

<div>
  <span>Fox</span>
  <span>Book</span>
  <span>Food</span>
</div>

这货到底是当内容好还是菜单好?
  上面这样的东西在恰当的CSS和JS(比如给click事件绑定一个页面跳转)下,就是一个菜单,第一个选项是卖狐狸,第二个卖书,第三个卖食物,你一点话都没有。
  但同样在一定的CSS(比如第一个背景色红色第二个背景黄色第三个背景绿色)下,却是一句普通的话而已。
  而,如果要说是用语义分析来判断这是否构成一句话的话,现在还没法做到这点,就算能做到一定程度,对服务器端的压力也是可想而知的。
  所以,就我们现在的问题来说,只能是给每个节点一个可能的分数,最后通过综合分析各项指标,做出恰当的筛选。
  比如,这里就没个span的节点来说,构成内容的分数都是0.1(我瞎编的值),而对于整体的div这个节点来说,可能是内容的分是0.1+0.1+0.1+0.1=0.4,前面三个是每个span子节点的,最后一个0.1是从整个节点来看这句“话”的。
  通过这样的方法,可以一定程度上解决非内容文本与内容文本的筛选——剩下的就是调整参数和通过前面说的东西来优化的问题了——如果还对每个域或者子域将优化结果和调整参数都记录下来,那么对某个特定网段的页面就可以有较好的匹配和抓取结果了。
  但,这还只是分辨非内容文本和内容文本,我们还需要分辨非内容文本和标题——也就是文档结构指示文本。
  前面的分析对这两类东西是几乎无能为力的,比如如下这段东西:
<blockquote>第一章 阿拉蕾
很久很久以前,上帝说要有欢笑,于是造了阿拉蕾。
第二章 宝瓜
过了没多久,上帝说要有胡闹,于是造了宝瓜。</blockquote>

如果我们按照上面所说的来分析,我们将看到,“第一章”这一行见被判定为“非内容文本”,第二行是内容文本,第三行是非内容文本,第四行是内容文本。
  这显然不是我们想要的结果。
  于是,这里我们将采用一种在Photoshop中很常见的技术,那就是将选区扩大,然后再收缩,从而将原本不相连的选区连接起来。
  根据一个大多数页面都遵守的规律——内容都和内容在一起,非内容都和非内容在一起,从而来计算每个判定为非内容的节点(也就是前面所说的分值低于某个程度的节点)到内容节点的距离,超过临界值就认为真的不是内容。
  或者也可以用更加Photoshop的方法,计算一个节点的“是内容节点可能性”的扩散,并根据“如果扩散到的值比节点原有的值小则保留原有值否则使用扩散值”这样的基本规律,从新计算扩散后的结果。
  上面的处理可以将内容之间的标题给找出来,缺点是会将一头一尾的非内容节点也包括进去,所有最后就是对首尾做额外的判断。
  进过这么一轮,我们就可以筛选出页面的内容区了。

当然,上面所说的只是基本思路,而且很多系统参数都没有,这些都需要在实际操作的时候进行调整和修改。

在Git上,有一个叫做Goose的项目,其ContentExtractor的基本算法思路就是这样的一套流程。

如果加上一定的Tag、Class、ID和语义分析,以及对各域的记录与分析(当然也就需要用户的恰当反馈与操作),那么就可以获得一个不错的内容抓取模块了吧——我猜。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,043评论 25 707
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,703评论 1 92
  • 一、样式篇 第1章 初识jQuery (1)环境搭建 进入官方网站获取最新的版本 http://jquery.co...
    凛0_0阅读 3,338评论 0 44
  • 一直在关注人物阅读号,不会常关注,但没事就喜欢扫两眼,因为里面有各行各业的榜样人生,不是鸡汤,是朴实的人性剖析。 ...
    I_am_橙子阅读 84评论 0 0
  • 一、回顾总结 1、加:增加碎片化时间价值,提前准备一张碎片时间清单,对于等车,等电梯的几分钟事情可以做点有用的事。...
    遇见未知的自己珍珍阅读 574评论 0 2