基於文本密度的新聞正文抽取方法之Python實現


參考文章鏈接: http://www.cnblogs.com/jasondan/p/3497757.html 

        http://d.wanfangdata.com.cn/Patent/CN201410007832.6/

    

基於網頁分析構思出的正文提取算法

回顧以上的網頁分析,如果按照文本密度來找提取正文,那么就是寫這么一個算法,能夠從過濾html標簽后的文本中找到正文文本的起止行號,行號之間的文本就是網頁正文部分。

還是從上面三個網頁的分析結果看,他們都有這么一個特性:正文部分的文本密度要高出非正文部分很多。我們按照這個特性就可以很容易將算法實現,那就是基於閾(讀音:yu)值去分析正文所在的位置。

那么接下來就需要解決一些問題:

  • 如何確定閾值?
  • 如何分析,一行行的分析?還是?

閾值的確定可以通過統計分析得出一個比較好的值,我在實際處理過程中,發現這個值取180是比較合適的,也就是分析文本的時候,如果所分析的文本超過了180,那么就可以認為到達了正文部分。

再有就是如何分析的問題,這個其實比較容易確定,一行行的分析效果肯定不好,如果在按行分析的過程中往下在分析幾行作為一次分析效果比較好。也就是一次性分析上5行左右,將字符累加起來,看看有沒有達到設定的閾值,如果達到了,那么認為已經進入正文部分了。

import re
from bs4 import BeautifulSoup,Comment
import requests

authorset ={'責任編輯','作者'}

def getcontentfromweb(src):
    obj = requests.get(src)
    return obj.text

def filter_tags(html_str):
    soup =BeautifulSoup(html_str)
    title =soup.title.string.encode().decode('utf-8')
    [script.extract() for script in soup.findAll('script')]
    [style.extract() for style in soup.findAll('style')]
    comments = soup.findAll(text=lambda text: isinstance(text, Comment))
    [comment.extract() for comment in comments]
    reg1 = re.compile("<[^>]*>")
    content = reg1.sub('', soup.prettify()).split('\n')
    return title,content

def getcontent(lst,title,authorset):
    lstlen = [len(x) for x in lst]
    threshold=50
    startindex = 0
    maxindex = lstlen.index(max(lstlen))
    endindex = 0
    for i,v in enumerate(lstlen[:maxindex-3]):
        if v> threshold and lstlen[i+1]>5 and lstlen[i+2]>5 and lstlen[i+3]>5:
            startindex = i
            break
    for i,v in enumerate(lstlen[maxindex:]):
        if v< threshold and lstlen[maxindex+i+1]<10 and lstlen[maxindex+i+2]<10 and lstlen[maxindex+i+3]<10:
            endindex = i
            break
    content =['<p>'+x.strip()+'</p>' for x in lst[startindex:endindex+maxindex] if len(x.strip())>0]
    return content

def run(url):
    ctthtml=getcontentfromweb(url)
    title,content =filter_tags(ctthtml)
    newcontent =getcontent(content,title,authorset)
    ctt =''.join(newcontent)
    return title,ctt

 


免責聲明!

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



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