简介
BeautifulSoup 是一个HTML/XML的解析器,主要用于解析和提取HTML/XML 数据。
它基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。
BeautifulSoup用来解析HTML 比较简单,API非常人性化,支持CSS选择器、Python标准库中的HTML解析器,也支持lxml 的XML解析器。
官方文档:http://beautifulsoup.readthedocs.io/zh_CN/v4.4.0
| 抓取工具| 速度| 难度|
|---|---|---|
| 正则 | 最快 | 复杂|
| BeautifulSoup | 慢 | 简单 |
| xpath | 快 | 简单|
安装
在pycharm的terminal终端命令窗口中输入: pip install beautifulsoup4 或者使用清华源的镜像,会更快一点 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple beautifulsoup4
知识
初始化
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
root = etree.HTML(html_doc)
root.xpath()
# 加载字符串 构建BeautifulSoup对象 指明解析器
soup = BeautifulSoup(html_doc,"lxml")
soup.select()
# 加载文档
soup = BeautifulSoup(open("path"),"lxml")
# 格式化输出加载的内容
print(soup.prettify())
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以分为4种。
Tag(标签)
最重要的一类对象,后边解析网页就靠它了。
用BeautifulSoup来获取Tags
from bs4 import BeautifulSoup
# 加载字符串 构建BeautifulSoup对象 指明解析器
soup = BeautifulSoup(html_doc,"lxml")
# 加载文档
soup = BeautifulSoup(open("path"),"lxml")
# 格式化输出加载的内容
print(soup.prettify())
# 注意,它查找的是在所有内容中的第一个符合要求的标签。
# 等同于xpath的 //title[1]
print(soup.title)
print(soup.head)
print(soup.a)
print(soup.p)
print(type(soup.p))
对于Tag,它有两个重要的属性,是name 和attrs(attributes)
#soup对象本身比较特殊,它的name即为[document]
print(soup.name)
print(soup.head.name)
#把p标签的所有属性打印输出了出来,得到的类型是一个字典。
print(soup.p.attrs["class"]) attributes
#根据名称获取对应的属性值,类型为列表
print(soup.p['class'])
#//p[1]/@class
print(soup.p.get('class'))
===没啥用====
#可以对这些属性和内容等等进行修改
soup.p['class']="newClass"
print(soup.p)
#删除属性
del soup.p['class']
print(soup.p)
NavigableString(标签文本内容)
获取标签内部的文字用.string即可,例如
print(soup.p.string)
#The Dormouse's story
# //p[1]/text()
print(type(soup.p.string))
#In[13]:<class'bs4.element.NavigableString'>
BeautifulSoup(根对象)(没啥用)
BeautifulSoup 对象表示的是一个文档的内容。大部分时候,可以把它当作Tag对象,是一个特殊的Tag,我们可以分别获取它的类型,名称,以及属性
print(type(soup.name))
#<type'unicode'>
print(soup.name)
#[document]
# attributes
print(soup.attrs)
#文档本身的属性为空
Comment(注释内容)
Comment对象是一个特殊类型的NavigableString对象,其输出注释但不包含注释符号。
print(soup.a)
#<aclass="sister"href="http://example.com/elsie"id="link1"><!--Elsie--></a>
print(soup.a.string)
#Elsie
print(type(soup.a.string))#<class'bs4.element.Comment'>
a 标签里的内容实际上是注释,但是如果我们利用.string 来输出它的内容时,注释符号已经去掉了。
遍历文档树
.contents
tag 的.content 属性可以将tag的子节点以列表的方式输出
print(soup.head.contents)
print(soup.head.contents[0])
.children
它返回的不是一个list,不过我们可以通过遍历获取所有子节点。 我们打印输出.children 看一下,可以发现它是一个list 生成器对象
print(soup.head.children)
for child in soup.body.children:
print(child)
.descendants属性
.contents 和.children 属性仅包含tag的直接子节点,.descendants 属性可以对所有tag的子孙节点进行递归循环, 和children类似,我们也需要遍历获取其中的内容。
for child in soup.descendants:
print(child)
CSS选择器
通过标签名查找
语法格式:
xpath: //标签名
soup.select('标签名')
查找所有title标签
print(soup.select(‘title’))
查找所有a标签
print(soup.select('a'))
查找标签b标签
print(soup.select('b'))
通过类名查找
语法格式:
xpath //*[@class="类名"]
soup.select('.类名')
查找所有class是sister的标签
print(soup.select(‘.sister’))
通过ID查找
语法格式:
xpath: //*[@id="id名字"]
soup.select('#id名字')
查找所有id是link1的标签
print(soup.select(‘#link1’))
组合查找
直接子集查找
直接子标签查找,则使用 > 分隔。 例如查找head标签直接子集中,标签为title的元素,二者需要用 。
# xpath: //head/title
print(soup.select("head > title"))
所有子集查找
每块表达式用 空格 连接。 例如查找p 标签中,id 等于link1的内容,二者需要用空格分开。
# xpath: //p//*[@id="link"]
print(soup.select('p #link1'))
属性查找
查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。
# 查找所有class属性值为sister的a标签
#xpath //a[@class="sister"]
print(soup.select('a[class="sister"]'))
# 查找所有href属性值为"http://example.com/elsie"的a标签
#xpath //a[@href="http://example.com/elsie"]
print(soup.select('a[href="http://example.com/elsie"]'))
同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开
# 查找所有p标签下 href属性值为"http://example.com/elsie"的a标签
#xpath //p//a[@href="http://example.com/elsie"]/*[@class="className"]
print(soup.select('p a[href="http://example.com/elsie"] > .className')
任务
双色球信息爬取 http://zst.aicai.com/ssq/openInfo/
豆瓣新书的信息爬取 https://book.douban.com/latest