首頁 後端開發 Python教學 python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)

python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)

Jun 06, 2016 am 11:31 AM
html python xhtml 解析

一、利用HTMLParser进行网页解析
具体HTMLParser官方文档可参考http://docs.python.org/library/htmlparser.html#HTMLParser.HTMLParser

1、从一个简单的解析例子开始
例1:
test1.html文件内容如下:

代码如下:




XHTML 与 HTML 4.01 标准没有太多的不同


i love you


下面是能够列出title和body的程序示例:

代码如下:


##@小五义:
##HTMLParser示例
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:

代码如下:




XHTML 与" HTML 4.01 "标准没有太多的不同


i love you×


利用上面的例子进行分析,其结果是:
title: XHTML 与 HTML 4.01 标准没有太多的不同
body:
i love you
实体完全消失了。这是因为当出现实体的时候,HTMLParser调用了handle_entityref()方法,因为代码中没有定义这个方法,所以就什么都没有做。经过修改后,如下:

代码如下:


##@小五义:
##HTMLParser示例:解决实体问题
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:

代码如下:




XHTML 与" HTML 4.01 "标准没有太多的不同


i love÷ you×


如果利用例2的代码执行后结果为:

title: XHTML 与" HTML 4.01 "标准没有太多的不同
body:
i love you×
结果中÷ 对应的÷没有显示出来。
添加handle_charref()进行处理,具体代码如下:

代码如下:


##@小五义:
##HTMLParser示例:解决实体问题
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 charnum255:
            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:

代码如下:




XHTML 与" HTML 4.01 "标准没有太多的不同

i love÷ you×


这里在handle_starttag(self,tag,attrs)中,tag=a时,attrs记录了属性值,因此只需要将attrs中name=href的value提出即可。具体如下:

代码如下:


##@小五义:
##HTMLParser示例:提取链接
# -*- 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 charnum255:
            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:

代码如下:




XHTML 与" HTML 4.01 "标准没有太多的不同


i love÷ you×
我想你
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)



将baidu_sylogo1.gif存取出来,具体代码如下:

代码如下:


##@小五义:
##HTMLParser示例:提取图片
# -*- 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 charnum255:
            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
baidu_sylogo1.gif已经生成!
body:
i love÷ you×
?ò????

5、实际例子:
例6、获取人人网首页上的各各链接地址,代码如下:

代码如下:


##@小五义:
##HTMLParser示例:获取人人网首页上的各各链接地址
#coding: utf-8
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 charnum255:
            return
        self.handle_data(chr(charnum))

    def gettitle(self):
        return self.linkaddr
tp=TitleParser()
tp.feed(urllib.urlopen('http://www.renren.com/').read())

运行结果:
分享:http://share.renren.com
应用程序:http://app.renren.com
公共主页:http://page.renren.com
人人生活:http://life.renren.com
人人小组:http://xiaozu.renren.com/
同名同姓:http://name.renren.com
人人中学:http://school.renren.com/allpages.html
大学百科:http://school.renren.com/daxue/
人人热点:http://life.renren.com/hot
人人小站:http://zhan.renren.com/
人人逛街:http://j.renren.com/
人人校招:http://xiaozhao.renren.com/
:http://www.renren.com
注册:http://wwv.renren.com/xn.do?ss=10113&rt=27
登录:http://www.renren.com/
帮助:http://support.renren.com/helpcenter
给我们提建议:http://support.renren.com/link/suggest
更多:#
:javascript:closeError();
打开邮箱查收确认信:#
重新输入:javascript:closeError();
:javascript:closeStop();
客服:http://help.renren.com/#http://help.renren.com/support/contomvice?pid=2&selection={couId:193,proId:342,cityId:1000375}
:javascript:closeLock();
立即解锁:http://safe.renren.com/relive.do
忘记密码?:http://safe.renren.com/findPass.do
忘记密码?:http://safe.renren.com/findPass.do
换一张:javascript:refreshCode_login();
MSN:#
360:https://openapi.360.cn/oauth2/authorize?client_id=5ddda4458747126a583c5d58716bab4c&response_type=code&redirect_uri=http://www.renren.com/bind/tsz/tszLoginCallBack&scope=basic&display=default
天翼:https://oauth.api.189.cn/emp/oauth2/authorize?app_id=296961050000000294&response_type=code&redirect_uri=http://www.renren.com/bind/ty/tyLoginCallBack
为什么要填写我的生日?:#birthday
看不清换一张?:javascript:refreshCode();
想了解更多人人网功能?点击此处:javascript:;
:javascript:;
:javascript:;
立刻注册:http://reg.renren.com/xn6245.do?ss=10113&rt=27
关于:http://www.renren.com/siteinfo/about
开放平台:http://dev.renren.com
人人游戏:http://wan.renren.com
公共主页:http://page.renren.com/register/regGuide/
手机人人:http://mobile.renren.com/mobilelink.do?psf=40002
团购:http://www.nuomi.com
皆喜网:http://www.jiexi.com
营销服务:http://ads.renren.com
招聘:http://job.renren-inc.com/
客服帮助:http://support.renren.com/helpcenter
隐私:http://www.renren.com/siteinfo/privacy
京ICP证090254号:http://www.miibeian.gov.cn/
互联网药品信息服务资格证:http://a.xnimg.cn/n/core/res/certificate.jpg

二、利用BeautifulSoup进行网页解析
1、BeautifulSoup下载和安装
下载地址:http://www.crummy.com/software/BeautifulSoup/download/3.x/
中文文档地址:http://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html#Entity%20Conversion
安装方法:将下载的文件解压缩后,文件夹下有个setup.py文件,然后在cmd下,运行python setup.py install进行安装,注意setup.py的路径问题。安装成功后,在python中就可以直接import BeautifulSoup了。
2、从一个简单的解析例子开始
例7:

代码如下:




XHTML 与" HTML 4.01 "标准没有太多的不同


i love÷ you×
我想你
python网络编程学习笔记(七):HTML和XHTML解析(HTMLParser、BeautifulSoup)



获取title的代码:

代码如下:


##@小五义:
##BeautifulSoup示例:title
#coding: utf8
import BeautifulSoup

a=open('test1.html','r')
htmlline=a.read()
soup=BeautifulSoup.BeautifulSoup(htmlline.decode('gb2312'))
#print soup.prettify()#规范化html文件
titleTag=soup.html.head.title
print titleTag.string


运行结果:
XHTML 与" HTML 4.01 "标准没有太多的不同
从代码和结果来看,应注意两点:
第一,在BeautifulSoup.BeautifulSoup(htmlline.decode('gb2312'))初始化过程中,应注意字符编码格式,从网上搜索了一下,开始用utf-8的编码显示不正常,换为gb2312后显示正常。其实可以用soup.originalEncoding方法来查看原文件的编码格式。
第二,结果中未对字符实体进行处理,在BeautifulSoup中文文档中,有专门对实体转换的解释,这里将上面的代码改为以下代码后,结果将正常显示:

代码如下:


##@小五义:
##BeautifulSoup示例:title
#coding: utf8
import BeautifulSoup
a=open('test1.html','r')
htmlline=a.read()
soup=BeautifulSoup.BeautifulStoneSoup(htmlline.decode('gb2312'),convertEntities=BeautifulSoup.BeautifulStoneSoup.ALL_ENTITIES)
#print soup.prettify()#规范化html文件
titleTag=soup.html.head.title
print titleTag.string

这里convertEntities=BeautifulSoup.BeautifulStoneSoup.ALL_ENTITIES中的ALL_ENTITIES定义了XML和HTML两者的实体代码。当然,也可以直接用XML_ENTITIES或者HTML_ENTITIES。运行结果如下:
XHTML 与" HTML 4.01 "标准没有太多的不同
3、提取链接
还有用上面的例子,这里代码变为:

代码如下:


##@小五义:
##BeautifulSoup示例:提取链接
#coding: utf8
import BeautifulSoup
a=open('test1.html','r')
htmlline=a.read()
a.close()
soup=BeautifulSoup.BeautifulStoneSoup(htmlline.decode('gb2312'),convertEntities=BeautifulSoup.BeautifulStoneSoup.ALL_ENTITIES)
name=soup.find('a').string
links=soup.find('a')['href']
print name+':'+links

运行结果为:
我想你:http://pypi.python.org/pypi
4、提取图片
依然是用上面的例子,把baidu图片提取出来。
代码为:

代码如下:


##@小五义:http://www.cnblogs.com/xiaowuyi
#coding: utf8
import BeautifulSoup,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+' finished!'
a=open('test1.html','r')
htmlline=a.read()
soup=BeautifulSoup.BeautifulStoneSoup(htmlline.decode('gb2312'),convertEntities=BeautifulSoup.BeautifulStoneSoup.ALL_ENTITIES)
links=soup.find('img')['src']
getimage(links)

提取链接和提取图片两部分主要都是用了find方法,具体方法为:
find(name, attrs, recursive, text, **kwargs)
findAll是列出全部符合条件的,find只列出第一条。这里注意的是findAll返回的是个list。
5、实际例子:
例8、获取人人网首页上的各各链接地址,代码如下:

代码如下:


##@小五义:
##BeautifulSoup示例:获取人人网首页上的各各链接地址
#coding: utf8
import BeautifulSoup,urllib
linkname=''
htmlline=urllib.urlopen('http://www.renren.com/').read()
soup=BeautifulSoup.BeautifulStoneSoup(htmlline.decode('utf-8'))
links=soup.findAll('a')
for i in links:
    ##判断tag是a的里面,href是否存在。
    if 'href' in str(i):
        linkname=i.string
        linkaddr=i['href']
        if 'NoneType' in str(type(linkname)):#当i无内容是linkname为Nonetype类型。
            print linkaddr
        else:
            print linkname+':'+linkaddr

运行结果:
分享:http://share.renren.com
应用程序:http://app.renren.com
公共主页:http://page.renren.com
人人生活:http://life.renren.com
人人小组:http://xiaozu.renren.com/
同名同姓:http://name.renren.com
人人中学:http://school.renren.com/allpages.html
大学百科:http://school.renren.com/daxue/
人人热点:http://life.renren.com/hot
人人小站:http://zhan.renren.com/
人人逛街:http://j.renren.com/
人人校招:http://xiaozhao.renren.com/
http://www.renren.com
注册:http://wwv.renren.com/xn.do?ss=10113&rt=27
登录:http://www.renren.com/
帮助:http://support.renren.com/helpcenter
给我们提建议:http://support.renren.com/link/suggest
更多:#
javascript:closeError();
打开邮箱查收确认信:#
重新输入:javascript:closeError();
javascript:closeStop();
客服:http://help.renren.com/#http://help.renren.com/support/contomvice?pid=2&selection={couId:193,proId:342,cityId:1000375}
javascript:closeLock();
立即解锁:http://safe.renren.com/relive.do
忘记密码?:http://safe.renren.com/findPass.do
忘记密码?:http://safe.renren.com/findPass.do
换一张:javascript:refreshCode_login();
MSN:#
360:https://openapi.360.cn/oauth2/authorize?client_id=5ddda4458747126a583c5d58716bab4c&response_type=code&redirect_uri=http://www.renren.com/bind/tsz/tszLoginCallBack&scope=basic&display=default
天翼:https://oauth.api.189.cn/emp/oauth2/authorize?app_id=296961050000000294&response_type=code&redirect_uri=http://www.renren.com/bind/ty/tyLoginCallBack
#birthday
看不清换一张?:javascript:refreshCode();
javascript:;
javascript:;
立刻注册:http://reg.renren.com/xn6245.do?ss=10113&rt=27
关于:http://www.renren.com/siteinfo/about
开放平台:http://dev.renren.com
人人游戏:http://wan.renren.com
公共主页:http://page.renren.com/register/regGuide/
手机人人:http://mobile.renren.com/mobilelink.do?psf=40002
团购:http://www.nuomi.com
皆喜网:http://www.jiexi.com
营销服务:http://ads.renren.com
招聘:http://job.renren-inc.com/
客服帮助:http://support.renren.com/helpcenter
隐私:http://www.renren.com/siteinfo/privacy
京ICP证090254号:http://www.miibeian.gov.cn/
互联网药品信息服务资格证:http://a.xnimg.cn/n/core/res/certificate.jpg

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

HTML:結構,CSS:樣式,JavaScript:行為 HTML:結構,CSS:樣式,JavaScript:行為 Apr 18, 2025 am 12:09 AM

HTML、CSS和JavaScript在Web開發中的作用分別是:1.HTML定義網頁結構,2.CSS控製網頁樣式,3.JavaScript添加動態行為。它們共同構建了現代網站的框架、美觀和交互性。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

HTML的未來:網絡設計的發展和趨勢 HTML的未來:網絡設計的發展和趨勢 Apr 17, 2025 am 12:12 AM

HTML的未來充滿了無限可能。 1)新功能和標準將包括更多的語義化標籤和WebComponents的普及。 2)網頁設計趨勢將繼續向響應式和無障礙設計發展。 3)性能優化將通過響應式圖片加載和延遲加載技術提升用戶體驗。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

visual studio code 可以用於 python 嗎 visual studio code 可以用於 python 嗎 Apr 15, 2025 pm 08:18 PM

VS Code 可用於編寫 Python,並提供許多功能,使其成為開發 Python 應用程序的理想工具。它允許用戶:安裝 Python 擴展,以獲得代碼補全、語法高亮和調試等功能。使用調試器逐步跟踪代碼,查找和修復錯誤。集成 Git,進行版本控制。使用代碼格式化工具,保持代碼一致性。使用 Linting 工具,提前發現潛在問題。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

See all articles