轉載請註明:@小五義

小五義 - 博客園?

www.cnblogs.com

在python中能夠進行html和xhtml的庫有很多,如HTMLParser、sgmllib、htmllib、BeautifulSoup、mxTidy、uTidylib等,這裡介紹一下HTMLParser、BeautifulSoup等模塊。

一、利用HTMLParser進行網頁解析

具體HTMLParser官方文檔可參考docs.python.org/library

1、從一個簡單的解析例子開始

例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 與&quot; HTML 4.01 &quot;標準沒有太多的不同</title>
</head>
<body>
i love you&times;
</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 與&quot; HTML 4.01 &quot;標準沒有太多的不同</title>
</head>
<body>
i love&#247; you&times;
</body>
</html>

如果利用例2的代碼執行後結果為:

title: XHTML 與" HTML 4.01 "標準沒有太多的不同

body:

i love you×

結果中&#247; 對應的÷沒有顯示出來。

添加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 與&quot; HTML 4.01 &quot;標準沒有太多的不同</title>
</head>
<body>

<a href="http://pypi.python.org/pypi" title="link1">i love&#247; you&times;</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 "標準沒有太多的不同

連接地址:pypi.python.org/pypi

body:

i love÷ you×

4、提取圖片

如果網頁中有一個圖片文件,將其提取出來,並存為一個單獨的文件。 例5:

<html>
<head>
<title> XHTML 與&quot; HTML 4.01 &quot;標準沒有太多的不同</title>
</head>
<body>
i love&#247; you&times;
<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 "標準沒有太多的不同 連接地址:pypi.python.org/pypi

baidu_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())

推薦閱讀:

相关文章