|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 极品召唤兽 于 2021-2-16 21:54 编辑
『 上 节 回 顾 』
~~来呀来呀~~
『 订 阅 淘 贴 』
~~欢迎欢迎~~
『 BeautifulSoup 』
它通过定位 HTML 标签来格式化和组织复杂的网页源代码,用简单易用的 Python 对象为我们展现出 HTML 结构信息。
如果我们想在自己的电脑上安装,可以通过在命令行中输入 pip install beautifulsoup4 安装。
处理数据分为两步:解析数据 和 提取数据
解析数据指将网页源代码解析成 Python 能“读懂”的格式
提取数据则是指将网页源代码中无关数据过滤掉,只提取出我们所需要的数据。
『 解 析 数 据 』
如何将其网页源代码解析成 BeautifulSoup 对象?
import requests
from bs4 import BeautifulSoup
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
res = requests.get('https://book.douban.com/top250', headers=headers)
soup = BeautifulSoup(res.text, 'html.parser')
Tips:相比之前我们添加 headers 参数,这是为了应对豆瓣的反爬虫机制。
这一关中你先原样照抄,下一关会详细讲解如何应对反爬虫。
from bs4 import BeautifulSoup
#导入 BeautifulSoup
BeautifulSoup(res.text, 'html.parser')
#将网页源代码的字符串形式解析成了 BeautifulSoup 对象
创建 BeautifulSoup 对象时需要传入两个参数
第一个参数是要解析的 HTML 文本
即网站源代码的字符串形式(res.text)
第二个参数是解析 HTML 的解析器
html.parser 是 Python 中内置的解析器,较为简单方便
res = requests.get('https://book.douban.com/top250', headers=headers)
print(type(res.text))
# 输出:<class 'str'>
soup = BeautifulSoup(res.text, 'html.parser')
print(type(soup))
# 输出:<class 'bs4.BeautifulSoup'>
网页源码 res.text 和 soup 内容打印出虽然相同
但两者格式类型却有差别
『 提 取 数 据 』
soup = BeautifulSoup(res.text, 'html.parser')
print(soup.find('a'))
# 输出:<a >登录/注册</a>
print(soup.find_all('a'))
# 输出:[
# <a >登录/注册</a>,
# <a >豆瓣电影</a>,
# <a >追风筝的人</a>,
# <a >解忧杂货店</a>,
# <a >小王子</a>
# ]
find() 返回首个符合条件的数据
find_all() 返回全部符合条件的数据
find可以添加 标签 和 属性 条件进行 查询
# 查找 id='doubanapp-tip' 的 div 标签
soup.find('div', id='doubanapp-tip')
# 查找所有 class='rating_nums' 的 span 标签
soup.find_all('span', class_='rating_nums')
# 查找 id='doubanapp-tip' 且 class='rating_nums' 的 div 标签
soup.find('div', id='doubanapp-tip', class_='rating_nums')
『 Tag 对 象 』
[b]BeautifulSoup 将 HTML 中的元素封装成了 Tag 对象。
和 BeautifulSoup 对象 一样,Tag 对象 里也有 find() 和 find_all() 方法。
因此,我们可以不断地调用这两个方法,一层一层地找到我们需要的数据。
实例:
<div class="content">
<a >登录/注册</a>
<h1>豆瓣读书 Top 250</h1>
<div class="books">
<a >豆瓣电影</a>
<div class="item">
<a >追风筝的人</a>
</div>
<div class="item">
<a >解忧杂货店</a>
</div>
<div class="item">
<a >小王子</a>
</div>
</div>
</div>
观察代码可以看出
1.书名在 a 标签 中
但如果直接使用 soup.find_all('a') 的话
第二行的“登录/注册”和第五行的“豆瓣电影”也会被获取到
2.书名在 class="item" 的 div 标签 里的 a 标签 内
我们只要先找到所有 class="item" 的 div 标签,然后再找到其中的 a 标签 即可
# 找到所有 class_='item' 的 div 标签
items = soup.find_all('div', class_='item')
for i in items:
# 找到 class_='item' 的 div 标签中的 a 标签
print(i.find('a'))
# 输出:
# <a >追风筝的人</a>
# <a >解忧杂货店</a>
# <a >小王子</a>
这样,我们就找到了所有书名的数据。此时返回的还是 Tag 对象。如果我们只想要书名和对应的链接呢?
『 Tag 对象 的 text 属性和 HTML 属性名取值 』
实例:
items = soup.find_all('div', class_='item')
for i in items:
tag = i.find('a')
# 获取 text 属性
name = tag.text
# 获取 href 属性值
link = tag['href']
print(name, link)
# 输出:
# 追风筝的人 https://book.douban.com/subject/1770782/
# 解忧杂货店 https://book.douban.com/subject/25862578/
# 小王子 https://book.douban.com/subject/1084336/
我们通过 Tag 对象 的 text 属性拿到了 a 标签里的文字内容[/b]即 追风筝的人 等
然后我们通过和字典取值一样的方式,将 HTML 属性名 作为键
得到了对应属性的值
这里是以 href 属性为例,其他的 HTML 属性也同样可以。
总结:
『 CSS 选择器 』
多次调用 find() 或 find_all() 方法一层层地找到了我们需要的数据。
如何才能不用多次查找就能直接找到数据呢?
在 CSS 选择器中
# 代表 id . 代表 class
比如:
#login 表示 id='login' 的所有元素,.item 表示 class='item' 的所有元素。
可以直接通过标签名选择对应的元素
比如:
a 表示所有的 a 元素,p 表示所有的 p 元素。
可以组合在一起 选择同时符合条件的元素
比如:
a#login 表示所有 id='login' 的 a 元素
p.item 表示所有 class='item' 的 p 元素
#login.item 表示所有 id='login' 且 class='item' 的元素
.item.book 表示所有 class 同时为 item 和 book 的元素
需要注意的是,选择同时符合条件的元素,选择器之间不能有空格!
『 子 元 素 选 择 』
[b]如果选择条件中出现了空格,就是另一种情况了--子元素选择
以 .item .book 为例
它表示选择所有 class='item' 的元素里面 class='book' 的元素
即嵌套在 class='item' 的元素里面 class='book' 的元素。
这个嵌套可以是任意层级的,只要在里面就行,不要求直接嵌套在第一层。
如果只需要直接嵌套在第一层符合条件的元素,可以用 > 分隔。比如:.item > .book。
实例:
from bs4 import BeautifulSoup
html = '''
<div class="item">
<p class="book">小王子</p>
<div class="hot">
<p class="book">追风筝的人</p>
</div>
</div>'''
soup = BeautifulSoup(html, 'html.parser')
print(soup.select('.item.book'))
# 输出:[](没有两个条件都满足的数据)
print(soup.select('.item .book'))
# 输出:[<p class="book">小王子</p>, <p class="book">追风筝的人</p>](嵌套满足)
print(soup.select('.item > .book'))
# 输出:[<p class="book">小王子</p>](嵌套第一层满足)
『 CSS 选择器 在 BeautifulSoup 中的使用 』
BeautifulSoup 对象 有一个 select() 方法,我们将 CSS 选择器 传进去即可直接找到我们需要的元素
上面查找在 class="item" 的 div 标签 里的 a 标签 的代码就可以这样写:
items = soup.select('div.item a')
for i in items:
name = i.text
link = i['href']
print(name, link)
# 输出:
# 追风筝的人 https://book.douban.com/subject/1770782/
# 解忧杂货店 https://book.douban.com/subject/25862578/
# 小王子 https://book.douban.com/subject/1084336/
[/b]
『 实 操 代 码 』
基础版soup解析 再逐层寻找
[b]import requests
from bs4 import BeautifulSoup
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
res = requests.get('https://book.douban.com/top250', headers=headers)
soup = BeautifulSoup(res.text, 'html.parser')
# 找到所有 class='pl2' 的 div 标签
items = soup.find_all('div', class_='pl2')
for i in items:
# 找到 class='pl2' 的 div 标签里的 a 标签
tag = i.find('a')
# 获取标签文本内容
name = tag.text
# 获取标签 href 属性的值
link = tag['href']
print(name, link)
name = ''.join(tag.text.split()) 去
#掉多余的空格和换行符使输出结果整洁
[b]改进版 获取数据更加直接[/b]
import requests
from bs4 import BeautifulSoup
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
res = requests.get('https://book.douban.com/top250', headers=headers)
soup = BeautifulSoup(res.text, 'html.parser')
items = soup.find_all('div', class_='pl2')
for i in items:
tag = i.find('a')
# 提取书名
name = tag['title']
# 提取链接
link = tag['href']
print(name, link)
[b]利用css 选择器 简化代码[/b]
import requests
from bs4 import BeautifulSoup
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}
res = requests.get('https://book.douban.com/top250', headers=headers)
soup = BeautifulSoup(res.text, 'html.parser')
items = soup.select('div.pl2 a')
for i in items:
# 提取书名
name = i['title']
# 提取链接
link = i['href']
print(name, link)
[/b]
|
|