第22天—Python爬虫—Beautiful Soup库
Beautiful Soup 的简介
简单来说,Beautiful Soup 是 python 的一个库,最主要的功能是从网页抓取数据。官方解释如下:
Beautiful Soup 提供一些简单的、python 式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。 Beautiful Soup 自动将输入文档转换为 Unicode 编码,输出文档转换为 utf-8 编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup 就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。 Beautiful Soup 已成为和 lxml、html6lib 一样出色的 python 解释器,为用户灵活地提供不同的解析策略或强劲的速度。
更多相关知识请看Beautiful Soup官方文档
Beautiful Soup 安装
进入终端输入下面的命令,安装Beautiful Soup三方库
pip install beautifulsoup4
使用Beautiful Soup
from bs4 import BeautifulSoup
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><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>
"""
# 创建 Beautiful Soup 对象:
soup = BeautifulSoup(html, 'lxml')
# print(soup, type(soup), sep='\n')
# prettify()格式化HTML源码
print(soup.prettify())
# 打印标签: 打印第一个某某标签的内容
print(soup.head.title)
# 打印标签内容:4种方法
print(soup.head.title.string)
print(soup.head.title.get_text())
print(soup.head.title.text)
print(soup.head.title.contents)
# 对应结果:
"""
The Dormouse's story
The Dormouse's story
The Dormouse's story
["The Dormouse's story"]
"""
# 选择标签方法内容:
# select: 使用(id、class、标签、属性、父子、后代、兄弟、相邻兄弟选择器等)去选择标签,返回的结果是一个列表
# select_one: 使用(id、class、标签、属性、父子、后代、兄弟、相邻兄弟选择器等)去选择标签, 返回的结果是select结果中的第一个元素
p_list = soup.select('body > p')
print(p_list)
p_list_1 = soup.select('body > .title')
print(p_list_1)
p = soup.select_one('body > p')
print(p)
# 对应结果:
"""
[<p class="title" name="dromouse"><b>The Dormouse's story</b></p>, <p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>, <p class="story">...</p>]
[<p class="title" name="dromouse"><b>The Dormouse's story</b></p>]
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
"""
HTML页面的结构
超文本标签语言 —> 所有的内容都放在标签下
<p> / <h1> / <a> / <img> / <li>
文本标签 / 链接标签 / 列表 / 表格 / 表单 / 图片 / 音视频 / 窗口
CSS(Cascading Style Sheet):页面渲染
选择器 —> 样式属性名: 样式属性值
- 标签选择器 —> div
- 类选择器 —> .foo
- ID选择器 —> #bar
- 父子选择器 —> div > p
- 后代选择器 —> div p
- 兄弟选择器 —> div ~ p
- 相邻兄弟选择器 —> div + p
- 伪类/伪元素 —> a:visited / p:first-letter
使用Beautiful Soup爬取链家数据
import requests
from bs4 import BeautifulSoup
for page in range(1, 10):
# 网址
URL = f'https://cd.lianjia.com/ershoufang/pg{page}/'
# 请求头
headers = {
'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
}
# 抓取页面
resp = requests.get(url=URL, headers=headers)
# 创建 Beautiful Soup 对象:
soup = BeautifulSoup(resp.text, 'lxml')
# 获取li标签,每个li标签包含每个二手房的所有信息
li_list = soup.select('body > .content > .leftContent > .sellListContent > .clear')
for i in li_list:
# 标题
title = i.select_one('li > .info > .title > a').text
print(title)
# 超链接
href = i.select_one('li > .info > .title > a').attrs['href']
print(href)
# 位置
area = i.select_one('li > .info > .flood > .positionInfo ').text.replace(' ', '')
print(area)
# 单价
unit_price = i.select_one('li > div.info > div.priceInfo > div.unitPrice > span').text
print(unit_price)
# 总价
total_price = i.select_one('li > div.info.clear > div.priceInfo > div.totalPrice > span').text
print(total_price)
print('-' * 10)
练习:
抓取中国新闻网当天新闻
import requests
import time
from bs4 import BeautifulSoup
flag = True
page = 1
while flag:
URL = f'https://www.chinanews.com/scroll-news/news{page}.html'
headers = {
'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
}
resp = requests.get(url=URL, headers=headers)
# 保证页面正常显示
resp.encoding = 'utf-8'
# 创建 Beautiful Soup 对象:
soup = BeautifulSoup(resp.text, 'lxml')
# 获取li标签 每个li标签包含了每条新闻的所有数据
li_list = soup.select('#content_right > div.content_list > ul > li')
# 页面加一
page += 1
# 获取
localtime = time.localtime()
for i in li_list:
try:
# 获取当天新闻
if i.select_one('li > div.dd_time').text[:-6] == f'{localtime.tm_mon}-{localtime.tm_mday}':
# 新闻类型
news_type = i.select_one('li > div.dd_lm').text
# 新闻标题
news_title = i.select_one('li > div.dd_bt > a').text
# 新闻链接
news_href = 'https:' + i.select_one('li > div.dd_bt > a').attrs['href']
# 新闻时间
news_time = i.select_one('li > div.dd_time').text
print(news_type, news_title, news_time)
print(news_href)
print('--' * 30)
else:
flag = False
break
except:
pass
.attrs[]
获取标签里面的属性