python解析html的库_用python解析html
python中,有三個庫可以解析html文本,HTMLParser,sgmllib,htmllib。他們的實現方法不通,但功能差不多。這三個庫中 提供解析html的類都是基類,本身并不做具體的工作。他們在發現的元件后(如標簽、注釋、聲名等),會調用相應的函數,這些函數必須重載,因為基類中不 作處理。
比如:
"""
AdviceThe IETF admonishes:
Be strict in what you send.
"""
如果對這個數據做處理,當檢測到標簽時,對于HTMLParser,會調用handle_starttag函數。
下面具體介紹下幾個庫
1、HTMLParser
#------------------?HTMLParser_stack.py?------------------#
#--?coding:?GBK?--
import?HTMLParser,sys,os,string
html?=?"""
AdviceThe?IETF?admonishes:
Be?strict?in?what?you?send.
"""
tagstack?=?[]
class?ShowStructure(HTMLParser.HTMLParser):
def?handle_starttag(self,?tag,?attrs):?tagstack.append(tag)
def?handle_endtag(self,?tag):?tagstack.pop()
def?handle_data(self,?data):
if?data.strip():
for?tag?in?tagstack:?sys.stdout.write('/'+tag)
sys.stdout.write('?>>?%s/n'?%?data[:40].strip())
ShowStructure().feed(html)
此函數的輸出:
/html/body/p >> The
/html/body/p/a >> IETF admonishes:
/html/body/p/a/i >> Be strict in what you
/html/body/p/a/i/b >> send
/html/body/p/a/i >> .
對于一些網頁,可能并沒有嚴格的開始結束標簽對,這時,我們可以去忽略一些標簽。可以自己寫個堆棧來處理這些標簽。
#*---------------?TagStack?class?example?-----------------#
class?TagStack:
def?__init__(self,?lst=[]):?self.lst?=?lst
def?__getitem__(self,?pos):?return?self.lst[pos]
def?append(self,?tag):
#?Remove?every?paragraph-level?tag?if?this?is?one
if?tag.lower()?in?('p','blockquote'):
self.lst?=?[t?for?t?in?self.lst
if?t?not?in?('p','blockquote')]
self.lst.append(tag)
def?pop(self,?tag):
#?"Pop"?by?tag?from?nearest?pos,?not?only?last?item
self.lst.reverse()
try:
pos?=?self.lst.index(tag)
except?ValueError:
raise?HTMLParser.HTMLParseError,?"Tag?not?on?stack"
del?self.lst[pos]
self.lst.reverse()
tagstack?=?TagStack()
HTMLParser有個bug,就是不能處理中文屬性,比如說,如果網頁里有這么一段:
那么解析到這一行時就會出錯。
錯誤原因還是正則表達式惹的禍。
attrfind = re.compile(
r'/s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(/s*=/s*'
r'(/'[^/']*/'|"[^"]*"|[-a-zA-Z0-9./,:;+*%?!&$/(/)_#=~@]*))?')
attrfind 沒有匹配中文字符。
可以更改這個匹配已修正這個錯誤。sgmllib則不存在這種錯誤。
2、sgmllib
html格式為sgml格式的一個子集,所以sgml可以處理跟多的東西,下面通過一段代碼來示例sgmllib的用法。
#------------------?HTMLParser_stack.py?------------------#
#--?coding:?GBK?--
import?sgmllib,sys,os,string
html?=?"""Advice
The?IETF?admonishes:
Be?strict?in?what?you?send.
?我?
"""
os.chdir('d://python')
f=file('testboard.txt','r')
contest=f.read()
tagstack?=?[]
class?ShowStructure(sgmllib.SGMLParser):
def?handle_starttag(self,?tag,?method,attrs):?tagstack.append(tag)
def?handle_endtag(self,?tag):?tagstack.pop()
def?handle_data(self,?data):
if?data.strip():
for?tag?in?tagstack:?sys.stdout.write('/'+tag)
sys.stdout.write('?>>?%s/n'?%?data[:40].strip())
def?unknown_starttag(self,tag,attrs):
print?'start?tag:'
def?unknown_endtag(self,tag):
print?'end?tag:'+tag+'>'
def?start_lala(self,attr):
print?'lala?tag?found'
ShowStructure().feed(html)
輸出:
start tag:
start tag:
/lala >> Advice
end tag:
end tag:
start tag:
start tag:
/lala >> The
start tag:
/lala >> IETF admonishes:
start tag:
/lala >> Be strict in what you
start tag:
/lala >> send
end tag:
/lala >> .
end tag:
end tag:
end tag:
start tag:
start tag:
/lala >> ?
start tag:
end tag:
end tag:
end tag:
和HTMLParser一樣,如果要用sgmllib解析html,則要繼承sgmllib.SGMLParser類,此類里的函數都是空的,用戶需要重載它。這個類提供的功能是在特定情況下調用相應的函數。
比如當發現標簽時,如果并沒有定義 start_html(self,attr)函數,則會調用unknown_starttag函數,具體怎么處理則更具用戶。
sgml的標簽是可以自定義的,比如自己定義了一個start_lala函數,則就會處理標簽。
有
個地方要說明下,如果定義了start_tagname函數,有定義了handle_starttag函數,則函數只會運行
handle_starttag函數,start_tagname為空函數都沒有問題,如果沒有定義handle_starttag函數,則遇
到標簽時,會運行start_tagname函數。如果沒有定義tagname的start函數,則此標簽為未知標簽,調
用unknown_starttag函數
總結
以上是生活随笔為你收集整理的python解析html的库_用python解析html的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式(四)结构型模式
- 下一篇: python列表添加数字_Python-