從HTML文件中提取正文的簡單方案


http://www.basesnet.com/seo/53

從HTML文件中提取正文的簡單方案

多種基於html正文提取的思想

一、基於統計的中文網頁正文抽取的研究

摘  要:信息抽取技術是一種廣泛運用於互聯網的數據挖掘技術。其目的是從互聯網海量數據中抽取有意義、有價值的數據和信息,從而能更好的利用互聯網資源。文中采用一種統計網頁特征的方法,將中文網頁中的正文部分抽取出來。該方法首先將網頁表示成基於XML的DOM樹形式,利用統計的節點信息從樹中過濾掉噪音數據節點,最后再選取正文節點。該方法相比傳統的基於包裝器的抽取方法,具有簡單,實用的特點,試驗結果表明,該抽取方法准確率達到90%以上,具有很好的實用價值。

來源網址:http://blog.csdn.net/zvane/archive/2008/03/21/2201414.aspx

二、基於標簽密度判定

譯者導讀:這篇文章主要介紹了從不同類型的HTML文件中抽取出真正有用的正文內容的一種有廣泛適應性的方法。其功能類似於CSDN近期推出的“剪影”,能夠去除頁眉、頁腳和側邊欄的無關內容,非常實用。其方法簡單有效而又出乎意料,看完后難免大呼原來還可以這樣!行文簡明易懂,雖然應用了人工神經網絡這樣的算法,但因為FANN良好的封裝性,並不要求讀者需要懂得ANN。全文示例以Python代碼寫成,可讀性更佳,具有科普氣息,值得一讀。

每個人手中都可能有一大堆討論不同話題的HTML文檔。但你真正感興趣的內容可能隱藏於廣告、布局表格或格式標記以及無數鏈接當中。甚至更糟的是,你希望那些來自菜單、頁眉和頁腳的文本能夠被過濾掉。如果你不想為每種類型的HTML文件分別編寫復雜的抽取程序的話,我這里有一個解決方案。
本文講述如何編寫與從大量HTML代碼中獲取正文內容的簡單腳本,這一方法無需知道HTML文件的結構和使用的標簽。它能夠工作於含有文本內容的所有新聞文章和博客頁面……
你想知道統計學和機器學習在挖掘文本方面能夠讓你省時省力的原因嗎?
答案極其簡單:使用文本和HTML代碼的密度來決定一行文件是否應該輸出。(這聽起來有點離奇,但它的確有用!)基本的處理工作如下:
一、解析HTML代碼並記下處理的字節數。
二、以行或段的形式保存解析輸出的文本。
三、統計每一行文本相應的HTML代碼的字節數
四、通過計算文本相對於字節數的比率來獲取文本密度
五、最后用神經網絡來決定這一行是不是正文的一部分。
僅僅通過判斷行密度是否高於一個固定的閾值(或者就使用平均值)你就可以獲得非常好的結果。但你也可以使用機器學習(這易於實現,簡直不值一提)來減少這個系統出現的錯誤。
來源網址:http://hi.baidu.com/whitecpf/blog/item/6c4dffde6004755094ee37c9.html

三、基於數據挖掘思想的網頁正文抽取方法的研究

提出了一種依靠數據挖掘思想,從中文新聞類網頁中抽取正文內容的方法。該方法將網頁源代碼進行線性化重構,然后利用重構后的代碼進行網頁噪聲的初步去除,再經過文本分類、聚類得到網頁正文的脈絡段落,最后通過吸收偽噪聲段落生成網頁正文。該方法克服了傳統的網頁內容抽取方法需要為網頁結構建樹的缺點,具有簡單、快速、准確的特點,試驗表明該方法的抽取准確率可以達到99%以上。

來源網址:http://epub.cnki.net/grid2008/detail.aspx?filename=ZGZR200608001051&dbname=cpfd2006

四、基於視覺網頁塊分析技術的正文抽取

基於視覺的正文抽取和網頁塊分析是完全模擬IE瀏覽器的顯示方式,對網頁進行解析。系統根據人類視覺原理,把網頁解析處理的結果,進行分塊。然后根據用戶需求,提取用戶需要的提取相關網頁塊的內容。
比如在競爭情報系統和自動新聞已經采編發系統中,正文的提取。提取:標題、正文、時間等信息。

    評:類似根據模板定義去提取網頁正文

 繼續收集中

當然還有很多如通過正則表達式,或剔除html標簽等等方式提取正文,但個人認為通用效果不理想。

The Easy Way to Extract Useful Text from Arbitrary HTML
從HTML文件中抽取正文的簡單方案
作者:alexjc
原文地址:http://ai-depot.com/articles/the-easy-way-to-extract-useful-text-from-arbitrary-html/
譯者導讀:這篇文章主要介紹了從不同類型的HTML文件中抽取出真正有用的正文內容的一種有廣泛適應性的方法。其功能類似於CSDN近期推出的“剪影”,能夠去除頁眉、頁腳和側邊欄的無關內容,非常實用。其方法簡單有效而又出乎意料,看完后難免大呼原來還可以這樣!行文簡明易懂,雖然應用了人工神經網絡這樣的算法,但因為FANN良好的封裝性,並不要求讀者需要懂得ANN。全文示例以Python代碼寫成,可讀性更佳,具有科普氣息,值得一讀。
You’ve finally got your hands on the diverse collection of HTML documents you needed. But the content you’re interested in is hidden amidst adverts, layout tables or formatting markup, and other various links. Even worse, there’s visible text in the menus, headers and footers that you want to filter out. If you don’t want to write a complex scraping program for each type of HTML file, there is a solution.
每個人手中都可能有一大堆討論不同話題的HTML文檔。但你真正感興趣的內容可能隱藏於廣告、布局表格或格式標記以及無數鏈接當中。甚至更糟的是,你希望那些來自菜單、頁眉和頁腳的文本能夠被過濾掉。如果你不想為每種類型的HTML文件分別編寫復雜的抽取程序的話,我這里有一個解決方案。
This article shows you how to write a relatively simple script to extract text paragraphs from large chunks of HTML code, without knowing its structure or the tags used. It works on news articles and blogs pages with worthwhile text content, among others…
本文講述如何編寫與從大量HTML代碼中獲取正文內容的簡單腳本,這一方法無需知道HTML文件的結構和使用的標簽。它能夠工作於含有文本內容的所有新聞文章和博客頁面……
Do you want to find out how statistics and machine learning can save you time and effort mining text?
你想知道統計學和機器學習在挖掘文本方面能夠讓你省時省力的原因嗎?

< type=text/javascript> The concept is rather simple: use information about the density of text vs. HTML code to work out if a line of text is worth outputting. (This isn’t a novel idea, but it works!) The basic process works as follows:

答案極其簡單:使用文本和HTML代碼的密度來決定一行文件是否應該輸出。(這聽起來有點離奇,但它的確有用!)基本的處理工作如下:
  1. Parse the HTML code and keep track of the number of bytes processed.
一、解析HTML代碼並記下處理的字節數。
  1. Store the text output on a per-line, or per-paragraph basis.
二、以行或段的形式保存解析輸出的文本。
  1. Associate with each text line the number of bytes of HTML required to describe it.
三、統計每一行文本相應的HTML代碼的字節數
  1. Compute the text density of each line by calculating the ratio of text to bytes.
四、通過計算文本相對於字節數的比率來獲取文本密度
  1. Then decide if the line is part of the content by using a neural network.
五、最后用神經網絡來決定這一行是不是正文的一部分。
You can get pretty good results just by checking if the line’s density is above a fixed threshold (or the average), but the system makes fewer mistakes if you use machine learning — not to mention that it’s easier to implement!
僅僅通過判斷行密度是否高於一個固定的閾值(或者就使用平均值)你就可以獲得非常好的結果。但你也可以使用機器學習(這易於實現,簡直不值一提)來減少這個系統出現的錯誤。
Let’s take it from the top…
現在讓我從頭開始……
Converting the HTML to Text
轉換HTML為文本
What you need is the core of a text-mode browser, which is already setup to read files with HTML markup and display raw text. By reusing existing code, you won’t have to spend too much time handling invalid XML documents, which are very common — as you’ll realise quickly.
你需要一個文本模式瀏覽器的核心,它應該已經內建了讀取HTML文件和顯示原始文本功能。通過重用已有代碼,你並不需要把很多時間花在處理無效的XML文件上。
As a quick example, we’ll be using  Python along with a few built-in modules: htmllib for the parsing and formatter for outputting formatted text. This is what the top-level function looks like:
我們將使用Python來完成這個例子,它的htmllib模塊可用以解析HTML文件,formatter模塊可用以輸出格式化的文本。嗯,實現的頂層函數如下:
def extract_text(html):
     # Derive from formatter.AbstractWriter to store paragraphs.
    writer = LineWriter()
     # Default formatter sends commands to our writer.
    formatter = AbstractFormatter(writer)
     # Derive from htmllib.HTMLParser to track parsed bytes.
    parser = TrackingParser(writer, formatter)
     # Give the parser the raw HTML data.
    parser.feed(html)
    parser.close()
     # Filter the paragraphs stored and output them.
     return writer.output()
The TrackingParser itself overrides the callback functions for parsing start and end tags, as they are given the current parse index in the buffer. You don’t have access to that normally, unless you start diving into frames in the call stack — which isn’t the best approach! Here’s what the class looks like:
TrackingParser覆蓋了解析標簽開始和結束時調用的回調函數,用以給緩沖對象傳遞當前解析的索引。通常你不得不這樣,除非你使用不被推薦的方法——深入調用堆棧去獲取執行幀。這個類看起來是這樣的:
class TrackingParser(htmllib.HTMLParser):
    ”"”Try to keep accurate pointer of parsing location.”"”
     def __init__(self, writer, *args):
        htmllib.HTMLParser.__init__(self, *args)
        self.writer = writer
     def parse_starttag(self, i):
        index = htmllib.HTMLParser.parse_starttag(self, i)
        self.writer.index = index
         return index
     def parse_endtag(self, i):
        self.writer.index = i
         return htmllib.HTMLParser.parse_endtag(self, i)
The LineWriter class does the bulk of the work when called by the default formatter. If you have any improvements or changes to make, most likely they’ll go here. This is where we’ll put our machine learning code in later. But you can keep the implementation rather simple and still get good results. Here’s the simplest possible code:
LinWriter的大部分工作都通過調用formatter來完成。如果你要改進或者修改程序,大部分時候其實就是在修改它。我們將在后面講述怎么為它加上機器學習代碼。但你也可以保持它的簡單實現,仍然可以得到一個好結果。具體的代碼如下:
class Paragraph:
     def __init__(self):
        self.text = ”
        self.bytes = 0
        self.density = 0.0
class LineWriter(formatter.AbstractWriter):
     def __init__(self, *args):
        self.last_index = 0
        self.lines = [Paragraph()]
        formatter.AbstractWriter.__init__(self)
     def send_flowing_data(self, data):
         # Work out the length of this text chunk.
        t = len(data)
         # We’ve parsed more text, so increment index.
        self.index += t
         # Calculate the number of bytes since last time.
        b = self.index - self.last_index
        self.last_index = self.index
         # Accumulate this information in current line.
        l = self.lines[-1]
        l.text += data
        l.bytes += b
     def send_paragraph(self, blankline):
        ”"”Create a new paragraph if necessary.”"”
         if self.lines[-1].text == ”:
             return
        self.lines[-1].text += ’n' * (blankline+1)
        self.lines[-1].bytes += 2 * (blankline+1)
        self.lines.append(Writer.Paragraph())
     def send_literal_data(self, data):
        self.send_flowing_data(data)
     def send_line_break(self):
        self.send_paragraph(0)
This code doesn’t do any outputting yet, it just gathers the data. We now have a bunch of paragraphs in an array, we know their length, and we know roughly how many bytes of HTML were necessary to create them. Let’s see what emerge from our statistics.
這里代碼還沒有做輸出部分,它只是聚合數據。現在我們有一系列的文字段(用數組保存),以及它們的長度和生成它們所需要的HTML的大概字節數。現在讓我們來看看統計學帶來了什么。
Examining the Data
數據分析
Luckily, there are some patterns in the data. In the raw output below, you’ll notice there are definite spikes in the number of HTML bytes required to encode lines of text, notably around the title, both sidebars, headers and footers.
幸運的是,數據里總是存在一些模式。從下面的原始輸出你可以發現有些文本需要大量的HTML來編碼,特別是標題、側邊欄、頁眉和頁腳。
While the number of HTML bytes spikes in places, it remains below average for quite a few lines. On these lines, the text output is rather high. Calculating the density of text to HTML bytes gives us a better understanding of this relationship.
雖然HTML字節數的峰值多次出現,但大部分仍然低於平均值;我們也可以看到在大部分低HTML字節數的字段中,文本輸出卻相當高。通過計算文本與HTML字節數的比率(即密度)可以讓我們更容易明白它們之間的關系:
The patterns are more obvious in this density value, so it gives us something concrete to work with.
密度值圖更加清晰地表達了正文的密度更高,這是我們的工作的事實依據。
Filtering the Lines
過濾文本行
The simplest way we can filter lines now is by comparing the density to a fixed threshold, such as 50% or the average density. Finishing the LineWriter class:
過濾文本行的最簡單方法是通過與一個閾值(如50%或者平均值)比較密度值。下面來完成LineWriter類:
     def compute_density(self):
        ”"”Calculate the density for each line, and the average.”"”
        total = 0.0
         for l  in self.lines:
            l.density = len(l.text) / float(l.bytes)
            total += l.density
         # Store for optional use by the neural network.
        self.average = total / float(len(self.lines))
     def output(self):
        ”"”Return a string with the useless lines filtered out.”"”
        self.compute_density()
        output = StringIO.StringIO()
         for l  in self.lines:
             # Check density against threshold.
             # Custom filter extensions go here.
            if l.density > 0.5:
                output.write(l.text)
         return output.getvalue()
This rough filter typically gets most of the lines right. All the headers, footers and sidebars text is usually stripped as long as it’s not too long. However, if there are long copyright notices, comments, or descriptions of other stories, then those are output too. Also, if there are short lines around inline graphics or adverts within the text, these are not output.
這個粗糙的過濾器能夠獲取大部分正確的文本行。只要頁眉、頁腳和側邊欄文本並不非常長,那么所有的這些都會被剔除。然而,它仍然會輸出比較長的版本聲明、注釋和對其它故事的概述;在圖片和廣告周邊的比較短小的文本,卻被過濾掉了。
To fix this, we need a more complex filtering heuristic. But instead of spending days working out the logic manually, we’ll just grab loads of information about each line and use machine learning to find patterns for us.
要解決這個問題,我們需要更復雜些的啟發式過濾器。為了節省手工計算需要花費的無數時間,我們將利用機器學習來處理每一文本行的信息,以找出對我們有用的模式。
Supervised Machine Learning
監督式機器學習
Here’s an example of an interface for tagging lines of text as content or not:
這是一個標識文本行是否為正文的接口界面:
The idea of supervised learning is to provide examples for an algorithm to learn from. In our case, we give it a set documents that were tagged by humans, so we know which line must be output and which line must be filtered out. For this we’ll use a simple neural network known as the perceptron. It takes floating point inputs and filters the information through weighted connections between “neurons” and outputs another floating point number. Roughly speaking, the number of neurons and layers affects the ability to approximate functions precisely; we’ll use both single-layer perceptrons (SLP) and multi-layer perceptrons (MLP) for prototyping.
所謂的監督式學習就是為算法提供學習的例子。在這個案例中,我們給定一系列已經由人標識好的文檔——我們知道哪一行必須輸出或者過濾掉。我們用使用一個簡單的神經網絡作為感知器,它接受浮點輸入並通過“神經元”間的加權連接過濾信息,然后輸后另一個浮點數。大體來說,神經元數量和層數將影響獲取最優解的能力。我們的原型將分別使用單層感知器(SLP)和多層感知器(MLP)模型。
To get the neural network to learn, we need to gather some data. This is where the earlier LineWriter.output() function comes in handy; it gives us a central point to process all the lines at once, and make a global decision which lines to output. Starting with intuition and experimenting a bit, we discover that the following data is useful to decide how to filter a line:
我們需要找些數據來供機器學習。之前的LineWriter.output()函數正好派上用場,它使我們能夠一次處理所有文本行並作出決定哪些文本行應該輸出的全局結策。從直覺和經驗中我們發現下面的幾條原則可用於決定如何過濾文本行:
  • Density of the current line.
  • 當前行的密度
  • Number of HTML bytes of the line.
  • 當前行的HTML字節數
  • Length of output text for this line.
  • 當前行的輸出文本長度
  • These three values for the previous line,
  • 前一行的這三個值
  • … and the same for the next line.
  • 后一行的這三個值
For the implementation, we’ll be using Python to interface with FANN, the Fast Artificial Neural Network Library. The essence of the learning code goes like this:
我們可以利用FANN的Python接口來實現,FANN是Fast Artificial Neural NetWork庫的簡稱。基本的學習代碼如下:
from pyfann  import fann, libfann
# This creates a new single-layer perceptron with 1 output and 3 inputs.
obj = libfann.fann_create_standard_array(2, (3, 1))
ann = fann.fann_class(obj)
# Load the data we described above.
patterns = fann.read_train_from_file(‘training.txt’)
ann.train_on_data(patterns, 1000, 1, 0.0)
# Then test it with different data.
for datin, datout  in validation_data:
    result = ann.run(datin)
     print ’Got:’, result, ’ Expected:’, datout
Trying out different data and different network structures is a rather mechanical process. Don’t have too many neurons or you may train too well for the set of documents you have (overfitting), and conversely try to have enough to solve the problem well. Here are the results, varying the number of lines used (1L-3L) and the number of attributes per line (1A-3A):
嘗試不同的數據和不同的網絡結構是比較機械的過程。不要使用太多的神經元和使用太好的文本集合來訓練(過擬合),相反地應當嘗試解決足夠多的問題。使用不同的行數(1L-3L)和每一行不同的屬性(1A-3A)得到的結果如下:
The interesting thing to note is that 0.5 is already a pretty good guess at a fixed threshold (see first set of columns). The learning algorithm cannot find much better solution for comparing the density alone (1 Attribute in the second column). With 3 Attributes, the next SLP does better overall, though it gets more false negatives. Using multiple lines also increases the performance of the single layer perceptron (fourth set of columns). And finally, using a more complex neural network structure works best overall — making 80% less errors in filtering the lines.
有趣的是作為一個猜測的固定閾值,0.5的表現非常好(看第一列)。學習算法並不能僅僅通過比較密度來找出更佳的方案(第二列)。使用三個屬性,下一個SLP比前兩都好,但它引入了更多的假陰性。使用多行文本也增進了性能(第四列),最后使用更復雜的神經網絡結構比所有的結果都要更好,在文本行過濾中減少了80%錯誤。
Note that you can tweak how the error is calculated if you want to punish false positives more than false negatives.
注意:你能夠調整誤差計算,以給假陽性比假陰性更多的懲罰(寧缺勿濫的策略)。
Conclusion
結論
Extracting text from arbitrary HTML files doesn’t necessarily require scraping the file with custom code. You can use statistics to get pretty amazing results, and machine learning to get even better. By tweaking the threshold, you can avoid the worst false positive that pollute your text output. But it’s not so bad in practice; where the neural network makes mistakes, even humans have trouble classifying those lines as “content” or not.
從任意HTML文件中抽取正文無需編寫針對文件編寫特定的抽取程序,使用統計學就能獲得令人驚訝的效果,而機器學習能讓它做得更好。通過調整閾值,你能夠避免出現魚目混珠的情況。它的表現相當好,因為在神經網絡判斷錯誤的地方,甚至人類也難以判定它是否為正文。
Now all you have to figure out is what to do with that clean text content!
現在需要思考的問題是用這些“干凈”的正文內容做什么應用好呢?

垂直搜索-網頁正文提取

原文鏈接: http://www.beijing-open-party.org/大體上看,目前的文字抓取方式,無外乎以下三種方法:

 

  • 通過正則表達式抓取:通過諸如BeautifulSoup這樣的工具進行。
    • 方法簡單,但是性能可能會有問題。與所抓取的目標網頁依賴過大,一旦網頁格式發生變動,就需要對抓取的方式進行一些更新。出於偷懶的原則,如果程 序能夠自動識別變化,那樣才比較完美。
  • 標簽特征,本話題所述方法即屬於此類別。
  • 基於視覺的處理,跨越標簽領域,有一些的技術門檻,此話題暫不涉及。
    • (在2009年2月的OpenParty” 有狐”活動中,有位來自雅虎中國的朋友分享了一篇在“服務器端使用Firefox進行網頁抓取和內容識別工作”的話題,實際上就是基於視覺的處理 實現)

基於文本密度算法的實現,是上述的標簽特征類別的方法。基本公式:純文本字符數/HTML源碼字符數。

原始方法:

  1. 記錄HTML標簽起始位置
  2. 統計HTML源碼首尾包括的字符數和其中的文本字符數

使用Python的matplotlib對統計的結果進行圖示查看,從直方圖中直觀地可以發現,網頁中有一部分的文本密度明顯高於其它部分。在整個 過程中還可以使用Tidy軟件包來清理HTML代碼,實例中演示的Sina頁面,使用Tidy進行清理后進行識別的效果要好很多。

從實際狀況出發,對算法進行小調整:從以前的文本前后判斷,變成標簽前后判斷。

優點:數據的整體性更好。
缺點:數據的分布情況不夠直觀,有干擾。可以適當地加入一些值的過濾方式來實現

整個實現方法所使用的代碼量:加入注釋以及模式過濾的原腳本大約有200多行Python代碼,如果是根據網上論文的原始實現,大約100多行 Python代碼。

所參考、的論文中描述的人工智能文本識別方法:

  • 使用神經網絡模型
    • 可使用FANN庫,有相應的Python封裝
  • 采用原始的一刀切方式,會有丟行的現象產生。
  • 個別行的密度會比較小。

神經網絡模型的算法,可以采用機器進行學習的方式進行。不過要注意,學習所采用的原料和實際使用中所針對的目標相似度的關系也很重要。學習的量較 少,可能會達不到完成任務 所需的精度;而學習量過大,出現”過學習”的狀況,也可能會出現過度吻合,從而導致對目標數據的變化非常敏感。

其它智能方法,針對HTML標簽序列:

  • 統計方法
  • 貝葉斯
  • 馬爾可夫
  • CRF

不過為了達成我們的目標,找到最竅門的地方,才是最關鍵的。比如在很多應用場合下,看似粗曠的’一刀切’方法可能效果也非常不錯。

這里介紹的自然語言識別只是一個具體的分支應用,而這個大領域還包括很多其他的內容,如逐漸變熱的分詞技術,也是值得關注的。

總的來說,自然語言識別技術需要根據應用領域、應用環境來提供相應的解決方案。沒有銀彈!

我一知半解的記錄肯定略有偏差,想要詳細了解此內容的朋友(如查閱上文提到的論文等內容),歡迎訪問宋博士”提取HTML文檔正文“的頁面以及他的Blog訪問詳情。

 

 

宋博的原文我也先給貼出來,地址:http://www.elias.cn/MyProject/ExtMainText

ExtMainText —— 提取html文檔正文

1.  簡介

這是一個使用Python語言實現的函數庫,能夠幫助從html文檔中提取文檔正文,換句話說也就是能夠過濾頁面上的廣告、欄目導航等非正文內容。 此函數庫可以用在從其他網站抓取文章內容的過程中,以及幫助搜索引擎抓取器忽略無關內容,將頁面分析集中到網頁更有價值的部分。

函數實現的基本原理是“正文標簽密度法”,0.2版本計算網頁每個html標簽下的“正文長度/標簽下所有字符總 長”,取文檔中密度高於制定閾值的最長部分作為文檔正文輸出。原理見:The Easy Way to Extract Useful Text from Arbitrary HTML

對不同網站,因其語言特征及模板外觀設計不同,而應當分別指定不同的密度閾值,具體應該根據所有標簽的密度分布狀況 實驗確定。一般英文網站可以取閾值0.5,中文網站使用0.5作為閾值同樣能得到不錯的輸出結果。

  • 當filterMode為 False 時,代碼僅返回最長的一段正文,有可能會將博客的評論信息等過濾掉(當評論文字都比較短的時候);
  • 當filterMode為 True 時,代碼會過濾掉密度低於閾值的html片段,也即能夠保留多段正文文字,從而通常可以保留博客的評論信息。

函數最終輸出的是包含文檔正文的html片段,如果需要將提取的正文內容進一步轉換為text 純文本內容,則可以調用html2text

English Doc, See: En.ExtMainText

2.  腳本下載

2.1  更新記錄

  • 2010-01-26:解決有時html文本中的特殊字符造成編碼錯誤的問題。
  • 2009-12-05:改為使用lxml api實現,使用新的密度計算公式,並增加“使用過濾模式”的選項。
  • 2008-10-21:在__main__部分添加html向text轉換的代碼,直接執行ExtMainText將給出更直觀的輸出;作為0.1a版本發布。
  • 2008-10-19:完成基本功能,作為0.1版本發布。

3.  使用說明

作為庫函數使用時可參照源代碼的DocString以及“ if __name__ == ‘__main__’ ”部分。也可以直接運行此腳本文件:

python ExtMainText.py 輸入的html文件名

這樣腳本將以默認參數(0.5)提取該html文件的正文內容,並轉換為純文本輸出。另外請注意輸入的html文本的編碼,在0.2a之后的版本只接受unicode文本作為輸入,因此需要提前完成對 輸入文檔的解碼。

4.  后續改進方向

相對於固定閾值,使用神經網絡等智能方法能夠獲得更為准確的輸出,建議參考也談網頁正文提取[下]以及賴勇浩先生翻譯的從HTML文件中抽取正文的簡單方案

5.  與其他實現的比較

也談網頁正文提取[下]The Easy Way to Extract Useful Text from Arbitrary HTML兩 篇文章的非人工智能算法的部分(也就是使用靜態閾值方法來提取文章正文)在算法和代碼實現上都是完全一樣的。雖然都是使用文本密度來識別文章正文部分,但 他們對文本密度的計算方法和我的還是存在一定區別,這里以我個人的理解進行簡單的比較分析。

他們在計算文本密度時,從頭至尾逐步解析html,當遇到一行純文本內容時,以這一行純文本的長度作為“文本長 度”,以這一行純文本結束位置到上一行純文本結束位置在原始html中所跨越的字符總數作為“字符長度”,並用兩者的比值作為文本密度的值。這種計算方法 存在一定的不合理性。從物理意義上來講,“字符長度”應該是與修飾一段純文本相關的html代碼 總長。但他們的計算方法是將純文本之前的html標簽作為其修飾成分,對於前后匹配的html標簽來說,特別是純文本被括在多層表格 及<div>標簽之內的情況,不能保證將各層標簽的結束標簽算作此段純文本的修飾內容,相反卻很可能將之計算為下一行純文本所對應的字節長度 組成部分。在極端條件下,也即分析第一行純文本時,算法會將之前的所有html標簽算作字節組成部分,也即包含了<head>部分,這不合理 地極大地降低了密度的取值。雖然掃描一般html頁面遇到的第一行純文本通常是菜單或者導航部分,需要作為正文提取的可能性不大,但這種算法實現方法與其 預期體現的物理意義不能很好地吻合。

我的實現則將每個html標簽下涵蓋的所有內容作為整體來分析,比如對一個<div>標簽,算法將此起 始標簽與其對應結束標簽之間包括的所有純文本內容作為“文本長度”,包括的所有字節內容作為“字節長度”,如此計算文本密度,可以保證所涉及的字節一定是 與對應的純文本密切相關的。因此對於靜態閾值方法來說,估計能夠獲得稍好的正文提取准確度。

當然,那兩篇文章的方法也有一定好處,就是對純文本內容按照行來區分,對后續人工智能的訓練和處理過程來說更便於人 的操作和理解。但文中提及的神經網絡方法並不是唯一的選擇,或許可以不考慮文本行,而是從 html 標簽的出現順序上尋找規律。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM