本篇文章給大家分享的是有關(guān)Python中如何解析HTML,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
成都服務(wù)器托管,成都創(chuàng)新互聯(lián)提供包括服務(wù)器租用、中國電信成都樞紐中心、帶寬租用、云主機、機柜租用、主機租用托管、CDN網(wǎng)站加速、域名與空間等業(yè)務(wù)的一體化完整服務(wù)。電話咨詢:028-86922220
這是一個典型的圖像標(biāo)簽:
我對 src=
之后的***組引號之間的部分很感興趣。 在尋找了一些解決方案后,我找到一個名為 BeautifulSoup 的 Python 模塊。 腳本的核心部分如下所示:
soup = BeautifulSoup(all_text, 'html.parser')match = soup.findAll("img")if len(match) > 0: for m in match: imagelist.append(str(m))
我們可以使用這個 findAll
方法來挖出圖片標(biāo)簽。 這是一小部分輸出:
到現(xiàn)在為止還挺好。我原以為下一步就可以搞定了,但是當(dāng)我在腳本中嘗試了一些字符串方法時,它返回了有關(guān)標(biāo)記的錯誤而不是字符串的錯誤。 我將輸出保存到一個文件中,并在 KWrite 中進行編輯。 KWrite 的一個好處是你可以使用正則表達式(regex)來做“查找和替換”操作,所以我可以用 \n 替換
,這樣可以看得更清楚。 KWrite 的另一個好處是,如果你用正則表達式做了一個不明智的選擇,你還可以撤消。
但我認(rèn)為,肯定有比這更好的東西,所以我轉(zhuǎn)而使用正則表達式,或者更具體地說 Python 的 re
模塊。 這個新腳本的相關(guān)部分如下所示:
match = re.findall(r'src="(.*)/>', all_text)if len(match)>0: for m in match: imagelist.append(m)
它的一小部分輸出如下所示:
images/cmcanvas.png" title="Context Menu for the document canvas" alt="Context Menu for the document canvas" />乍一看,它看起來與上面的輸出類似,并且附帶有去除圖像的標(biāo)簽部分的好處,但是有令人費解的是還夾雜著表格標(biāo)簽和其他內(nèi)容。 我認(rèn)為這涉及到這個正則表達式
src="(.*)/>
,這被稱為貪婪,意味著它不一定停止在遇到/>
的***個實例。我應(yīng)該補充一點,我也嘗試過src="(.*)"
,這真的沒有什么更好的效果,我不是一個正則表達式專家(只是做了這個),找了各種方法來改進這一點但是并沒什么用。做了一系列的事情之后,甚至嘗試了 Perl 的
HTML::Parser
模塊,最終我試圖將這與我為 Scribus 編寫的一些腳本進行比較,這些腳本逐個字符的分析文本內(nèi)容,然后采取一些行動。 為了最終目的,我終于想出了所有這些方法,并且完全不需要正則表達式或 HTML 解析器。 讓我們回到展示的那個img
標(biāo)簽的例子。我決定回到
src=
這一塊。 一種方法是等待s
出現(xiàn),然后看下一個字符是否是r
,下一個是c
,下一個是否=
。 如果是這樣,那就匹配上了! 那么兩個雙引號之間的內(nèi)容就是我所需要的。 這種方法的問題在于需要連續(xù)識別上面這樣的結(jié)構(gòu)。 一種查看代表一行 HTML 文本的字符串的方法是:for c in all_text:但是這個邏輯太亂了,以至于不能持續(xù)匹配到前面的
c
,還有之前的字符,更之前的字符,更更之前的字符。***,我決定專注于
=
并使用索引方法,以便我可以輕松地引用字符串中的任何先前或?qū)淼淖址?這里是搜索部分:index = 3 while index < linelength: if (all_text[index] == '='): if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and (all_text[index-1] == 'c'): imagefound(all_text, imagelist, index) index += 1 else: index += 1 else: index += 1我用第四個字符開始搜索(索引從 0 開始),所以我在下面沒有出現(xiàn)索引錯誤,并且實際上,在每一行的第四個字符之前不會有等號。 ***個測試是看字符串中是否出現(xiàn)了
=
,如果沒有,我們就會前進。 如果我們確實看到一個等號,那么我們會看前三個字符是否是s
、r
和c
。 如果全都匹配了,就調(diào)用函數(shù)imagefound
:def imagefound(all_text, imagelist, index): end = 0 index += 2 newimage = '' while end == 0: if (all_text[index] != '"'): newimage = newimage + all_text[index] index += 1 else: newimage = newimage + '\n' imagelist.append(newimage) end = 1 return我們給函數(shù)發(fā)送當(dāng)前索引,它代表著
=
。 我們知道下一個字符將會是"
,所以我們跳過兩個字符,并開始向名為newimage
的控制字符串添加字符,直到我們發(fā)現(xiàn)下一個"
,此時我們完成了一次匹配。 我們將字符串加一個換行符(\n
)添加到列表imagelist
中并返回(return
),請記住,在剩余的這個 HTML 字符串中可能會有更多圖片標(biāo)簽,所以我們馬上回到搜索循環(huán)中。以下是我們的輸出現(xiàn)在的樣子:
images/text-frame-link.pngimages/text-frame-unlink.pngimages/gimpoptions1.pngimages/gimpoptions3.pngimages/gimpoptions2.pngimages/fontpref3.pngimages/font-subst.pngimages/fontpref2.pngimages/fontpref1.pngimages/dtp-studio.png啊,干凈多了,而這只花費幾秒鐘的時間。 我本可以將索引前移 7 步來剪切
images/
部分,但我更愿意把這個部分保存下來,以確保我沒有剪切掉圖像文件名的***個字母,這很容易用 KWrite 編輯成功 —— 你甚至不需要正則表達式。 做完這些并保存文件后,下一步就是運行我編寫的另一個腳本sortlist.py
:#!/usr/bin/env python# -*- coding: utf-8 -*-# sortlist.py import os imagelist = []for line in open('/tmp/imagelist_parse4.txt').xreadlines(): imagelist.append(line) imagelist.sort() outfile = open('/tmp/imagelist_parse4_sorted.txt', 'w')outfile.writelines(imagelist)outfile.close()這會讀取文件內(nèi)容,并存儲為列表,對其排序,然后另存為另一個文件。 之后,我可以做到以下幾點:
ls /home/gregp/development/Scribus15x/doc/en/images/*.png > '/tmp/actual_images.txt'然后我需要在該文件上運行
sortlist.py
,因為ls
方法的排序與 Python 不同。 我原本可以在這些文件上運行比較腳本,但我更愿意以可視方式進行操作。 ***,我成功找到了 42 個圖像,這些圖像沒有來自文檔的 HTML 引用。這是我的完整解析腳本:
#!/usr/bin/env python# -*- coding: utf-8 -*-# parseimg4.py import os def imagefound(all_text, imagelist, index): end = 0 index += 2 newimage = '' while end == 0: if (all_text[index] != '"'): newimage = newimage + all_text[index] index += 1 else: newimage = newimage + '\n' imagelist.append(newimage) end = 1 return htmlnames = []imagelist = []tempstring = ''filenames = os.listdir('/home/gregp/development/Scribus15x/doc/en/')for name in filenames: if name.endswith('.html'): htmlnames.append(name)#print htmlnamesfor htmlfile in htmlnames: all_text = open('/home/gregp/development/Scribus15x/doc/en/' + htmlfile).read() linelength = len(all_text) index = 3 while index < linelength: if (all_text[index] == '='): if (all_text[index-3] == 's') and (all_text[index-2] == 'r') and(all_text[index-1] == 'c'): imagefound(all_text, imagelist, index) index += 1 else: index += 1 else: index += 1 outfile = open('/tmp/imagelist_parse4.txt', 'w')outfile.writelines(imagelist)outfile.close()imageno = len(imagelist)print str(imageno) + " images were found and saved"腳本名稱為
parseimg4.py
,這并不能真實反映我陸續(xù)編寫的腳本數(shù)量(包括微調(diào)的和大改的以及丟棄并重新開始寫的)。 請注意,我已經(jīng)對這些目錄和文件名進行了硬編碼,但是很容易變得通用化,讓用戶輸入這些信息。 同樣,因為它們是工作腳本,所以我將輸出發(fā)送到/tmp
目錄,所以一旦重新啟動系統(tǒng),它們就會消失。這不是故事的結(jié)尾,因為下一個問題是:僵尸 HTML 文件怎么辦? 任何未使用的文件都可能會引用圖像,不能被前面的方法所找出。 我們有一個
menu.xml
文件作為聯(lián)機手冊的目錄,但我還需要考慮 TOC(LCTT 譯注:TOC 是 table of contents 的縮寫)中列出的某些文件可能引用了不在 TOC 中的文件,是的,我確實找到了一些這樣的文件。以上就是Python中如何解析HTML,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
當(dāng)前標(biāo)題:Python中如何解析HTML
鏈接地址:http://weahome.cn/article/ppeces.html