文章目录
历史回顾
- 1.爬虫专题大纲
- 2.urllib、urllib2、request三者关系
- 3.urllib学习
- 4.urllib2学习
- 5.requests学习
- 6.页面提取之正则表达式
- 6.页面提取之xpath
- ps:如何用浏览器抓包分析
页面提取已经总结了xpath(lxml库)、正则(re库),我最先接触并且常用的是xpath和正则,这两个的组合完全满足页面解析需求,所以beautifulsoup使用的比较少。
并且个人感觉beautifulsoup就是鸡肋,但是也有不少人主要使用这个库,现在总结一下python的beautifulsoup库的使用方法。
安装
pip install beautifulsoup4
介绍
加载html
我们抓取一个页面,并且使用BeautifulSoup加载页面,然后使用prettify格式化打印一下页面源码。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
import sys
from bs4 import BeautifulSoup
reload(sys)
sys.setdefaultencoding('utf8')
def first():
url = "http://www.tenliu.top/index.php/2018/01/09/%E7%88%AC%E8%99%AB-requests%E5%AD%A6%E4%B9%A0/"
page = requests.get(url).text
soup = BeautifulSoup(page,"lxml")
print soup.prettify()
if __name__=="__main__":
first()
可以看到BeautifulSoup(page,"lxml")
加载html页面,但是加载方法不止这一种,如下:
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup, “html.parser”) | Python的内置标准库执行速度适中文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup, “lxml”) | 速度快文档容错能力强 | 需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup, [“lxml”, “xml”])BeautifulSoup(markup, “xml”) | 速度快唯一支持XML的解析器 | 需要安装C语言库 |
html5lib | BeautifulSoup(markup, “html5lib”) | 最好的容错性以浏览器的方式解析文档生成HTML5格式的文档 | 速度慢不依赖外部扩展 |
四种对象类型
beautiful soup将html文档转成树形结构:beautiful soup节点分成四种对象
- Tag,就是html标签
- NavigableString,我的理解就是html标签的文字。
- BeautifulSoup,就是html文档的全部内容,可视为Tag,没什么好讲的
- Comment,文档的注释部分。
前面三个类型,我们后面会融合讲解,说明一下Comment,在我看来是鸡肋,但是既然是总结,总要解释一下:
>>> markup = '''<div>this is string</div><b><!--Hey, buddy. Want to buy a used parser?--></b>'''
>>> s = BeautifulSoup(markup)
>>> s.div.string
u'this is string'
>>> s.b.string
u'Hey, buddy. Want to buy a used parser?'
>>> type(s.b.string)
<class 'bs4.element.Comment'>
>>> type(s.div.string)
<class 'bs4.element.NavigableString'>
定位节点
如何定位html标签才是重点,我们先加载一个待解析的页面
>>> import requests
>>> from bs4 import BeautifulSoup
>>> url = "http://www.tenliu.top/index.php/2018/01/09/%E7%88%AC%E8%99%AB-requests%E5%AD%A6%E4%B9%A0/"
>>> page = requests.get(url).text
>>> soup = BeautifulSoup(page,"lxml")
通过标签名称定位
选择html第一个a标签
>>> soup.a
<a class="skip-link screen-reader-text" href="#content">\u8df3\u81f3\u5185\u5bb9</a>
加入节点关系
选择html的body的第一个a标签
>>> soup.body.a
<a class="skip-link screen-reader-text" href="#content">\u8df3\u81f3\u5185\u5bb9</a>
选择多个标签
选择html页面所有a标签
>>> soup.find_all('a')
选择html页面所有a标签和b标签
>>> soup.find_all(['a','b'])
加入正则表达式(标签名)
选择所有以b开头的html标签
>>> import re
>>> soup.find_all(re.compile('^b'))
通过属性的键值选择标签
选择属性rel等于home的所有标签
>>> soup.find_all(rel="home")
[<a href="http://www.tenliu.top/" rel="home">TenLiu\u4e2a\u4eba\u7f51\u7ad9</a>]
选择属性rel等于home的所有a标签
>>> soup.find_all("a",rel="home")
[<a href="http://www.tenliu.top/" rel="home">TenLiu\u4e2a\u4eba\u7f51\u7ad9</a>]
加入正则表达式(属性)
>>> soup.find_all(rel=re.compile('hom'))
[<a href="http://www.tenliu.top/" rel="home">TenLiu\u4e2a\u4eba\u7f51\u7ad9</a>]
节点内文本
string
.string
,如果tag只有一个 NavigableString 类型或tag类型的子节点,那么这个tag可以使用 .string
得到文本内容
>>> markup = '''<p><b>aaaa</b></p><div><b>bbbb</b><b>cccc</b></div>'''
>>> s = BeautifulSoup(markup)
>>> s
<html><body><p><b>aaaa</b></p><div><b>bbbb</b><b>cccc</b></div></body></html>
>>> s.p
<p><b>aaaa</b></p>
>>> s.p.string
u'aaaa'
>>> s.div.string
>>>
strings
.strings
,如果tag包含了多个子节点,例如上面的div标签,本文内容何如提取呢?
>>> for string in s.div.strings:
... print string
...
bbbb
cccc
节点属性
.attrs
>>> soup.p.a.attrs
{'href': 'http://www.tenliu.top/', 'rel': ['home']}
>>> soup.p.a.attrs['href']
'http://www.tenliu.top/'
>>> soup.p.a['href']
'http://www.tenliu.top/'
其他
- tag的
.contents
属性可以将tag的所有直接子节点以列表的方式输出 - 通过tag的
.children
生成器,可以对tag的所有直接子节点进行循环 .descendants
属性可以对所有tag的子孙节点进行递归循环- ······
就到这里吧。