序言

  之前用python爬取网页的时候,一直用的是regex或者自带的库sgmllib里的SGMLParser。但是遇到复杂一点的情况时,SGMLParser往往就不那么给力了!(哈,难道说我 too native了?毕竟beautifulSoup是继承sgmlparser的么~)所以,我寻寻觅觅寻寻觅觅,发现了BeautifulSoup这么个玩意。BeautifulSoup提供了很人性化的parser tree,有了它,我们可以简单的抽取出tagname, attrs, text等等等等...

  install什么的,看这里 -> http://www.crummy.com/software/BeautifulSoup/

入门

(ps:其实入门什么的看官方文档是最好的了,这里只是记录一下简单的用法。)

(official document link : http://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html

  首先先介绍实际工作中最常用的几个方法:

  举例的html代码(就用官方例子好了):

 1 <html>
2 <head>
3 <title>Page title</title>
4 </head>
5 <body>
6 <p id="firstpara" align="center">
7 This is paragraph<b>one</b>.
8 </p>
9 <p id="secondpara" align="blah">
10 This is paragraph<b>two</b>.
11 </p>
12 </body>
13 </html>

0、初始化

1 soup = BeautifulSoup(html) # html为html源代码字符串,type(html) == str

1、用tag获取相应代码块的剖析树:

  既然要分析html,首先要找到对我们有用的tag块,beautiful提供了非常便利的方式。

#当用tag作为搜索条件时,我们获取的包含这个tag块的剖析树:
#<tag><xxx>ooo</xxx></tag>
#这里获取head这个块
head = soup.find('head')
# or
# head = soup.head
# or
# head = soup.contents[0].contents[0]

运行后,我们会得到:

1 <head>
2 <title>Page title</title>
3 </head>

  这里小灯我还是推荐使用第二种方法,find方法在当前tag剖析树(当前这个html代码块中)寻找符合条件的子树并返回。find方法提供多种查询方式,包括用喜闻乐见的regex哦~之后会详细介绍。

  contents属性是一个列表,里面保存了该剖析树的直接儿子。

如:

1 html = soup.contents[0] # <html> ... </html>
2 head = html.contents[0] # <head> ... </head>
3 body = html.contents[1] # <body> ... </body>

2、用contents[], parent, nextSibling, previousSibling寻找父子兄弟tag

  为了更加方便灵活的分析html代码块,beautifulSoup提供了几个简单的方法直接获取当前tag块的父子兄弟。

假设我们已经获得了body这个tag块,我们想要寻找<html>, <head>, 第一个<p>, 第二个<p>这四个tag块:

# body = soup.bodyhtml = body.parent # html是body的父亲
head = body.previousSibling # head和body在同一层,是body的前一个兄弟
p1 = body.contents[0] # p1, p2都是body的儿子,我们用contents[0]取得p1
p2 = p1.nextSibling # p2与p1在同一层,是p1的后一个兄弟, 当然body.content[1]也可得到 print p1.text
# u'This is paragraphone.'
print p2.text
# u'This is paragraphtwo.'
# 注意:1,每个tag的text包括了它以及它子孙的text。2,所有text已经被自动转
#为unicode,如果需要,可以自行转码encode(xxx)

  然而,如果我们要寻找祖先或者孙子tag怎么办呢?? 用while循环吗? 不, beautifulsoup已经提供了方法。

3、用find, findParent, findNextSibling, findPreviousSibling寻找祖先或者子孙 tag:

  有了上面的基础,这里应该很好理解了,例如find方法(我理解和findChild是一样的),就是以当前节点为起始,遍历整个子树,找到后返回。

  而这些方法的复数形式,会找到所有符合要求的tag,以list的方式放回。他们的对应关系是:find->findall, findParent->findParents, findNextSibling->findNextSiblings...

  如:

1 print soup.findAll('p')
2 # [<p id="firstpara" align="center">This is paragraph <b>one</b>.</p>, <p id="secondpara" align="blah">This is paragraph <b>two</b>.</p>]

  

  这里我们重点讲一下find的几种用法,其他的类比:

  find(name=None, attrs={}, recursive=True, text=None, **kwargs)

(ps:只讲几种用法,完整请看官方link : http://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html#The%20basic%20find%20method:%20findAll%28name,%20attrs,%20recursive,%20text,%20limit,%20**kwargs%29

  1) 搜索tag:

1 find(tagname)        # 直接搜索名为tagname的tag 如:find('head')
2 find(list) # 搜索在list中的tag,如: find(['head', 'body'])
3 find(dict) # 搜索在dict中的tag,如:find({'head':True, 'body':True})
4 find(re.compile('')) # 搜索符合正则的tag, 如:find(re.compile('^p')) 搜索以p开头的tag
5 find(lambda) # 搜索函数返回结果为true的tag, 如:find(lambda name: if len(name) == 1) 搜索长度为1的tag
6 find(True) # 搜索所有tag

  2) 搜索属性(attrs):

1 find(id='xxx')                                  # 寻找id属性为xxx的
2 find(attrs={id=re.compile('xxx'), algin='xxx'}) # 寻找id属性符合正则且algin属性为xxx的
3 find(attrs={id=True, algin=None}) # 寻找有id属性但是没有algin属性的

  3) 搜索文字(text):

注意,文字的搜索会导致其他搜索给的值如:tag, attrs都失效。

方法与搜索tag一致

  4) recursive, limit:

  recursive=False表示只搜索直接儿子,否则搜索整个子树,默认为True。

  当使用findAll或者类似返回list的方法时,limit属性用于限制返回的数量,如findAll('p', limit=2): 返回首先找到的两个tag

*4、用next,previous寻找上下文tag(少用)

  这里我们主要看看next, next是取得当前的tag的下一个(按代码从上到下的顺序)tag块。这与contents是不一样的,千万别混淆了哦^ ^

  我们举个栗子来看看

1 <a>
2 a
3 <b>b</b>
4 <c>c</c>
5 </a>

我们看看next的实际效果:

1 a = soup.a
2 b = soup.b
3 n1 = b.next
4 n2 = n1.next

输出一下:

1 print a.next
2 # u'a'
3 print n1
4 # u'b'
5 print n2
6 # <c>c</c>

所以,next仅仅是获取文档上的“下一个”的tag,和剖析树中的位置无关。

当然也有findNext和findAllNext方法。

至于previous, 表示上一个tag块,就类比一下吧~^ ^

=======

待续

用python的BeautifulSoup分析html的更多相关文章

  1. 用python的BeautifulSoup分析html 【转】

    原地址:http://www.cnblogs.com/twinsclover/archive/2012/04/26/2471704.html 序言 之前用python爬取网页的时候,一直用的是rege ...

  2. python爬虫之分析Ajax请求抓取抓取今日头条街拍美图(七)

    python爬虫之分析Ajax请求抓取抓取今日头条街拍美图 一.分析网站 1.进入浏览器,搜索今日头条,在搜索栏搜索街拍,然后选择图集这一栏. 2.按F12打开开发者工具,刷新网页,这时网页回弹到综合 ...

  3. Ubuntu下一个python的BeautifulSoup和rsa安装方法---信息检索project2部分:微博爬行要求python包裹

    后果<信息检索>第二project,微博具有抓取数据,再处理.师兄给了代码.让慢慢爬.可是在ubuntu下.少了非常多python软件包.须要安装. 1.首先执行时.说少了python.B ...

  4. 搭建基于python +opencv+Beautifulsoup+Neurolab机器学习平台

    搭建基于python +opencv+Beautifulsoup+Neurolab机器学习平台 By 子敬叔叔 最近在学习麦好的<机器学习实践指南案例应用解析第二版>,在安装学习环境的时候 ...

  5. Python配合BeautifulSoup读取网络图片并保存在本地

    本例为Python配合BeautifulSoup读取网络图片,并保存在本地. BeautifulSoup可代替正则表达式,更好地解析Html文本,获取其中的指定内容,如Tag.Property等 # ...

  6. Python文章相关性分析---金庸武侠小说分析

    百度到<金庸小说全集 14部>全(TXT)作者:金庸 下载下来,然后读取内容with open('names.txt') as f: data = [line.strip() for li ...

  7. [python]Python代码安全分析工具(Bandit)

    简介: Bandit是一款Python源码分析框架,可用于Python代码的安全性分析.Bandit使用标准库中的ast模块,将Python源码解析成Python语法节点构成的树.Bandit允许用户 ...

  8. 用python探索和分析网络数据

    Edited by Markdown Refered from: John Ladd, Jessica Otis, Christopher N. Warren, and Scott Weingart, ...

  9. python scrapy,beautifulsoup,regex,sgmparser,request,connection

    In [2]: import requests   In [3]: s = requests.Session()   In [4]: s.headers 如果你是爬虫相关的业务?抓取的网站还各种各样, ...

随机推荐

  1. 菜篮子成血战场!生鲜O2O为何厮杀如此惨烈

    衣食住行作为与大众生活直接挂钩的刚需,已经被诸多互联网企业全面渗入,并在彻底颠覆大众原有的生活形态.但其中作为最底层.最基本的"菜篮子"--生鲜市场,似乎仍然没有被互联网元素完全& ...

  2. Molex莫仕:技术向左,连接器向右

    序言:众所周知,Molex莫仕主要产品是连接器,近几年伴随市场的改变,客户要求的改变,供应链的改变,我Molex也在改变,现在的Molex已不仅仅是连接器公司,转型成技术为导向的公司——技术向左,连接 ...

  3. cooking和session

    ## Cookie ## # 基本概念: >> 用于保存一次会话中的记录,存放在客户端(浏览器); |-- "一次会话" |-- 当客户端打开一个界面时 被称作一次会话 ...

  4. 原本准备的 event loop 分享

    基础介绍 Stack 栈 一种先入后出的数据结构. 两个基本操作: 推入,弹出 Queue 队列 一种先入先出的数据结构 操作: 入队,出队 两种任务: 同步任务,异步任务 同步任务: 在调用栈中等待 ...

  5. 大厂常问iOS面试题--性能优化篇

    1.造成tableView卡顿的原因有哪些? 1.最常用的就是cell的重用, 注册重用标识符 如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell 如果有很多数据的时候 ...

  6. C++冒险攻略(持续更新中。。。)

    C++语言程序设计 我的C++冒险之旅 绪论 计算机系统基本概念 计算机硬件 计算机程序语言 计算机解决问题是程序控制的 程序就是操作步骤 程序要使用语言来表达 机器语言 计算机能识别的是机器语言 机 ...

  7. 关于java性能优化细节方面的建议

    在Javva程序中,性能问题的大部分原因并不在于Java语言,而是程序本身,养成一个良好的编码习惯非常重要,能够显著地提升程序性能.下面来聊聊该方面的建议: 1.尽量在合适的场合使用单例: 所谓单例, ...

  8. 微信小程序结构目录、配置介绍、视图层(数据绑定,运算,列表渲染,条件渲染)

    目录 一.小程序结构目录 1.1 小程序文件结构和传统web对比 1.2 基本的项目目录 二.配置介绍 2.1 配置介绍 2.2 全局配置app.json 2.3 page.json 三.视图层 3. ...

  9. 必备技能六、Vue框架引入JS库的正确姿势

    在Vue.js应用中,可能需要引入Lodash,Moment,Axios,Async等非常好用的JavaScript库.当项目变得复杂庞大,通常会将代码进行模块化拆分.可能还需要跑在不同的环境下,比如 ...

  10. PHP的for循环

    For循环执行代码块指定的次数,或者当指定的条件为真时循环执行代码块.for循环用于您预先知道脚本需要运行的次数的情况 for(初始值:条件:增量) { 要执行的代码: } <html> ...