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守护进程和脚本单例运行详解
Jan 06 Python
老生常谈Python序列化和反序列化
Jun 28 Python
Python 数值区间处理_对interval 库的快速入门详解
Nov 16 Python
快速排序的四种python实现(推荐)
Apr 03 Python
python3.4 将16进制转成字符串的实例
Jun 12 Python
Pandas聚合运算和分组运算的实现示例
Oct 17 Python
关于tf.reverse_sequence()简述
Jan 20 Python
python中的 zip函数详解及用法举例
Feb 16 Python
python将音频进行变速的操作方法
Apr 08 Python
Python Flask异步发送邮件实现方法解析
Aug 01 Python
django有哪些好处和优点
Sep 01 Python
Python WSGI 规范简介
Apr 11 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
40年前的这部特摄片恐龙特级克塞号80后的共同回忆
2020/03/08 日漫
php is_file()和is_dir()用于遍历目录时用法注意事项
2010/03/02 PHP
PHP5中虚函数的实现方法分享
2011/04/20 PHP
提高php运行速度的一些小技巧分享
2012/07/03 PHP
php实现的DateDiff和DateAdd时间函数代码分享
2014/08/16 PHP
PHP将回调函数作用到给定数组单元的方法
2014/08/19 PHP
php实现检查文章是否被百度收录
2015/01/27 PHP
PHP框架laravel的.env文件配置教程
2017/06/07 PHP
通过js动态操作table(新增,删除相关列信息)
2012/05/23 Javascript
兼容最新firefox、chrome和IE的javascript图片预览实现代码
2014/08/08 Javascript
初步了解javascript面向对象
2015/11/09 Javascript
基于JavaScript实现定时跳转到指定页面
2016/01/01 Javascript
第一次接触神奇的Bootstrap网格系统
2016/07/27 Javascript
JS实用的带停顿的逐行文本循环滚动效果实例
2016/11/23 Javascript
jQuery 全选 全不选 事件绑定的实现代码
2017/01/23 Javascript
js实现自定义路由
2017/02/04 Javascript
老生常谈jacascript DOM节点获取
2017/04/17 Javascript
详解vue渲染从后台获取的json数据
2017/07/06 Javascript
VueJs使用Amaze ui调整列表和内容页面
2017/11/30 Javascript
ES6 Set结构的应用实例分析
2019/06/26 Javascript
pandas 层次化索引的实现方法
2019/07/06 Python
python 将字符串中的数字相加求和的实现
2019/07/18 Python
pycharm重命名文件的方法步骤
2019/07/29 Python
Python 70行代码实现简单算式计算器解析
2019/08/30 Python
python 操作hive pyhs2方式
2019/12/21 Python
如何实现在jupyter notebook中播放视频(不停地展示图片)
2020/04/23 Python
Pytorch环境搭建与基本语法
2020/06/03 Python
如何在Python对Excel进行读取
2020/06/04 Python
Pytorch模型迁移和迁移学习,导入部分模型参数的操作
2021/03/03 Python
莫斯科隐形眼镜网上商店:Linzi
2019/07/22 全球购物
Skyscanner新西兰:全球领先的旅游搜索网站
2019/08/26 全球购物
MIRTA官网:手工包,100%意大利制造
2020/02/11 全球购物
一年级小学生评语
2014/04/22 职场文书
2016国培学习心得体会
2016/01/08 职场文书
职工趣味运动会开幕词
2016/03/04 职场文书
Python Numpy之linspace用法说明
2021/04/17 Python