Beautiful Soup的简介
Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据,官方解释如下:
- Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
- Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。
- Beautiful Soup已成为和lxml一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。
GitHub地址:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/
和lxml一样,BeautifulSoup也是一个HTML/XML的解析器,主要功能也是如何解析和提取HTML/XML数据。
解析工具对比
BeautifulSoup的基本使用
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 <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> <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>
"""
# 创建Beautiful Soup对象
soup = BeautifulSoup(html_doc, 'html.parser')
# 类型
print(type(soup))
# 格式化输出对象的内容
print(soup.prettify())
解析器
搜索文档树
Beautiful Soup定义了很多搜索方法,这里介绍两个:find()和find_all(),其它方法的参数和用法类似。
from bs4 import BeautifulSoup
html_doc = """
<table class="tablelist" cellspacing="0" cellpadding="0">
<tbody>
<tr class="h">
<td class="1" width="374">职位名称</td>
<td>职位类别</td>
<td>人数</td>
<td>地点</td>
<td>发布时间</td>
</tr>
<tr class="even">
<td class="l"><a href="https://www.baidu.com">区块链高级研发工程师</a></td>
<td class="l">技术类</td>
<td class="l">1</td>
<td class="l">深圳</td>
<td class="l">2018-11-25</td>
</tr>
<tr class="even">
<td><a href="https://www.qq.com">金融云高级后台开发</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
<tr>
<td><a href="https://www.juran.com">高级研发工程师</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
<tr>
<td><a href="https://www.python.com">高级图像算法工程师</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
<tr>
<td><a href="https://www.lg.com" id="test" class="test">高级业务运维工程师</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
</tbody>
</table>
"""
soup = BeautifulSoup(html_doc, 'lxml')
# 1.获取所有tr标签
# trs = soup.find_all('tr')
# # find查找一个
# # trs = soup.find('tr')
# # print(trs)
# find_all返回的是list
# print(trs)
# for tr in trs:
# print(tr)
# print('='*30)
# 2.获取第2个tr标签
# trs = soup.find_all('tr', limit=2)[1]
# print(trs)
# 3.获取所有class等于even的tr标签
# trs = soup.find_all('tr', class_='even')
# trs = soup.find_all('tr', attrs={'class': 'even'})
# for tr in trs:
# print(tr)
# print('='*30)
# 4.将所有id等于test,class也等于test的a标签提取出来
alist = soup.find_all('a', id='test', class_='test')
# alist = soup.find_all('a', attrs={'id': 'test', 'class': 'test'})
print(alist)
# 5.获取所有的a标签的href属性
# hrefs = soup.find_all('a')
# for a in hrefs:
# 输出每个a标签
# print(a)
# 怎么去获取里面的href属性呢,有以下两种方式
# 1.通过下标的方式
# href = a['href']
# 还可以这样写,用get代码可读性更高,如果不存在不会报错,上面和下面的方法都会报错
# href = a.get('href')
# print(href)
# 2.通过attrs属性的方式
# href = a.attrs['href']
# print(href)
# 6.获取所有的职位信息(纯文本)
# trs = soup.find_all('tr')[1:]
# for tr in trs:
# print(tr)
# tds = tr.find_all('td')
# print(tds)
# title = tds[0]
# print(title.string)
# 获取tr标签的所有文本
# infos = list(tr.strings)
# print(infos)
# 可以去除空格取纯文本
# infos = list(tr.stripped_strings)
# print(infos[0])
CSS常用选择器介绍
- 通过标签名查找
print(soup.select('a'))
- 通过类名查找
# 查找class=sister的标签
print(soup.select('.sister'))
- 通过id查找
# 查找id=link1的标签
print(soup.select('#link1'))
- 组合查找
组合查找即和写class文件时,标签名与类名、id名进行的组合原理是一样的,例如查找p标签中,id等于link1的内容,二者需要用空格分开:
print(soup.select('p #link1'))
- 直接子标签查找,则使用 > 分割:
print(soup.select('head > title'))
- 通过属性查找
print(soup.select('a[href="http://example.com/elsie"]'))
- 获取内容
以上的select 方法返回的结果都是列表形式,可以遍历形式输出,然后用get_text()方法来获取它的内容。
select和css选择器提取元素
from bs4 import BeautifulSoup
html_doc = """
<table class="tablelist" cellspacing="0" cellpadding="0">
<tbody>
<tr class="h">
<td class="1" width="374">职位名称</td>
<td>职位类别</td>
<td>人数</td>
<td>地点</td>
<td>发布时间</td>
</tr>
<tr class="even">
<td class="l"><a href="https://www.baidu.com">区块链高级研发工程师</a></td>
<td class="l">技术类</td>
<td class="l">1</td>
<td class="l">深圳</td>
<td class="l">2018-11-25</td>
</tr>
<tr class="even">
<td><a href="https://www.qq.com">金融云高级后台开发</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
<tr>
<td><a href="https://www.juran.com">高级研发工程师</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
<tr>
<td><a href="https://www.python.com">高级图像算法工程师</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
<tr>
<td><a href="https://www.lg.com" id="test" class="test">高级业务运维工程师</a></td>
<td>技术类</td>
<td>2</td>
<td>深圳</td>
<td>2018-11-24</td>
</tr>
</tbody>
</table>
"""
soup = BeautifulSoup(html_doc, 'lxml')
# 1.获取所有tr标签
# trs = soup.select('tr')
# print(trs)
# 2.获取第2个tr标签
# trs = soup.select('tr')[1]
# print(trs)
# 3.获取所有class等于even的tr标签
# tr = soup.select('tr.even')
# print(tr)
# 4.获取所有的a标签的href属性
# alist = soup.select('a')
# for a in alist:
# href = a.get('href')
# print(href)
# 5.获取所有的职位信息(纯文本)
# trs = soup.select('tr')
# for tr in trs:
# infos = list(tr.stripped_strings)
# print(infos)
BeautifulSoup4四大对象种类
BeautifulSoup4将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:
- Tag
- NavigableString
- BeautifulSoup
- Comment
遍历文档树
contents和children
- contents返回所有子节点的列表
- children返回所有子节点的迭代器
爬取图片
import requests
from bs4 import BeautifulSoup
def run(page):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
url = 'https://www.buxiuse.com/?cid=3&page={}'.format(page)
response = requests.get(url, headers=headers).text
soup = BeautifulSoup(response, 'lxml')
scrcs = soup.find_all('img')
for img in scrcs:
src = img.get('src')
name = img.get('alt')
with open('imgs/{}-1.jpg'.format(name), 'wb') as f:
f.write(requests.get(src, headers=headers).content)
print('正在下载{}'.format(name))
if __name__ == '__main__':
for page in range(1, 5):
run(page)
爬取天气
import requests
from bs4 import BeautifulSoup
def main():
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
url = 'http://www.weather.com.cn/textFC/hb.shtml'
response = requests.get(url, headers=headers)
# 乱码的话就解码(乱码的原因有两种:1、当前请求的编码和网页的编码不一样2、当前文件的编码也会影响爬下来的数据是不是乱码)
response.encoding = 'utf-8'
# 获取页面的源代码
html = response.text
# print(html)
soup = BeautifulSoup(html, 'lxml')
conMidtab = soup.find('div', attrs={'calss': 'conMidtab'})
# 获取table表格
tables = conMidtab.find_all('table')
for table in tables:
trs = table.find_all('tr')[2:]
for index, tr in enumerate(trs):
tds = tr.find_all('td')
# 判断索引
if index == 0:
city_td = tds[1]
else:
city_td = tds[0]
temp_td = tds[-2]
city = list(city_td.stripped_strings)[0]
temp = list(temp_td.stripped_strings)[0]
print(city, temp)
if __name__ == '__main__':
main()