如何找到一張頁面的“內(nèi)容區(qū)”

這本身是一個很有意思的問題,而且也很實用。

Instapaper和Pocket這樣的稍后閱讀類軟件當(dāng)然需要,各種搜索引擎的Spider也需要,甚至于SNS類網(wǎng)站也需要——G+、Facebook和豆瓣等都會為你添加的Link自動生成內(nèi)容摘要,而如果這份摘要結(jié)果一看是Header里的Menu,這就糗大了。

這個任務(wù)對于人肉智能來說,是不足為據(jù)的——我們打開一個頁面,掃一掃,事情就結(jié)束了。
  但對于電腦里的人工智能來說,這事就蛋疼了。

這里,就簡要分析一下要如何獲得一張頁面的內(nèi)容區(qū),這么一個問題。
  PS:話說最近打算寫而沒有寫完的文章還有很多,到底怎么會今天突然想寫這個的啊。。。


我們先來想一下人是如何看一個頁面,并找出其中的內(nèi)容區(qū)的。
  這事其實分兩部分。

第一步,就是根據(jù)以往的經(jīng)驗來篩選出一個頁面的大致布局,從而鎖定內(nèi)容區(qū)的位置。

比如說,當(dāng)我們打開簡書頁面的時候,如果不是初來乍到,那么我們的視線會先掃過整個頁面,然后很自然地就知道了內(nèi)容的大致布局——左面的是NavBar,右上是Menu,中間是內(nèi)容,靠左是作者信息,底下是評論。
  這個我們掃一眼基本就心里有數(shù)了,而這個行為又可以分解為三個部分:根據(jù)過往經(jīng)驗從頁面布局分析功能;根據(jù)過往經(jīng)驗從UI元素的形狀和相對位置來分析出其功能;根據(jù)過往經(jīng)驗從UI元素的文字提示看出這貨的功能。
  大致的篩選過程就是這樣——從最大的布局,到中間層次的UI元素形狀和位置,再到細致的UI元素本身。這些根據(jù)我們的經(jīng)驗,都可以知道大概是干嘛的。
  這放在計算機來說,就可以分解為兩個不同的部分。
  第一部分就是根據(jù)頁面的Tag、Class和ID做語義分析,來了解大概。
  不過這個對國內(nèi)大部分網(wǎng)站來說是很糟糕的,因為國內(nèi)網(wǎng)站(其實國外老網(wǎng)站也是如此)基本都不管語義標(biāo)簽,內(nèi)容不用article,都是用div或者p,菜單也不用menu或者nav,依然是div或者p。所以這個也只能作為輔助,不能當(dāng)真。
  第二部分就是大數(shù)據(jù)下的學(xué)習(xí)了,這個這里略過不提。

所以,以“過往經(jīng)驗”做判斷,對機器來說基本算是死路一條。

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

文本分析的基本模式,可以分解為這么幾步——

首先,將文章拆分成多個節(jié)點。
  這里,對HTML文本做Parse,給出類似DOM-Tree,這就做完了第一步。
  當(dāng)然,這里也會做一定的篩選——比如將前面提到的header、footer、nav、menu都去掉,iframe肯定也要去掉,video啊audio啊object啊這些統(tǒng)統(tǒng)去掉。

接著,是做Style的篩選。
  這里比較牛叉的,是從DOM-Tree生成網(wǎng)站的Render-Tree,然后將所有浮動元素去除——內(nèi)容顯然不應(yīng)該是浮動的。
  但,如果是要后臺服務(wù)器端批量高效處理的話,那么繪制出Render-Tree顯然沒戲。
  所以,我們能做的只是根據(jù)節(jié)點上的Style做出簡單處理,CSS匹配這個最多就做一些簡單的匹配,否則實用全套CSS匹配,就等于給出Render-Tree,這事就沒譜了。
  我們將所有浮動的元素去除,所有不可見的元素去除,留下那些可見的、固定的節(jié)點,篩選這事就算完成了第一步了。

第三步,內(nèi)容篩選。
  Style篩選只是將頁面上鐵定有問題的東西給去除,但比如簡書左側(cè)導(dǎo)航條這樣的存在依然是無法就這么輕松地去除的。
  于是,下面就是內(nèi)容篩選。
  頁面上的有用的內(nèi)容,大致可以分為這么三類:
  文字,圖片,標(biāo)題。
  這里“標(biāo)題”可以更好地說成是“文檔結(jié)構(gòu)指示文本”,不過太麻煩了,還是用“標(biāo)題”吧,足夠了。
  而頁面上的非內(nèi)容資源,則可以有很多,包括跳轉(zhuǎn)鏈接,導(dǎo)航鏈接,功能模組,等等。
  除了比較特殊的功能模組,前面兩了鏈接和內(nèi)容中的“文字”其實是有很大的區(qū)別的,但卻和“標(biāo)題”比較容易混淆。
  但這兩類鏈接和文字也不是完全地涇渭分明,因為文本中本來就可以就某些特定的文字設(shè)置超鏈接,所以如果簡單粗暴地將所有含有鏈接的節(jié)點都去除,那就沒剩下什么了。
  我們先來看鏈接和文字是如何區(qū)分的。
  作為頁面交互元素的鏈接(而不是文章內(nèi)的超鏈接),其特點就是一般用的都是短語或者簡單的詞匯,基本不用用句子,更加不會用長句或者復(fù)雜句——一個回到主頁寫出一個定語從句這樣的奇葩網(wǎng)站我也是真醉了。
  所以,如果我們發(fā)現(xiàn)一個節(jié)點里有一定量的句子,那么這個節(jié)點就有很高的幾率是內(nèi)容而非功能鏈接。
  但,很多時候這樣的判斷未必是靠譜的,比如下面這樣的東西:

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

這貨到底是當(dāng)內(nèi)容好還是菜單好?
  上面這樣的東西在恰當(dāng)?shù)腃SS和JS(比如給click事件綁定一個頁面跳轉(zhuǎn))下,就是一個菜單,第一個選項是賣狐貍,第二個賣書,第三個賣食物,你一點話都沒有。
  但同樣在一定的CSS(比如第一個背景色紅色第二個背景黃色第三個背景綠色)下,卻是一句普通的話而已。
  而,如果要說是用語義分析來判斷這是否構(gòu)成一句話的話,現(xiàn)在還沒法做到這點,就算能做到一定程度,對服務(wù)器端的壓力也是可想而知的。
  所以,就我們現(xiàn)在的問題來說,只能是給每個節(jié)點一個可能的分數(shù),最后通過綜合分析各項指標(biāo),做出恰當(dāng)?shù)暮Y選。
  比如,這里就沒個span的節(jié)點來說,構(gòu)成內(nèi)容的分數(shù)都是0.1(我瞎編的值),而對于整體的div這個節(jié)點來說,可能是內(nèi)容的分是0.1+0.1+0.1+0.1=0.4,前面三個是每個span子節(jié)點的,最后一個0.1是從整個節(jié)點來看這句“話”的。
  通過這樣的方法,可以一定程度上解決非內(nèi)容文本與內(nèi)容文本的篩選——剩下的就是調(diào)整參數(shù)和通過前面說的東西來優(yōu)化的問題了——如果還對每個域或者子域?qū)?yōu)化結(jié)果和調(diào)整參數(shù)都記錄下來,那么對某個特定網(wǎng)段的頁面就可以有較好的匹配和抓取結(jié)果了。
  但,這還只是分辨非內(nèi)容文本和內(nèi)容文本,我們還需要分辨非內(nèi)容文本和標(biāo)題——也就是文檔結(jié)構(gòu)指示文本。
  前面的分析對這兩類東西是幾乎無能為力的,比如如下這段東西:
<blockquote>第一章 阿拉蕾
很久很久以前,上帝說要有歡笑,于是造了阿拉蕾。
第二章 寶瓜
過了沒多久,上帝說要有胡鬧,于是造了寶瓜。</blockquote>

如果我們按照上面所說的來分析,我們將看到,“第一章”這一行見被判定為“非內(nèi)容文本”,第二行是內(nèi)容文本,第三行是非內(nèi)容文本,第四行是內(nèi)容文本。
  這顯然不是我們想要的結(jié)果。
  于是,這里我們將采用一種在Photoshop中很常見的技術(shù),那就是將選區(qū)擴大,然后再收縮,從而將原本不相連的選區(qū)連接起來。
  根據(jù)一個大多數(shù)頁面都遵守的規(guī)律——內(nèi)容都和內(nèi)容在一起,非內(nèi)容都和非內(nèi)容在一起,從而來計算每個判定為非內(nèi)容的節(jié)點(也就是前面所說的分值低于某個程度的節(jié)點)到內(nèi)容節(jié)點的距離,超過臨界值就認為真的不是內(nèi)容。
  或者也可以用更加Photoshop的方法,計算一個節(jié)點的“是內(nèi)容節(jié)點可能性”的擴散,并根據(jù)“如果擴散到的值比節(jié)點原有的值小則保留原有值否則使用擴散值”這樣的基本規(guī)律,從新計算擴散后的結(jié)果。
  上面的處理可以將內(nèi)容之間的標(biāo)題給找出來,缺點是會將一頭一尾的非內(nèi)容節(jié)點也包括進去,所有最后就是對首尾做額外的判斷。
  進過這么一輪,我們就可以篩選出頁面的內(nèi)容區(qū)了。

當(dāng)然,上面所說的只是基本思路,而且很多系統(tǒng)參數(shù)都沒有,這些都需要在實際操作的時候進行調(diào)整和修改。

在Git上,有一個叫做Goose的項目,其ContentExtractor的基本算法思路就是這樣的一套流程。

如果加上一定的Tag、Class、ID和語義分析,以及對各域的記錄與分析(當(dāng)然也就需要用戶的恰當(dāng)反饋與操作),那么就可以獲得一個不錯的內(nèi)容抓取模塊了吧——我猜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,291評論 25 708
  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J的外補...
    _Yfling閱讀 14,180評論 1 92
  • 一、樣式篇 第1章 初識jQuery (1)環(huán)境搭建 進入官方網(wǎng)站獲取最新的版本 http://jquery.co...
    凜0_0閱讀 3,681評論 0 44
  • 一直在關(guān)注人物閱讀號,不會常關(guān)注,但沒事就喜歡掃兩眼,因為里面有各行各業(yè)的榜樣人生,不是雞湯,是樸實的人性剖析。 ...
    I_am_橙子閱讀 118評論 0 0
  • 一、回顧總結(jié) 1、加:增加碎片化時間價值,提前準(zhǔn)備一張碎片時間清單,對于等車,等電梯的幾分鐘事情可以做點有用的事。...
    遇見未知的自己珍珍閱讀 793評論 0 2

友情鏈接更多精彩內(nèi)容