鱼C论坛

 找回密码
 立即注册
查看: 4901|回复: 11

[学习笔记] 爬虫学习笔记4-----数据提取与解析 New!

[复制链接]
发表于 2021-2-16 21:39:27 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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]




                               
登录/注册后可看大图


本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-16 22:48:51 | 显示全部楼层

回帖奖励 +1 鱼币

来捧个场,加油!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-18 10:57:49 | 显示全部楼层
学习了,虽然对新手来说还有些难度,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-2-18 12:48:57 | 显示全部楼层

回帖奖励 +1 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-18 16:33:33 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-19 07:40:58 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-19 07:41:44 | 显示全部楼层

回帖奖励 +1 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-5-28 00:08:50 | 显示全部楼层
very nice. thanks so much!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-11-24 21:46:35 | 显示全部楼层
刚好最近学到这里,感谢&#128031;友分享
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-3 16:54:24 | 显示全部楼层
讲解很仔细!感谢楼主!希望能继续多出几个案例演示一下,从浅入深。希望能有进阶教程,再次感谢!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-13 17:28:51 | 显示全部楼层
非常棒! 感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-12-13 20:43:28 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-24 08:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表