python網路編程學習筆記(7):HTML和XHTML解析
轉載請註明:@小五義
小五義 - 博客園在python中能夠進行html和xhtml的庫有很多,如HTMLParser、sgmllib、htmllib、BeautifulSoup、mxTidy、uTidylib等,這裡介紹一下HTMLParser、BeautifulSoup等模塊。
一、利用HTMLParser進行網頁解析
具體HTMLParser官方文檔可參考http://docs.python.org/library/htmlparser.html#HTMLParser.HTMLParser1、從一個簡單的解析例子開始
例1:
test1.html文件內容如下:<html>
<head>
<title> XHTML 與 HTML 4.01 標準沒有太多的不同</title>
</head>
<body>
i love you
</body>
</html>
下面是能夠列出title和body的程序示例:
import HTMLParser
class TitleParser(HTMLParser.HTMLParser):
def __init__(self):
self.taglevels=[]
self.handledtags=[title,body] #提出標籤
self.processing=None
HTMLParser.HTMLParser.__init__(self)
def handle_starttag(self,tag,attrs):
if tag in self.handledtags:
self.data=
self.processing=tag
def handle_data(self,data):
if self.processing:
self.data +=data
def handle_endtag(self,tag):
if tag==self.processing:
print str(tag)+:+str(tp.gettitle())
self.processing=None
def gettitle(self):
return self.data
fd=open(test1.html)
tp=TitleParser()
tp.feed(fd.read())
運行結果如下:
title: XHTML 與 HTML 4.01 標準沒有太多的不同 body: i love you 程序定義了一個TitleParser類,它是HTMLParser類的子孫。HTMLParser的feed方法將接收數據,並通過定義的HTMLParser對象對數據進行相應的解析。其中handle_starttag、handle_endtag判斷起始和終止tag,handle_data檢查是否取得數據,如果self.processing不為None,那麼就取得數據。2、解決html實體問題
(HTML 中有用的字元實體)(1)實體名稱
當與到HTML中的實體問題時,上面的例子就無法實現,如這裡將test1.html的代碼改為: 例2:<html>
<head>
<title> XHTML 與" HTML 4.01 "標準沒有太多的不同</title>
</head>
<body>
i love you×
</body>
</html>
利用上面的例子進行分析,其結果是:
title: XHTML 與 HTML 4.01 標準沒有太多的不同
body:
i love you
實體完全消失了。這是因為當出現實體的時候,HTMLParser調用了handle_entityref()方法,因為代碼中沒有定義這個方法,所以就什麼都沒有做。經過修改後,如下:
from htmlentitydefs import entitydefs
import HTMLParser
class TitleParser(HTMLParser.HTMLParser):
def __init__(self):
self.taglevels=[]
self.handledtags=[title,body]
self.processing=None
HTMLParser.HTMLParser.__init__(self)
def handle_starttag(self,tag,attrs):
if tag in self.handledtags:
self.data=
self.processing=tag
def handle_data(self,data):
if self.processing:
self.data +=data
def handle_endtag(self,tag):
if tag==self.processing:
print str(tag)+:+str(tp.gettitle())
self.processing=None
def handle_entityref(self,name):
if entitydefs.has_key(name):
self.handle_data(entitydefs[name])
else:
self.handle_data(&+name+;)
def gettitle(self):
return self.data
fd=open(test1.html)
tp=TitleParser()
tp.feed(fd.read())
運行結果為:
title: XHTML 與" HTML 4.01 "標準沒有太多的不同body:
i love you× 這裡就把所有的實體顯示出來了。(2)實體編碼
例3:<html>
<head>
<title> XHTML 與" HTML 4.01 "標準沒有太多的不同</title>
</head>
<body>
i love÷ you×
</body>
</html>
如果利用例2的代碼執行後結果為:
title: XHTML 與" HTML 4.01 "標準沒有太多的不同
body:
i love you×
結果中÷ 對應的÷沒有顯示出來。
添加handle_charref()進行處理,具體代碼如下:
from htmlentitydefs import entitydefs
import HTMLParser
class TitleParser(HTMLParser.HTMLParser):
def __init__(self):
self.taglevels=[]
self.handledtags=[title,body]
self.processing=None
HTMLParser.HTMLParser.__init__(self)
def handle_starttag(self,tag,attrs):
if tag in self.handledtags:
self.data=
self.processing=tag
def handle_data(self,data):
if self.processing:
self.data +=data
def handle_endtag(self,tag):
if tag==self.processing:
print str(tag)+:+str(tp.gettitle())
self.processing=None
def handle_entityref(self,name):
if entitydefs.has_key(name):
self.handle_data(entitydefs[name])
else:
self.handle_data(&+name+;)
def handle_charref(self,name):
try:
charnum=int(name)
except ValueError:
return
if charnum<1 or charnum>255:
return
self.handle_data(chr(charnum))
def gettitle(self):
return self.data
fd=open(test1.html)
tp=TitleParser()
tp.feed(fd.read())
運行結果為:
title: XHTML 與" HTML 4.01 "標準沒有太多的不同 body: i love÷ you×3、提取鏈接
例4:<html>
<head>
<title> XHTML 與" HTML 4.01 "標準沒有太多的不同</title>
</head>
<body>
<a href="http://pypi.python.org/pypi" title="link1">i love÷ you×</a>
</body>
</html>
這裡在handle_starttag(self,tag,attrs)中,tag=a時,attrs記錄了屬性值,因此只需要將attrs中name=href的value提出即可。具體如下:
# -*- coding: cp936 -*-
from htmlentitydefs import entitydefs
import HTMLParser
class TitleParser(HTMLParser.HTMLParser):
def __init__(self):
self.taglevels=[]
self.handledtags=[title,body]
self.processing=None
HTMLParser.HTMLParser.__init__(self)
def handle_starttag(self,tag,attrs):
if tag in self.handledtags:
self.data=
self.processing=tag
if tag ==a:
for name,value in attrs:
if name==href:
print 連接地址:+value
def handle_data(self,data):
if self.processing:
self.data +=data
def handle_endtag(self,tag):
if tag==self.processing:
print str(tag)+:+str(tp.gettitle())
self.processing=None
def handle_entityref(self,name):
if entitydefs.has_key(name):
self.handle_data(entitydefs[name])
else:
self.handle_data(&+name+;)
def handle_charref(self,name):
try:
charnum=int(name)
except ValueError:
return
if charnum<1 or charnum>255:
return
self.handle_data(chr(charnum))
def gettitle(self):
return self.data
fd=open(test1.html)
tp=TitleParser()
tp.feed(fd.read())
運行結果為:
title: XHTML 與" HTML 4.01 "標準沒有太多的不同連接地址:http://pypi.python.org/pypi
body:i love÷ you×
4、提取圖片
如果網頁中有一個圖片文件,將其提取出來,並存為一個單獨的文件。 例5:<html>
<head>
<title> XHTML 與" HTML 4.01 "標準沒有太多的不同</title>
</head>
<body>
i love÷ you×
<a href="http://pypi.python.org/pypi" title="link1">我想你</a>
<div id="m"><img src="http://www.baidu.com/img/baidu_sylogo1.gif" width_="270" height="129" ></div>
</body>
</html>
將baidu_sylogo1.gif存取出來,具體代碼如下:
# -*- coding: cp936 -*-
from htmlentitydefs import entitydefs
import HTMLParser,urllib
def getimage(addr):#提取圖片並存在當前目錄下
u = urllib.urlopen(addr)
data = u.read()
filename=addr.split(/)[-1]
f=open(filename,wb)
f.write(data)
f.close()
print filename+已經生成!
class TitleParser(HTMLParser.HTMLParser):
def __init__(self):
self.taglevels=[]
self.handledtags=[title,body]
self.processing=None
HTMLParser.HTMLParser.__init__(self)
def handle_starttag(self,tag,attrs):
if tag in self.handledtags:
self.data=
self.processing=tag
if tag ==a:
for name,value in attrs:
if name==href:
print 連接地址:+value
if tag==img:
for name,value in attrs:
if name==src:
getimage(value)
def handle_data(self,data):
if self.processing:
self.data +=data
def handle_endtag(self,tag):
if tag==self.processing:
print str(tag)+:+str(tp.gettitle())
self.processing=None
def handle_entityref(self,name):
if entitydefs.has_key(name):
self.handle_data(entitydefs[name])
else:
self.handle_data(&+name+;)
def handle_charref(self,name):
try:
charnum=int(name)
except ValueError:
return
if charnum<1 or charnum>255:
return
self.handle_data(chr(charnum))
def gettitle(self):
return self.data
fd=open(test1.html)
tp=TitleParser()
tp.feed(fd.read())
運動結果為:
title: XHTML 與" HTML 4.01 "標準沒有太多的不同 連接地址:http://pypi.python.org/pypibaidu_sylogo1.gif已經生成!
body: i love÷ you× ?ò????5、實際例子:
例6、獲取人人網首頁上的各各鏈接地址,代碼如下:from htmlentitydefs import entitydefs
import HTMLParser,urllib
def getimage(addr):
u = urllib.urlopen(addr)
data = u.read()
filename=addr.split(/)[-1]
f=open(filename,wb)
f.write(data)
f.close()
print filename+已經生成!
class TitleParser(HTMLParser.HTMLParser):
def __init__(self):
self.taglevels=[]
self.handledtags=[a]
self.processing=None
self.linkstring=
self.linkaddr=
HTMLParser.HTMLParser.__init__(self)
def handle_starttag(self,tag,attrs):
if tag in self.handledtags:
for name,value in attrs:
if name==href:
self.linkaddr=value
self.processing=tag
def handle_data(self,data):
if self.processing:
self.linkstring +=data
#print data.decode(utf-8)+:+self.linkaddr
def handle_endtag(self,tag):
if tag==self.processing:
print self.linkstring.decode(utf-8)+:+self.linkaddr
self.processing=None
self.linkstring=
def handle_entityref(self,name):
if entitydefs.has_key(name):
self.handle_data(entitydefs[name])
else:
self.handle_data(&+name+;)
def handle_charref(self,name):
try:
charnum=int(name)
except ValueError:
return
if charnum<1 or charnum>255:
return
self.handle_data(chr(charnum))
def gettitle(self):
return self.linkaddr
tp=TitleParser()
tp.feed(urllib.urlopen(http://www.renren.com/).read())
推薦閱讀: