Python网页解析利器BeautifulSoup安装使用介绍


Posted in Python onMarch 17, 2015

python解析网页,无出BeautifulSoup左右,此是序言

安装

BeautifulSoup4以后的安装需要用eazy_install,如果不需要最新的功能,安装版本3就够了,千万别以为老版本就怎么怎么不好,想当初也是千万人在用的啊。安装很简单

$ wget "http://www.crummy.com/software/BeautifulSoup/download/3.x/BeautifulSoup-3.2.1.tar.gz"  

$ tar zxvf BeautifulSoup-3.2.1.tar.gz 

然后把里面的BeautifulSoup.py这个文件放到你python安装目录下的site-packages目录下

site-packages是存放Python第三方包的地方,至于这个目录在什么地方呢,每个系统不一样,可以用下面的方式找一下,基本上都能找到

$ sudo find / -name "site-packages" -maxdepth 5 -type d  

$ find ~ -name "site-packages" -maxdepth 5 

当然如果没有root权限就查找当前用户的根目录
$ find ~ -name "site-packages" -maxdepth 5 -type d 

如果你用的是Mac,哈哈,你有福了,我可以直接告诉你,Mac的这个目录在/Library/Python/下,这个下面可能会有多个版本的目录,没关系,放在最新的一个版本下的site-packages就行了。使用之前先import一下
from BeautifulSoup import BeautifulSoup 

使用

在使用之前我们先来看一个实例
现在给你这样一个页面

http://movie.douban.com/tag/%E5%96%9C%E5%89%A7

它是豆瓣电影分类下的喜剧电影,如果让你找出里面评分最高的100部,该怎么做呢
好了,我先晒一下我做的,鉴于本人在CSS方面处于小白阶段以及天生没有美术细菌,界面做的也就将就能看下,别吐

Python网页解析利器BeautifulSoup安装使用介绍

接下来我们开始学习BeautifulSoup的一些基本方法,做出上面那个页面就易如反掌了

鉴于豆瓣那个页面比较复杂,我们先以一个简单样例来举例,假设我们处理如下的网页代码

<html>  

<head><title>Page title</title></head>  

<body>  

    <p id="firstpara" align="center">  

    This is paragraph  

        <b>  

        one  

        </b>  

        .  

    </p>  

    <p id="secondpara" align="blah">  

    This is paragraph  

        <b>  

        two  

        </b>  

        .  

    </p>  

</body>  

</html> 

你没看错,这就是官方文档里的一个样例,如果你有耐心,看官方文档就足够了,后面的你都不用看
http://www.leeon.me/upload/other/beautifulsoup-documentation-zh.html

初始化

首先将上面的HTML代码赋给一个变量html如下,为了方便大家复制这里贴的是不带回车的,上面带回车的代码可以让大家看清楚HTML结构

html = '<html><head><title>Page title</title></head><body><p id="firstpara" align="center">This is paragraph<b>one</b>.</p><p id="secondpara" align="blah">This is paragraph<b>two</b>.</p></body></html>' 

初始化如下:
soup = BeautifulSoup(html) 

我们知道HTML代码可以看成一棵树,这个操作等于是把HTML代码解析成一种树型的数据结构并存储在soup中,注意这个数据结构的根节点不是<html>,而是soup,其中html标签是soup的唯一子节点,不信你试试下面的操作
print soup  

print soup.contents[0]  

print soup.contents[1] 

前两个输出结果是一致的,就是整个html文档,第三条输出报错IndexError: list index out of range

查找节点

查找节点有两种反回形式,一种是返回单个节点,一种是返回节点list,对应的查找函数分别为find和findAll

单个节点

1.根据节点名

## 查找head节点  

print soup.find('head') ## 输出为<head><title>Page title</title></head>  

## or  

## head = soup.head 

这种方式查找到的是待查找节点最近的节点,比如这里待查找节点是soup,这里找到的是离soup最近的一个head(如果有多个的话)

2.根据属性

## 查找id属性为firstpara的节点  

print soup.find(attrs={'id':'firstpara'})    

## 输出为<p id="firstpara" align="center">This is paragraph<b>one</b>.</p>  

## 也可节点名和属性进行组合  

print soup.find('p', attrs={'id':'firstpara'})  ## 输出同上

3.根据节点关系

节点关系无非就是兄弟节点,父子节点这样的

p1 = soup.find(attrs={'id':'firstpara'}) ## 得到第一个p节点  

print p1.nextSibling ## 下一个兄弟节点  

## 输出<p id="secondpara" align="blah">This is paragraph<b>two</b>.</p>  

p2 = soup.find(attrs={'id':'secondpara'}) ## 得到第二个p节点  

print p2.previousSibling ## 上一个兄弟节点  

## 输出<p id="firstpara" align="center">This is paragraph<b>one</b>.</p>  

print p2.parent ## 父节点,输出太长这里省略部分 <body>...</body>  

print p2.contents[0] ## 第一个子节点,输出u'This is paragraph'

多个节点

将上面介绍的find改为findAll即可返回查找到的节点列表,所需参数都是一致的

1.根据节点名

## 查找所有p节点  

soup.findAll('p')

2.根据属性查找
## 查找id=firstpara的所有节点  

soup.findAll(attrs={'id':'firstpara'}) 

需要注意的是,虽然在这个例子中只找到一个节点,但返回的仍是一个列表对象

上面的这些基本查找功能已经可以应付大多数情况,如果需要各个高级的查找,比如正则式,可以去看官方文档

获取文本

getText方法可以获取节点下的所有文本,其中可以传递一个字符参数,用来分割每个各节点之间的文本

## 获取head节点下的文本  

soup.head.getText()         ## u'Page title'  

## or  

soup.head.text  

## 获取body下的所有文本并以\n分割  

soup.body.getText('\n')     ## u'This is paragraph\none\n.\nThis is paragraph\ntwo\n.' 

实战

有了这些功能,文章开头给出的那个Demo就好做了,我们再来回顾下豆瓣的这个页面
http://movie.douban.com/tag/%E5%96%9C%E5%89%A7
如果要得到评分前100的所有电影,对这个页面需要提取两个信息:1、翻页链接;2、每部电影的信息(外链,图片,评分、简介、标题等)
当我们提取到所有电影的信息后再按评分进行排序,选出最高的即可,这里贴出翻页提取和电影信息提取的代码

## filename: Grab.py  

from BeautifulSoup import BeautifulSoup, Tag  

import urllib2  

import re  

from Log import LOG  

  

def LOG(*argv):  

    sys.stderr.write(*argv)  

    sys.stderr.write('\n')  

  

class Grab():  

    url = ''  

    soup = None  

    def GetPage(self, url):  

        if url.find('http://',0,7) != 0:  

            url = 'http://' + url  

        self.url = url  

        LOG('input url is: %s' % self.url)  

        req = urllib2.Request(url, headers={'User-Agent' : "Magic Browser"})  

        try:  

            page = urllib2.urlopen(req)  

        except:  

            return  

        return page.read()    

  

    def ExtractInfo(self,buf):  

        if not self.soup:  

            try:  

                self.soup = BeautifulSoup(buf)  

            except:  

                LOG('soup failed in ExtractInfo :%s' % self.url)  

            return  

        try:  

            items = self.soup.findAll(attrs={'class':'item'})  

        except:  

            LOG('failed on find items:%s' % self.url)  

            return  

        links = []  

        objs = []   

        titles = []  

        scores = []  

        comments = []  

        intros = []  

        for item in items:  

            try:  

                pic = item.find(attrs={'class':'nbg'})  

                link = pic['href']  

                obj = pic.img['src']  

                info = item.find(attrs={'class':'pl2'})  

                title = re.sub('[ \t]+',' ',info.a.getText().replace(' ','').replace('\n',''))  

                star = info.find(attrs={'class':'star clearfix'})  

                score = star.find(attrs={'class':'rating_nums'}).getText().replace(' ','')  

                comment = star.find(attrs={'class':'pl'}).getText().replace(' ','')  

                intro = info.find(attrs={'class':'pl'}).getText().replace(' ','')  

            except Exception,e:  

                LOG('process error in ExtractInfo: %s' % self.url)  

                continue  

            links.append(link)  

            objs.append(obj)  

            titles.append(title)      

            scores.append(score)  

            comments.append(comment)  

            intros.append(intro)  

        return(links, objs, titles, scores, comments, intros)  

  

    def ExtractPageTurning(self,buf):  

        links = set([])  

        if not self.soup:  

            try:  

                self.soup = BeautifulSoup(buf)  

            except:  

                LOG('soup failed in ExtractPageTurning:%s' % self.url)  

                return  

        try:  

            pageturning = self.soup.find(attrs={'class':'paginator'})  

            a_nodes = pageturning.findAll('a')  

            for a_node in a_nodes:  

                href = a_node['href']  

                if href.find('http://',0,7) == -1:  

                    href = self.url.split('?')[0] + href  

                links.add(href)  

        except:  

            LOG('get pageturning failed in ExtractPageTurning:%s' % self.url)  

  

        return links  

  

    def Destroy(self):  

        del self.soup  

        self.soup = None 

接着我们再来写个测试样例

## filename: test.py  

#encoding: utf-8  

from Grab import Grab  

import sys  

reload(sys)  

sys.setdefaultencoding('utf-8')  

  

grab = Grab()  

buf = grab.GetPage('http://movie.douban.com/tag/喜剧?start=160&type=T')  

if not buf:  

        print 'GetPage failed!'  

        sys.exit()  

links, objs, titles, scores, comments, intros = grab.ExtractInfo(buf)  

for link, obj, title, score, comment, intro in zip(links, objs, titles, scores, comments, intros):  

        print link+'\t'+obj+'\t'+title+'\t'+score+'\t'+comment+'\t'+intro  

pageturning = grab.ExtractPageTurning(buf)  

for link in pageturning:  

        print link  

grab.Destroy() 

OK,完成这一步接下来的事儿就自个看着办吧
本文只是介绍了BeautifulSoup的皮毛而已,目的是为了让大家快速学会一些基本要领,想当初我要用什么功能都是去BeautifulSoup的源代码里一个函数一个函数看然后才会的,一把辛酸泪啊,所以希望后来者能够通过更便捷的方式去掌握一些基本功能,也不枉我一字一句敲出这篇文章,尤其是这些代码的排版,真是伤透了脑筋

Python 相关文章推荐
优化Python代码使其加快作用域内的查找
Mar 30 Python
调试Python程序代码的几种方法总结
Apr 28 Python
Python使用ftplib实现简易FTP客户端的方法
Jun 03 Python
python3+opencv3识别图片中的物体并截取的方法
Dec 05 Python
Python3中lambda表达式与函数式编程讲解
Jan 14 Python
简单了解python关系(比较)运算符
Jul 08 Python
Python利用PyExecJS库执行JS函数的案例分析
Dec 18 Python
Django Xadmin多对多字段过滤实例
Apr 07 Python
Python 抓取数据存储到Redis中的操作
Jul 16 Python
python修改微信和支付宝步数的示例代码
Oct 12 Python
python3中确保枚举值代码分析
Dec 02 Python
Python实现制作销售数据可视化看板详解
Nov 27 Python
python回溯法实现数组全排列输出实例分析
Mar 17 #Python
使用Python实现下载网易云音乐的高清MV
Mar 16 #Python
python使用点操作符访问字典(dict)数据的方法
Mar 16 #Python
python用来获得图片exif信息的库实例分析
Mar 16 #Python
python通过pil模块获得图片exif信息的方法
Mar 16 #Python
使用Python抓取模板之家的CSS模板
Mar 16 #Python
Python实现竖排打印传单手机号码易撕条
Mar 16 #Python
You might like
PHP提取中文首字母
2008/04/09 PHP
PHP CURL获取cookies模拟登录的方法
2013/11/04 PHP
PHP变量的定义、可变变量、变量引用、销毁方法
2013/12/20 PHP
PHP将进程作为守护进程的方法
2015/03/19 PHP
PHP编程求最大公约数与最小公倍数的方法示例
2017/05/29 PHP
asp(javascript)全角半角转换代码 dbc2sbc
2009/08/06 Javascript
javascript 学习笔记(onchange等)
2010/11/14 Javascript
分享一道笔试题[有n个直线最多可以把一个平面分成多少个部分]
2012/10/12 Javascript
微信小程序开发之录音机 音频播放 动画实例 (真机可用)
2016/12/08 Javascript
3分钟快速搭建nodejs本地服务器方法运行测试html/js
2017/04/01 NodeJs
基于JavaScript实现新增内容滚动播放效果附完整代码
2017/08/24 Javascript
angularjs实现时间轴效果的示例代码
2017/11/29 Javascript
使用sessionStorage解决vuex在页面刷新后数据被清除的问题
2018/04/13 Javascript
vue 动态添加class,三个以上的条件做判断方式
2020/11/02 Javascript
[03:00]《DAC最前线》之欧美新秀VS老将
2015/02/01 DOTA
Python中的特殊语法:filter、map、reduce、lambda介绍
2015/04/14 Python
Python如何实现MySQL实例初始化详解
2017/11/06 Python
Python cookbook(数据结构与算法)实现优先级队列的方法示例
2018/02/18 Python
python opencv 图像尺寸变换方法
2018/04/02 Python
使用Python设计一个代码统计工具
2018/04/04 Python
Python3.6笔记之将程序运行结果输出到文件的方法
2018/04/22 Python
Python原始套接字编程实例解析
2020/01/29 Python
详解Pycharm出现out of memory的终极解决方法
2020/03/03 Python
Python itertools.product方法代码实例
2020/03/27 Python
django 连接数据库出现1045错误的解决方式
2020/05/14 Python
Python xpath表达式如何实现数据处理
2020/06/13 Python
python和JavaScript哪个容易上手
2020/06/23 Python
解决PyCharm无法使用lxml库的问题(图解)
2020/12/22 Python
Java里面Pass by value和Pass by Reference是什么意思
2016/05/02 面试题
2014年小班元旦活动方案
2014/02/16 职场文书
初中学生评语大全
2014/04/24 职场文书
写给纪委的违纪检讨书
2015/05/05 职场文书
导游词之河北邯郸
2019/09/12 职场文书
导游词之长城八达岭
2019/09/24 职场文书
MySQL表类型 存储引擎 的选择
2021/11/11 MySQL
css3属性选择器 “~”(波浪号) “,”(逗号) “+”(加号)和 “>”(大于号)
2022/04/19 HTML / CSS