歡迎光臨
每天分享高質量文章

實用乾貨:7個實體教你從PDF、Word和網頁中提取資料

導讀:本文的標的是介紹一些Python庫,幫助你從類似於PDF和Word DOCX 這樣的二進制檔案中提取資料。我們也將瞭解和學習如何從網絡信息源(web feeds)(如RSS)中獲取資料,以及利用一個庫幫助解析HTML文本並從文件中提取原始文本。

我們還將學習如何從不同來源提取原始文本,對其進行規範化,並基於它創建一個用戶定義的語料庫。

在本文中,你將學習7個不同的實體。我們將學習從PDF檔案、Word文件和Web中獲取資料。PDF和Word文件是二進制檔案,通過Web,你將獲得HTML格式的資料,因此,我們也會對資料執行規範化和原始文本轉換任務。

 

 

作者:克裡希納·巴夫薩、納雷什·庫馬爾、普拉塔普·丹蒂

如需轉載請聯繫大資料(ID:hzdashuju)

 

 

 

01 字串操作的重要性

 

作為一名NLP專家,你將要處理大量的文本內容。當你在處理文本時,你必須知道一些字串操作。我們將從幾個簡短的範例入手,幫助你理解str類及其在Python中的相關操作。

 

1. 準備工作

 

這裡,你僅僅需要Python解釋器和一個文本編輯器。我們將使用join(連接)、split(分割)、addition(加法)和multiplication(乘法)運算子以及索引。

 

2. 如何實現

 

(1)創建一個新的Python檔案,命名為StringOps1.py。

 

(2)定義以下兩個物件:

 

namesList = ['Tuffy','Ali','Nysha','Tim' ]
sentence = 'My dog sleeps on sofa'

 

第一個物件nameList是一個包含若干名字的字串串列,第二個物件sentence是一個包含一句話的字串物件。

 

(3)首先,我們看看join函式的特點以及它的功能:

 

names = ';'.join(namesList)
print(type(names), ':', names)

 

join()函式可以被任意一個string物件呼叫,它的輸入引數是一個str物件的串列。通過將呼叫字串的內容作為連接分隔符,它將所有str物件連接成一個str物件,並傳回連接後的物件。運行這兩行代碼後,你得到的輸出如下:

 

 : Tuffy;Ali;Nysha;Tim

 

(4)接下來,我們來看split方法的功能:

 

wordList = sentence.split(' ')
print((type(wordList)), ':', wordList)

當split函式呼叫一個字串時,它會將其內容分割為多個str物件,創建一個包含這些字串物件的串列,並傳回該串列。該函式接受單個str物件作為引數,表示分隔符。運行代碼,得到如下輸出:

 

 : ['My', 'dog', 'sleeps', 'on', 'sofa']

 

(5)算術運算子+和*也可以用於字串。添加以下代碼並輸出:

 

additionExample = 'ganehsa' + 'ganesha' + 'ganesha'
multiplicationExample = 'ganesha' * 2
print('Text Additions :', additionExample)
print('Text Multiplication :', multiplicationExample)

 

我們首先看一下輸出結果,隨後討論其工作原理:

 

Text Additions: ganehsaganeshaganesha
Text Multiplication: ganeshaganesha

 

+運算子被稱為連接符,它將字串連接為單個str物件,產生一個新的字串。如前所述,我們也可以使用*運算子對字串做乘法。此外,需要註意的是這些操作不會添加任何額外的內容,例如在字串之間插入空格。

 

(6)接下來,我們來瞭解一下字串中的字符索引。添加下列幾行代碼:

 

str = 'Python NLTK'
print(str[1])
print(str[-3])

 

首先,我們宣告一個新的 string 物件。然後可以直接訪問字串中的第二個字符(y)。這裡還有個小技巧:Python允許你在訪問任何串列物件時使用負索引,比如說-1意味著最後一個成員,-2是倒數第二個成員,依此類推。例如,在前面代碼的str物件中,索引7和-4是相同的字符N:

 

Output: <class 'str'> : Tuffy;Ali;Nysha;Tim
<class 'list'> : ['My''dog''sleeps''on''sofa']
Text Additions : ganehsaganeshaganesha
Text Multiplication : ganeshaganesha
y L

 

3. 工作原理

 

我們使用split()函式將一個字串變成了一個字串串列,並使用join()函式將一個字串串列變成了一個字串。接下來我們瞭解了有關字串的一些算術運算子的用法。

需要註意的是,我們不能在字串中使用“-”(負號)和“/”(除法)運算子。最後,我們瞭解瞭如何在任一字串中訪問單個字符,特別值得一提的是,我們可以在訪問字串時使用負索引。

 

本段實體非常簡單和直觀,主要是介紹Python允許的一些常見和不常見的字串操作。接下來,我們將在以上操作基礎上繼續學習一些字串操作。

 

 

02 深入實踐字串操作

 

接下來,我們將瞭解子字串、字串替換以及如何訪問一個字串的所有字符。

 

1. 如何實現

 

(1)創建一個新的Python檔案,命名為StringOps2.py並定義以下string物件:

 

str = 'NLTK Dolly Python'

 

(2)訪問str物件中以第四個字符作為結束的子串。

 

print('Substring ends at:',str[:4])

 

我們知道索引從零開始,因此將傳回由第0個到第3個字符組成的子串。運行代碼,輸出如下:

 

Substring ends at: NLTK

 

(3)訪問str物件中從某個點開始直到末尾的子串:

 

print('Substring starts from:',str[11:] )

 

以上代碼指示解釋器傳回str物件中從索引11到結束的一個子串。運行代碼,得到以下輸出:

 

Substring starts from: Python

 

(4)從str物件中訪問包含Dolly的子串。添加以下行:

 

print('Substring :',str[5:10])

 

以上代碼傳回從索引5到10的字符,不包括第10個字符。輸出是:

 

Substring : Dolly

 

(5)我們在前一段中已經瞭解了負索引在字串操作中的應用。現在我們試試看它在獲取子串中的作用:

 

print('Substring fancy:', str[-12:-7])
Run and check the output, it will be –
Substring fancy: Dolly

 

這裡得到的輸出與上一步完全相同!為了理解這個結果,我們做一些計算:-1表示最後一個字符,-2是倒數第二個字符,依此類推。你將會發現[5:10]和[-12:-7]在這個例子中得出的子串是相同的。

 

(6)瞭解in運算子在if陳述句中的用法:

 

if 'NLTK' in str:
 print('found NLTK')

 

運行以上代碼,程式的輸出如下所示:

 

found NLTK

 

如上所示,in運算子會檢查左邊的字串是否屬於右邊字串的子串。

 

(7)瞭解str物件中replace函式的使用:

 

replaced = str.replace('Dolly''Dorothy')
print('Replaced String:', replaced)

 

replace函式只需要兩個引數。第一個是需要被替換的子字串,第二個是用來替換前面子字串的新子字串。replace函式傳回一個新的string物件,並且它不會修改呼叫它的字串,運行代碼,有如下輸出:

 

Replaced String: NLTK Dorothy Python

 

(8)最後,迭代上面得到的replaced物件並訪問它的每一個字符:

 

print('Accessing each character:')
for s in replaced:
  print(s)

 

以上操作每次在新的一行輸出replaced物件的每個字符,最終輸出如下:

 

Output: Substring ends at: NLTK
Substring starts from: Python
Substring : Dolly
Substring fancy: Dolly
found NLTK
Replaced String: NLTK Dorothy Python
Accessing each character:
N
L 
T 
K 
D 
o 
r 
o 
t 
h 
y 
P 
y 
t 
h
o 
n

 

2. 工作原理

 

字串物件只是一個字符串列。正如第一步所示,我們可以像訪問一個串列那樣用for陳述句來訪問字串中的每個字符。任何串列的方括號內的字符“:”表示我們想要的一個子串列。

方括號內,如果字符“:”之後是一個數字n,表示我們希望獲得一個從串列索引0開始到索引n-1結束的子串列。同樣地,一個數字m後跟著字符“:”,則表示我們想要一個從串列索引m開始到串列末尾的子串列。

 

 

03 在Python中讀取PDF檔案

 

這個實體是從Python中訪問PDF檔案。首先,你需要安裝PyPDF2庫。

 

1. 準備工作

 

假設你已經安裝了pip。然後,在Python2或Python3版本上用pip安裝PyPDF2庫,你只需要在命令列中運行以下命令:

 

pip install pypdf2

 

如果你成功安裝了PyPDF2庫,就完成了準備工作。與此同時,你需要通過以下鏈接下載一些我們將在本段用到的測試文件:

https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0

 

2. 如何實現

 

(1)創建一個新的Python檔案,命名為pdf.py並添加以下代碼:

 

from PyPDF2 import PdfFileReader

 

這行代碼會匯入PyPDF2庫中的PdfFileReader類。

 

(2)在上面創建的檔案中添加如下Python函式,它的功能是讀取一個PDF檔案並傳回其全文:

 

def getTextPDF(pdfFileName, password = '')

 

該函式需要兩個引數,一個是你要讀取的PDF檔案路徑,一個是這個PDF檔案的密碼(如果有的話)。可見,password 引數是可選的。

 

(3)現在我們來定義這個函式。在該函式下添加如下代碼:

 

pdf_file = open(pdfFileName, 'rb')
read_pdf = PdfFileReader(pdf_file)

 

 

第一行代碼會以讀取和反向查找樣式打開檔案。第一行本質是一個Python檔案打開命令/函式,僅能打開非文本的二進制檔案。第二行將打開的檔案傳遞給PdfFileReader類,用於處理PDF文件。

 

(4)如果檔案設置了密碼保護,接下來是解密被密碼保護的PDF檔案:

 

if password != '':
read_pdf.decrypt(password)

 

如果在函式呼叫時設置了密碼,那麼我們在解密這個檔案時也同樣需要密碼。

 

(5)從PDF檔案中讀取文本:

 

text = []
for i in range(0,read_pdf.getNumPages()-1):
text.append(read_pdf.getPage(i).extractText())

 

創建一個字串串列,並將每一頁的文本都添加到這個串列中。

 

(6)傳回最終的輸出結果:

 

return '\n'.join(text)

 

將串列中所有的字串都連接起來,並且在每個字串之間都加一個換行符,傳回連接後的單一字串。

 

(7)在pdf.py目錄下創建另一個名為TestPDFs.py 的檔案,添加以下匯入陳述句:

 

import pdf

 

(8)現在我們打印輸出兩個文件中的文本,其中一個是受密碼保護的,一個是未加密的:

 

pdfFile = 'sample-one-line.pdf'
pdfFileEncrypted = 'sample-one-line.protected.pdf'
print('PDF 1: \n',pdf.getTextPDF(pdfFile))
print('PDF 2: \n',pdf.getTextPDF(pdfFileEncrypted,'tuffy'))

 

輸出:本實體的前六步只是創建了一個Python函式,並不向控制台輸出內容,第七和第八步會輸出以下內容:

 

This is a sample PDF document I am using to demonstrate in the
tutorial.
This is a sample PDF document
password protected.

 

3. 工作原理

 

PyPDF2是用於提取PDF檔案內容的一個純Python庫。該庫有很多功能,可用於裁剪頁面、疊加圖像數字簽名、創建新的PDF檔案等。但是,對NLP工程師需要實現的文本分析任務來說,該庫只用來讀取內容。

在第二步中,以反向查找樣式打開檔案很重要,因為當加載檔案內容時,PyPDF2模塊試圖從尾部開始讀取檔案內容。此外,如果PDF檔案是受密碼保護的,而你沒有在訪問檔案前解密檔案,Python解釋器將丟擲一個PdfReadError錯誤。

 

 

04 在Python中讀取Word檔案

 

這裡,我們將學習如何加載和讀取Word/DOCX文件。用於讀取Word/DOCX檔案的相關庫會更加全面,在這些庫中我們還可以處理段落邊界、文本樣式以及對所謂的run物件的操作。我們將會瞭解以上提到的所有內容,因為這些內容在文本分析任務中是至關重要的。

 

Tip: 如果你沒有安裝Microsoft Word軟體,你可以使用Liber Office和Open Office軟體的開源版本來創建和編輯“.docx”檔案。

 

1. 準備工作

 

假設你已經在你的機器上安裝了pip,我們將使用pip來安裝python-docx庫。不要將它與另一個名為docx的庫混淆,這是兩個完全不同的庫。我們將從python docx庫中匯入docx物件。在命令列中執行下麵的命令將安裝這個庫:

 

pip install python-docx

 

成功安裝了該庫後,繼續下一步,我們將在這個實體中使用一個測試文件,如果你已經通過本文第一段提供的鏈接下載了所有文件,你應該已具備相關文件。如果沒有,請從以下鏈接下載sample-one-line.docx文件。

https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0

 

現在,準備工作就全部完成了。

 

2. 如何實現

 

(1)創建一個新的Python檔案,命名為word.py並添加以下匯入代碼:

 

import docx

 

這裡只需匯入python-docx模塊的docx物件。

 

(2)定義getTextWord函式:

 

def getTextWord(wordFileName):

 

該函式需要一個字串引數wordFileName,包含你要讀取的Word檔案的絕對路徑。

 

(3)初始化doc 物件:

 

doc = docx.Document(wordFileName)

 

此時doc物件加載了你要讀取的Word檔案。

 

(4)接下來我們要從已經加載文件的doc物件中讀取文本,添加以下代碼來實現:

 

fullText = []
for para in doc.paragraphs:
  fullText.append(para.text)

 

首先初始化一個字串串列fullText,然後採用for迴圈逐段從文件中讀取文本,並把每段都放到fullText串列中去。

 

(5)然後,我們將所有的片段/段落連接為一個字串物件,並將其作為函式的輸出結果傳回:

 

return '\n'.join(fullText)

 

通過以上操作,我們將fullText陣列的所有元素用“\ n”分隔符連接起來,並傳回連接後的物件。最後儲存該Python檔案並退出。

 

(6)創建另一個Python檔案,命名為TestDocX.py,並添加以下匯入宣告:

 

import docx
import word

 

這裡只需匯入docx庫以及我們在前五步中實現的word.py檔案。

 

(7)現在我們將要讀取一個DOCX檔案並使用我們在word.py中實現的API打印輸出它的全部內容。添加以下兩行代碼:

 

docName = 'sample-one-line.docx'
print('Document in full :\n',word.getTextWord(docName))

 

首先在第一行代碼中初始化文件的路徑,然後使用API打印輸出文件的全部內容。當你運行這部分代碼時,得到以下輸出:

 

Document in full :

 

這是一個帶有一些粗體文本、一些斜體文本和一些下劃線文本的PDF示例文件。我們還嵌入了一個標題,如下所示:

 

This is my TITLE.
This is my third paragraph.

 

(8)正如前面提到的,Word / DOCX文件是一個更加豐富的信息來源,除了提供文本內容外,還能提供很多信息。現在我們來看有關段落的信息。添加以下四行代碼:

 

doc = docx.Document(docName)
print('Number of paragraphs :',len(doc.paragraphs))
print('Paragraph 2:',doc.paragraphs[1].text)
print('Paragraph 2 style:',doc.paragraphs[1].style)

 

以上代碼的第二行打印出了給定文件中段落的數量。第三行打印出了文件中第二段的內容。而第四行將會打印出第二段的樣式,比如在這個例子中的樣式就是Title型別。當你運行以上代碼後,輸出將如下所示:

 

Number of paragraphs : 3
Paragraph 2: This is my TITLE.
Paragraph 2 style: _ParagraphStyle('Title') id: 4374023248

 

(9)接下來,我們將瞭解什麼是run物件。添加以下代碼:

 

print('Paragraph 1:',doc.paragraphs[0].text)
print('Number of runs in paragraph 1:',len(doc.paragraphs[0].runs))
for idx, run in enumerate(doc.paragraphs[0].runs):
  print('Run %s : %s' %(idx,run.text))

 

首先,我們獲得文件第一段的全部內容。然後,我們獲得第一段中run物件的數目。最後,我們把每個run物件打印輸出。

 

(10)為了明確每個run物件的格式,添加以下代碼:

 

print('is Run 0 underlined:',doc.paragraphs[0].runs[5].underline)
print('is Run 2 bold:',doc.paragraphs[0].runs[1].bold)
print('is Run 7 italic:',doc.paragraphs[0].runs[3].italic)

 

這段代碼的各行分別在檢查相應run物件的下劃線樣式、粗體樣式以及斜體樣式。最終輸出如下:

 

Output: Document in full :
This is a sample PDF document with some text in BOLD, some in
ITALIC and some underlined. We are also embedding a Title down
below.
This is my TITLE.
This is my third paragraph.
Number of paragraphs : 3
Paragraph 2: This is my TITLE.
Paragraph 2 style: _ParagraphStyle('Title') id: 4374023248
Paragraph 1: This is a sample PDF document with some text in BOLD,
some in ITALIC and some underlined. We're also embedding a Title
down below.
Number of runs in paragraph 1: 8
Run 0 : This is a sample PDF document with
Run 1 : some text in BOLD
Run 2 : ,
Run 3 : some in ITALIC
Run 4 : and
Run 5 : some underlined.
Run 6 : We are also embedding a Title down below
Run 7 : .
is Run 0 underlined: True
is Run 2 bold: True
is Run 7 italic: True

 

3. 工作原理

 

首先,我們在word.py檔案中寫了一個函式,它將讀取給定的DOCX檔案並傳回一個包含檔案全部內容的字串物件。前面的輸出內容大都是不需要解釋的,我特別闡述了關於Paragraph和Run的輸出內容。DOCX檔案的結構可以用python-docx庫的三個資料型別來表示,其中最高一級是Document物件。

 

每個文件都包含多個段落。文件中出現新的一行或一個回車,就表示開始一個新的段落。每個段落用多個Run物件表示段落內格式的變化,這裡的格式包含有字體、尺寸、顏色和其他樣式元素(如粗體、斜體、下劃線等等)。這些元素每次發生變化時,都會創建一個新的Run物件。

 

 

05 使用PDF、DOCX和純文本檔案,創建用戶自定義的語料庫

 

現在我們要創建自己的語料庫,而不是使用從互聯網上得到的語料庫。

 

1. 準備工作

 

在準備方面,我們將使用本文第一個實體中提到的Dropbox檔案夾中的幾個檔案。如果你已經從那個檔案夾中下載了全部的檔案,那麼你已經完成了準備工作。否則,請從

https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0

下載如下檔案:

 

  • sample_feed.txt

  • sample-pdf.pdf

  • sample-one-line.docx

 

如果你沒有按照本文的順序來完成實體,那麼你需要先回頭看看本文的前兩個實體。我們將用到本文前兩個實體中完成的兩個模塊 word.py和pdf.py。本段實體更多是關於本文前兩個實體所做工作的應用以及語料庫概念的應用。下麵我們來看實際的代碼。

 

2. 如何實現

 

(1)創建一個新的Python檔案,命名為createCorpus.py並添加以下代碼:

 

import os
import word, pdf
from nltk.corpus.reader.plaintext import PlaintextCorpusReader

 

我們匯入os庫用於與檔案有關的操作,word庫和pdf庫是本文前兩段完成的庫,最後匯入的PlaintextCorpusReader是為了完成語料庫建立這一最終標的。

 

(2)編寫一個簡單的函式,用來打開並讀取一個純文本檔案,並將其全部內容作為string物件傳回。添加以下代碼:

 

def getText(txtFileName):
  file = open(txtFileName, 'r')
  return file.read()

 

第一行代碼定義了函式及其輸入引數。第二行代碼以只讀方式打開檔案(open函式的第二個引數r表示以只讀方式打開)。第三行代碼讀取打開檔案的內容並將其作為string物件傳回。

 

(3)在磁盤或檔案系統中創建一個新檔案夾corpus。添加以下三行代碼:

 

newCorpusDir = 'mycorpus/'
if not os.path.isdir(newCorpusDir):
    os.mkdir(newCorpusDir)

 

第一行定義的string物件包含了新檔案夾名,第二行檢查該檔案夾在磁盤或檔案系統中是否存在,第三行則通過執行os.mkdir()函式在磁盤上創建一個給定名字的檔案夾。以上代碼執行後將在你的Python檔案所在的工作目錄下創建一個名為mycorpus的新檔案夾。

 

(4)然後,逐個讀取前面提到的三個檔案。首先從純文本檔案開始,添加以下代碼:

 

txt1 = getText('sample_feed.txt')

 

呼叫之前完成的getText函式,它將讀取Sample_feed.txt檔案並將輸出結果存入名為txt1的字串物件中。

 

(5)現在,添加以下代碼來讀取PDF檔案:

 

txt2 = pdf.getTextPDF('sample-pdf.pdf')

 

這裡使用了PDF.py模塊的getTextPDF()函式,它將讀取sample-pdf.pdf檔案並將檔案內容存入名為txt2的字串物件中。

 

(6)最後,通過以下代碼讀取DOCX檔案:

 

txt3 = word.getTextWord('sample-one-line.docx')

 

這裡使用了word.py模塊的getTexWord()函式,它將讀取sample-one-line.docx檔案並將檔案內容存入名為txt3的字串物件中。

 

(7)接下來,將上面讀到的三個字串物件寫到磁盤檔案中。添加以下代碼:

 

files = [txt1,txt2,txt3]
for idx, f in enumerate(files):
    with open(newCorpusDir+str(idx)+'.txt''w'as fout:
        fout.write(f)

 

  • 第一行:創建一個包含以上三個字串物件的陣列

  • 第二行:使用for迴圈來遍歷files陣列

  • 第三行:以只寫樣式打開一個新檔案(採用w選項呼叫open函式)

  • 第四行:將當前字串內容寫到檔案中

 

(8)在mycorpus目錄下,也就是我們之前存放檔案的目錄下新建一個PlainTextCorpus物件:

 

newCorpus = PlaintextCorpusReader(newCorpusDir, '.*')

 

以上一行代碼看似簡單,但是它在內部做了很多的文本處理,如識別段落、句子、單詞等等。該函式的兩個引數分別是語料庫目錄的路徑以及要處理的檔案名樣式(這裡我們已經設置corpus reader可以處理該目錄下所有的檔案)。通過以上步驟,我們創建了一個用戶自定義的語料庫。

 

(9)接下來,我們來看PlainTextCorpusReader是否加載正常。添加以下代碼來進行測試:

 

print(newCorpus.words())
print(newCorpus.sents(newCorpus.fileids()[1]))
print(newCorpus.paras(newCorpus.fileids()[0]))

 

第一行代碼將打印輸出語料庫包含的所有單詞陣列(部分)。第二行代碼將打印輸出檔案1.txt中的句子。第三行代碼將打印輸出檔案0.txt中的段落:

 

Output: ['Five', 'months', '.', 'That', "'", 's', 'how', ...]
[['A', 'generic', 'NLP'], ['(', 'Natural', 'Language',
'Processing', ')', 'toolset'], ...]
[[['Five', 'months', '.']], [['That', "'", 's', 'how', 'long',
'it', "'", 's', 'been', 'since', 'Mass', 'Effect', ':',
'Andromeda', 'launched', ',', 'and', 'that', "'", 's', 'how',
'long', 'it', 'took', 'BioWare', 'Montreal', 'to', 'admit', 'that',
'nothing', 'more', 'can', 'be', 'done', 'with', 'the', 'ailing',
'game', "'", 's', 'story', 'mode', '.'], ['Technically', ',', 'it',
'wasn', "'", 't', 'even', 'a', 'full', 'five', 'months', ',', 'as',
'Andromeda', 'launched', 'on', 'March', '21', '.']], ...]

 

3. 工作原理

 

該實體最後一步的輸出很簡單直接,展示了各個物件不同的特征。輸出內容的第一行是新語料庫的單詞串列,它與句子、段落、檔案等更高級的結構沒有關係。

第二行是1.txt檔案中所有句子組成的串列,其中每個句子都是由該句子中單詞組成的串列。

第三行是0.txt檔案中所有段落組成的串列,其中每個段落物件又是由該段落中的句子組成的串列。從中可以發現,這些段落和句子保留了很多原有的結構。

 

 

06 讀取RSS信息源的內容

 

豐富網站摘要(Rich Site Summary,RSS)信息源(feed)是一種計算機可讀格式,用於傳送互聯網上定期更新的內容。大多數提供通知信息的網站以這種格式提供更新,例如新聞文章、在線出版物等。訂閱者可以通過規範化格式定期訪問其更新信息。

 

1. 準備工作

 

本段實體的標的是讀取一個RSS信息源並訪問其中的一條內容。為此,我們將使用全球之聲(Mashable)提供的RSS信息源。全球之聲是一個數字媒體網站。簡而言之,它是一個科技和社交媒體的博客串列。該網站的RSS信息源網址(URL)是:

http://feeds.mashable.com/Mashable

另外,我們需要用feedparser庫來讀取RSS信息源。打開終端並運行以下命令即可在你的計算機上安裝這個庫:

 

pip install feedparser

 

安裝好feedparser庫後,我們就可以開始實現第一個讀取RSS信息源的Python程式。

 

2. 如何實現

 

(1)創建一個新的Python檔案,命名為rssReader.py,並添加以下代碼:

 

import feedparser

 

(2)將全球之聲信息源(Mashable feed)載入記憶體中,添加以下代碼:

 

myFeed = feedparser.parse("http://feeds.mashable.com/Mashable")

 

myFeed物件包含全球之聲信息源的第一頁,通過feedparser自動下載和解析該信息源並填充到合適的位置。myFeed物件的條目串列將包含每個帖子(post)。

 

(3)檢查當前信息源的標題並計算帖子數目:

 

print('Feed Title :', myFeed['feed']['title'])
print('Number of posts :', len(myFeed.entries))

 

在第一行代碼中,我們通過myFeed物件獲取到了信息源的標題。在第二行代碼中,我們計算了myFeed物件中entries物件的長度。如前所述,entries物件是一個包含解析後信息源中所有帖子的串列。運行代碼,輸出如下所示:

 

Feed Title: Mashable
Number of posts : 30

 

標題是Mashable,當前,Mashable每次最多存放30個帖子到信息源。

 

(4)從entries串列中獲取第一個post,並打印輸出其標題:

 

post = myFeed.entries[0]
print('Post Title :',post.title)

 

在第一行代碼中,我們獲取了entries串列中的第一個元素並將其加載到post物件中。在第二行代碼中,我們打印輸出了post物件的標題。運行代碼,輸出應該與以下內容相似:

 

Post Title: The moon literally blocked the sun on Twitter

 

這裡提到輸出內容應該與其相似而不是完全一樣,是因為信息源在不斷自我更新。

 

(5)訪問post的原始HTML內容,並將其打印輸出:

 

content = post.content[0].value
print('Raw content :\n',content)

 

首先,我們訪問post的內容物件並獲取其具體值,打印輸出如下:

 

Output: Feed Title: Mashable
Number of posts : 30
Post Title: The moon literally blocked the sun on Twitter
Raw content :
src="https://i.amz.mshcdn.com/DzkxxIQCjyFHGoIBJoRGoYU3Y8o=/575x323/
filters:quality(90)/https%3A%2F%2Fblueprint-apiproduction.s3.amazonaws.com%2Fuploads%2Fcard%2Fimage%2F569570%2F0ca
3e1bf-a4a2-4af4-85f0-1bbc8587014a.jpg" />

width: 50px;”>href=”http://twitter.com/share?via=Mashable&text;=The+moon+literally
+blocked+the+sun+on+Twitter&url;=http%3A%2F%2Fmashable.com%2F2017%2F
08%2F21%2Fmoon-blocks-sun-eclipse-2017-
twitter%2F%3Futm_campaign%3DMash-Prod-RSS-Feedburner-All-
Partial%26utm_cid%3DMash-Prod-RSS-Feedburner-All-Partial”
style=”margin: 10px;”>

The national space agency threw shade the best way it knows how:
by blocking the sun. Yep, you read that right.

 

 

HA HA HA I’ve blocked the Sun! Make way for the Moonhref=”https://twitter.com/hashtag/SolarEclipse2017?src=hash”>#Solar
Eclipse2017

 

 href=”https://t.co/nZCoqBlSTe”>pic.twitter.com/nZCoqBlSTe

— NASA Moon (@NASAMoon) href=”https://twitter.com/NASAMoon/status/899681358737539073″>Augus
t 21, 2017

 

 

3. 工作原理

 

互聯網上大多數的RSS信息源都以時間順序排列,將最新的帖子放到最上面。因此,在該實體中我們每次訪問的都是信息源提供的最新內容。信息源本身是不斷更新的。所以,每次運行程式時,輸出的格式保持不變,但是輸出的內容卻可能發生改變,這取決於信息源更新的速度。

另外,我們在控制台直接輸出原始的HTML文本而不是其文本內容。接下來,我們將解析HTML並從頁面獲取我們需要的信息。最後,本實體可以附加以下內容:讀取你想要的任何信息源,將信息源中所有帖子的信息儲存到磁盤,並利用它創建一個純文本的語料庫。當然,你可以從上一個和下一個實體中獲得啟發。

 

 

07 使用BeautifulSoup解析HTML

 

大多數情況下,你需要處理的網上資料都以HTML頁面的形式存在。因此,我們認為有必要向你介紹Python的HTML解析方法。有很多Python模塊可以用來解析HTML,在接下來的實體中,我們將使用BeautifulSoup4庫來解析HTML。

 

1. 準備工作

 

BeautifulSoup4包適用於Python2和Python3。在使用這個包之前,我們需要提前下載並將它安裝在解釋器上。和之前一樣,我們將使用pip來安裝這個包。在命令列運行以下命令:

 

pip install beautifulsoup4

 

另外,你還需要本文Dropbox檔案夾中的sample-html.html檔案。如果你還沒有下載該檔案,請從以下鏈接下載:

https://www.dropbox.com/sh/bk18dizhsu1p534/AABEuJw4TArUbzJf4Aa8gp5Wa?dl=0

 

2. 如何實現

 

(1)完成所有準備工作後,從匯入以下宣告開始:

 

from bs4 import BeautifulSoup

 

從bs4模塊中匯入BeautifulSoup類,它將用於解析HTML。

 

(2)將一個HTML檔案加載到BeautifulSoup物件中:

 

html_doc = open('sample-html.html''r').read()
soup = BeautifulSoup(html_doc, 'html.parser')

 

在第一行代碼中,我們將sample-html.html檔案的內容加載到str物件html_doc中。然後,創建了一個BeautifulSoup物件,需要解析的HTML檔案作為第一個引數,html.parser作為第二個引數。通過以上操作,BeautifulSoup物件使用html解析器來解析文件。它將文件內容加載到soup物件中進行解析以備使用。

 

(3)soup物件最主要、最簡單且最有用的功能就是去除所有的HTML標簽並獲取文本內容。添加以下代碼:

 

print('\n\nFull text HTML Stripped:')
print(soup.get_text())

 

在soup物件上呼叫的get_text()方法將傳回HTML標簽去除後的檔案內容。運行以上代碼,將得到以下輸出:

 

Full text HTML Stripped:
Sample Web Page
Main heading
This is a very simple HTML document
Improve your image by including an image.
Add a link to your favorite Web site.
This is a new sentence without a paragraph break, in bold italics.
This is purely the contents of our sample HTML document without any
of the HTML tags.

 

(4)有時不僅需要去除HTML標簽,可能還需要獲取特定標簽的內容。訪問其中的一個標簽:

 

print('Accessing the , end=' ')
print(soup.title)

 

soup.title將傳回檔案中的第一個標題(title)標簽。以上代碼的輸出如下所示:

 

Accessing the 

 

(5)現在,我們需要某個HTML標簽的文本內容。通過以下代碼獲取

標簽的內容:

 

 

print('Accessing the text of 

 tag :’

 

, end=' ')
print(soup.h1.string)

 

soup.h1.string命令將傳回以

標簽開頭的文本。以上代碼的輸出如下所示:

 

 

Accessing the text of 

 tag : Main heading

 

 

(6)訪問標簽的屬性。這裡,我們將訪問img標簽的alt屬性。添加以下代碼行:

 

print('Accessing property of  tag :', end=' ')
print(soup.img['alt'])

 

通過仔細觀察,你會發現訪問標簽屬性的語法和訪問標簽文本的語法是不同的。運行以上代碼,得到以下輸出:

 

Accessing property of  tag : A Great HTML Resource

 

(7)最後,一個HTML檔案中同一型別的標簽可能多次出現。使用“.”語法僅能獲取檔案中第一次出現的標簽。為了獲取所有的標簽,我們將使用find_all()函式,如下所示:

 

print('\nAccessing all occurences of the 

tag :’

 

)
for p in soup.find_all('p'):
    print(p.string)

 

在BeautifulSoup物件上呼叫find_all()函式,引數是標簽名,它將搜索整個HTML樹並傳回符合條件的標簽串列。我們使用for迴圈來遍歷該串列,並將BeautifulSoup物件中所有

標簽的內容/文本打印並輸出:

 

 

Output: Full text HTML Stripped:
Sample Web Page
Main heading
This is a very simple HTML document
Improve your image by including an image.
Add a link to your favorite Web site.
This is a new sentence without a paragraph break, in bold italics.
Accessing the 
Accessing the text of 

 tag : Main heading
Accessing property of  tag : A Great HTML Resource
Accessing all occurences of the

tag :
This is a very simple HTML document
Improve your image by including an image.
None

 

 

3. 工作原理

 

BeautifulSoup4是一個很方便的庫,可以用於解析任何HTML和XML內容。它支持Python內置的HTML解析器,但是你也可以使用其他第三方的解析器,例如,lxml解析器和純Python的html5lib解析器。

這裡,我們使用Python內置的HTML解析器。如果你瞭解了HTML並會編寫簡單的HTML代碼的話,輸出結果是非常容易理解的。

 

關於作者:克裡希納·巴夫薩(KrishnaBhavsar)花了大約10年時間在各行業領域如酒店業、銀行業、醫療行業等進行自然語言處理、社交媒體分析和文本挖掘方面的研究。他致力於用不同的NLP語料庫如StanfordCoreNLP、IBM的 SystemText和BigInsights、GATE和NLTK來解決與文本分析有關的行業問題。

納雷什·庫馬爾(NareshKumar)曾為財富500強企業設計、實施和運行超大型因特網應用程式,在這方面他擁有超過十年的專業經驗。他是一位全棧架構師,在電子商務、網絡托管、醫療、大資料及分析、資料流、廣告和資料庫等領域擁有豐富的實踐經驗。

本文摘編自《自然語言處理Python進階》,經出版方授權發佈。

延伸閱讀《自然語言處理Python進階

點擊上圖瞭解及購買

轉載請聯繫微信:togo-maruko

推薦語:本書包含的實體可以讓你學會使用NLTK(處理NLP任務的主要Python平臺)完成自然語言處理的各種任務,涵蓋了自然語言理解、自然語言處理和句法分析等。 

赞(0)

分享創造快樂