抓取網頁內容

對搜索引擎、文件索引、文檔轉換、數據檢索、站點備份或遷移等應用程序來講,常常用到對網頁(即HTML文件)的解析處理。事實上,經過Python語言 提供的各類模塊,咱們無需藉助Web服務器或者Web瀏覽器就可以解析和處理HTML文檔。本文上篇中,咱們介紹了一個能夠幫助簡化打開位於本地和Web 上的HTML文檔的Python模塊。在本文中,咱們將論述如何使用Python模塊來迅速解析在HTML文件中的數據,從而處理特定的內容,如連接、圖 像和Cookie等。同時還會介紹如何規範HTML文件的格式標籤。

1、從HTML文檔中提取連接html

Python語言還有一個很是有用的模塊HTMLParser,該模塊使咱們可以根據HTML文檔中的標籤來簡潔、高效地解析HTML文檔。因此,在處理HTML文檔的時候,HTMLParser是最經常使用的模塊之一。python

import HTMLParser

import urllib

class parseLinks(HTMLParser.HTMLParser):

def handle_starttag(self, tag, attrs):

if tag == ' a ' :

for name,value in attrs:

if name == ' href ' :

print value

print self.get_starttag_text()

lParser
= parseLinks()

lParser.feed(urllib.urlopen(
" http://www.python.org/index.html " ).read())

處理HTML文檔的時候,咱們經常須要從其中提取出全部的連接。使用HTMLParser模塊後,這項任務將變得易如反掌。首先,咱們須要定義 一個新的HTMLParser類,以覆蓋handle_starttag()方法,咱們將使用這個方法來顯示全部標籤的HRef屬性值。瀏覽器

定義好新的HTMLParser類以後,須要建立一個實例來返回HTMLParser對象。而後,就可使用urllib.urlopen(url)打開HTML文檔並讀取該HTML文件的內容了。服務器

爲了解析HTML文件的內容並顯示包含其中的連接,可使用read()函數將數據傳遞給HTMLParser對象。HTMLParser對象 的feed函數將接收數據,並經過定義的HTMLParser對象對數據進行相應的解析。須要注意,若是傳給HTMLParser的feed()函數的數 據不完整的話,那麼不完整的標籤會保存下來,並在下一次調用feed()函數時進行解析。當HTML文件很大,須要分段發送給解析器的時候,這個功能就會 有用武之地了。下面是一個具體的例子cookie

import HTMLParser

import urllib

import sys

# 定義HTML解析器

class parseLinks(HTMLParser.HTMLParser):

def handle_starttag(self, tag, attrs):

if tag == ' a ' :

for name,value in attrs:

if name == ' href ' :

print value

print self.get_starttag_text()

# 建立HTML解析器的實例

lParser
= parseLinks()

# 打開HTML文件

lParser.feed(urllib.urlopen( \

" http://www.python.org/index.html " ).read())

lParser.close()app

2、從HTML文檔中提取圖像 dom

處理HTML文檔的時候,咱們經常須要從其中提取出全部的圖像。使用HTMLParser模塊後,這項任務將變得易如反掌。首先,咱們須要定義 一個新的HTMLParser類,以覆蓋handle_starttag()方法,該方法的做用是查找img標籤,並保存src屬性值所指的文件。函數

import HTMLParser

import urllib

def getImage(addr):

u
= urllib.urlopen(addr)

data
= u.read()

class parseImages(HTMLParser.HTMLParser):

def handle_starttag(self, tag, attrs):

if tag == ' img ' :

for name,value in attrs:

if name == ' src ' :

getImage(urlString
+ " / " + value)

u
= urllib.urlopen(urlString)

lParser.feed(u.read())

定義好新的HTMLParser類以後,須要建立一個實例來返回HTMLParser對象。而後,就可使用urllib.urlopen(url)打開HTML文檔並讀取該HTML文件的內容了。測試

爲了解析HTML文件的內容並顯示包含其中的圖像,可使用feed(data)函數將數據發送至HTMLParser對象。HTMLParser對象的feed函數將接收數據,並經過定義的HTMLParser對象對數據進行相應的解析。下面是一個具體的示例:網站

import HTMLParser

import urllib

import sys

urlString
= " http://www.python.org "

# 把圖像文件保存至硬盤

def getImage(addr):

u
= urllib.urlopen(addr)

data
= u.read()

splitPath
= addr.split( ' / ' )

fName
= splitPath.pop()

print " Saving %s " % fName

f
= open(fName, ' wb ' )

f.write(data)

f.close()

# 定義HTML解析器

class parseImages(HTMLParser.HTMLParser):

def handle_starttag(self, tag, attrs):

if tag == ' img ' :

for name,value in attrs:

if name == ' src ' :

getImage(urlString
+ " / " + value)

# 建立HTML解析器的實例

lParser
= parseImages()

# 打開HTML文件

u
= urllib.urlopen(urlString)

print " Opening URL\n==================== "

print u.info()

# 把HTML文件傳給解析器

lParser.feed(u.read())

lParser.close()

上述代碼的運行結果以下所示:

Opening URL

====================

Date: Fri,
26 Jun 2009 10 : 54 : 49 GMT

Server: Apache
/ 2.2 . 9 (Debian) DAV / 2 SVN / 1.5 . 1 mod_ssl / 2.2 . 9 OpenSSL / 0.9 .8g mod_wsgi / 2.3 Python / 2.5 . 2

Last
- Modified: Thu, 25 Jun 2009 0 9 : 44 : 54 GMT

ETag:
" 105800d-46e7-46d29136f7180 "

Accept
- Ranges: bytes

Content
- Length: 18151

Connection: close

Content
- Type: text / html

Saving python
- logo.gif

Saving trans.gif

Saving trans.gif

Saving afnic.fr.png


3、從HTML文檔中提取文本

處理HTML文檔的時候,咱們經常須要從其中提取出全部的文本。使用HTMLParser模塊後,這項任務將變得很是簡單了。首先,咱們須要定義一個新的HTMLParser類,以覆蓋handle_data()方法,該方法是用來解析並文本數據的。

import HTMLParser

import urllib

class parseText(HTMLParser.HTMLParser):

def handle_data(self, data):

if data != ' \n ' :

urlText.append(data)

lParser
= parseText()

lParser.feed(urllib.urlopen( \

http:
// docs.python.org / lib / module - HTMLParser.html).read())

定義好新的HTMLParser類以後,須要建立一個實例來返回HTMLParser對象。而後,就可使用urllib.urlopen(url)打開HTML文檔並讀取該HTML文件的內容了。

爲了解析HTML文件的內容並顯示包含其中的文本,咱們可使用feed(data)函數將數據傳遞給HTMLParser對象。 HTMLParser對象的feed函數將接收數據,並經過定義的HTMLParser對象對數據進行相應的解析。要注意的是,若是傳給 HTMLParser的feed()函數的數據不完整的話,那麼不完整的標籤會保存下來,並在下一次調用feed()函數時進行解析。當HTML文件很 大,須要分段發送給解析器的時候,這個功能就會有用武之地了。下面是一個具體的代碼示例:

import HTMLParser

import urllib

urlText
= []

# 定義HTML解析器

class parseText(HTMLParser.HTMLParser):

def handle_data(self, data):

if data != ' \n ' :

urlText.append(data)

# 建立HTML解析器的實例

lParser
= parseText()

# 把HTML文件傳給解析器

lParser.feed(urllib.urlopen( \

「http:
// docs.python.org / lib / module - HTMLParser.html」 \

).read())

lParser.close()

for item in urlText:

print item

4、從HTML文檔中提取Cookies

不少時候,咱們都須要處理Cookie,幸運的是Python語言的cookielib模塊爲咱們提供了許多自動處理在HTML中的HTTP Cookie的類。當處理要求爲客戶端設置Cookie的HTML文檔的時候,這些類對咱們很是有用。

import urllib2

import cookielib

from urllib2 import urlopen, Request

cJar
= cookielib.LWPCookieJar()

opener
= urllib2.build_opener( \

urllib2.HTTPCookieProcessor(cJar))

urllib2.install_opener(opener)

r
= Request(testURL)

h
= urlopen(r)

for ind, cookie in enumerate(cJar):

print " %d - %s " % (ind, cookie)

cJar.save(cookieFile)

爲了從HTML文檔提取cookies,首先得使用cookielib模塊的LWPCookieJar()函數建立一個cookie jar的實例。LWPCookieJar()函數將返回一個對象,該對象能夠從硬盤加載Cookie,同時還能向硬盤存放Cookie。

接下來,使用urllib2模塊的build_opener([handler, . . .])函數建立一個opener對象,當HTML文件打開時該對象將處理cookies。函數build_opener能夠接收零個或多個處理程序(這些 程序將按照它們被指定的順序鏈接在一塊兒)做爲參數並返回一個。

注意,若是想讓urlopen()使用opener對象來打開HTML文件的話,能夠調用install_opener(opener)函數,並將opener對象傳給它。不然,請使用opener對象的open(url)函數來打開HTML文件。

一旦已經建立並安裝了opener對象,就可使用urllib2模塊中的Request(url)函數來建立一個Request對象,而後就能使用urlopen(Request)函數來打開HTML文件了。

打開HTML頁面後,該頁面的全部Cookie將被存放到LWPCookieJar對象中,以後,您可使用LWPCookieJar對象的save(filename)函數了。

import os

import urllib2

import cookielib

from urllib2 import urlopen, Request

cookieFile
= " cookies.dat "

testURL
= ' http://maps.google.com/ '

# 爲cookie jar 建立實例

cJar
= cookielib.LWPCookieJar()

# 建立HTTPCookieProcessor的opener對象

opener
= urllib2.build_opener( \

urllib2.HTTPCookieProcessor(cJar))

# 安裝HTTPCookieProcessor的opener

urllib2.install_opener(opener)

# 建立一個Request對象

r
= Request(testURL)

# 打開HTML文件

h
= urlopen(r)

print " 頁面的頭部\n====================== "

print h.info()

print " 頁面的Cookies\n====================== "

for ind, cookie in enumerate(cJar):

print " %d - %s " % (ind, cookie)

# 保存cookies

cJar.save(cookieFile)

上述代碼的運行結果以下所示:

頁面的頭部

======================

Cache
- Control: private

Content
- Type: text / html; charset = ISO - 8859 - 1

Set
- Cookie: PREF = ID = 5d9692b55f029733:NW = 1 :TM = 1246015608 :LM = 1246015608 :S = frfx -- b3xt73TaEA; expires = Sun, 26 - Jun - 2011 11 : 26 : 48 GMT; path =/ ; domain = .google.com

Date: Fri,
26 Jun 2009 11 : 26 : 48 GMT

Server: mfe

Expires: Fri,
26 Jun 2009 11 : 26 : 48 GMT

Transfer
- Encoding: chunked

Connection: close

頁面的Cookies


5、爲HTML文檔中的屬性值添加引號

前面咱們討論了若是根據HTML解析器中的某種處理程序來解析HTML文件,但是有時候咱們卻須要使用全部的處理程序來處理HTML文檔。值得慶幸的是,使用HTMLParser模塊解析HTML文件的全部要素並不比處理連接或者圖像難多少。

import HTMLParser

import urllib

class parseAttrs(HTMLParser.HTMLParser):

def handle_starttag(self, tag, attrs):

. . .

attrParser
= parseAttrs()

attrParser.init_parser()

attrParser.feed(urllib.urlopen(
" test2.html " ).read())

這裏,咱們將討論如何使用HTMLParser模塊來解析HTML文件,從而爲「裸奔」的屬性值加上引號。首先,咱們要定義一個新的HTMLParser類,以覆蓋下面全部的處理程序來爲屬性值添加引號。

handle_starttag(tag, attrs)

handle_charref(name)

handle_endtag(tag)

handle_entityref(ref)

handle_data(text)

handle_comment(text)

handle_pi(text)

handle_decl(text)

handle_startendtag(tag, attrs)

咱們還須要在parser類中定義一個函數來初始化用於存儲解析好的數據的變量,同時還要定義另一個函數來返回解析好的數據。

定義好新的HTMLParser類以後,須要建立一個實例來返回HTMLParser對象。使用咱們建立的init函數初始化該解析器,這樣,咱們就可使用urllib.urlopen(url)打開HTML文檔並讀取該HTML文件的內容了。

爲了解析HTML文件的內容並給屬性值添加引號,可使用feed(data)函數將數據傳遞給HTMLParser對象。HTMLParser對象的feed函數將接收數據,並經過定義的HTMLParser對象對數據進行相應的解析。下面是一個具體的示例代碼:

import HTMLParser

import urllib

import sys

# 定義HTML解析器

class parseAttrs(HTMLParser.HTMLParser):

def init_parser (self):

self.pieces
= []

def handle_starttag(self, tag, attrs):

fixedAttrs
= ""

# for name,value in attrs:

for name, value in attrs:

fixedAttrs
+= " %s=\"%s\" " % (name, value)

self.pieces.append(
" <%s %s> " % (tag, fixedAttrs))

def handle_charref(self, name):

self.pieces.append(
" &#%s; " % (name))

def handle_endtag(self, tag):

self.pieces.append(
"" % (tag))

def handle_entityref(self, ref):

self.pieces.append(
" &%s " % (ref))

def handle_data(self, text):

self.pieces.append(text)

def handle_comment(self, text):

self.pieces.append(
"" % (text))

def handle_pi(self, text):

self.pieces.append(
"" % (text))

def handle_decl(self, text):

self.pieces.append(
"" % (text))

def parsed (self):

return "" .join(self.pieces)

# 建立HTML解析器的實例

attrParser
= parseAttrs()

# 初始化解析器數據

attrParser.init_parser()

# 把HTML文件傳給解析器

attrParser.feed(urllib.urlopen(
" test2.html " ).read())

# 顯示原來的文件內容

print " 原來的文件\n======================== "

print open( " test2.html " ).read()

# 顯示解析後的文件

print " 解析後的文件\n======================== "

print attrParser.parsed()

attrParser.close()

咱們還須要創建一個測試文件,名爲test2.html,該文件內容能夠從上述代碼的運行結果看到,具體以下所示:

原來的文件
========================
< html >
< head >
< meta content = " text/html; charset=utf-8 "
http
- equiv = " content-type " />
< title > Web頁面 </ title >
</ head >
< body >
< H1 > Web頁面清單 </ H1 >
< a href = http: // www.python.org > Python網站 </ a >
< a href = test.html > 本地頁面 </ a >
< img SRC = test.jpg >
</ body >
</ html >

解析後的文件
========================
< html >
< head >
< meta content = " text/html; charset=utf-8 "
http
- equiv = " content-type " ></ meta >
< title > Web頁面 </ title >
</ head >
< body >
< h1 > Web頁面清單 </ h1 >
< a href = " http://www.python.org " > Python網站 </ a >
< a href = " test.html " > 本地頁面 </ a >
< img src = " test.jpg " >
</ body >
</ html >
相關文章
相關標籤/搜索