python常用的爬虫库、包含bs4_python爬虫常用库之BeautifulSoup详解

经过了前面几篇文章的学习,估计你已经会爬不少中小型网站了。但是有人说,前面的正则很难唉,学不好。正则的确很难,有人说过:如果一个问题用正则解决,那么就变成了两个问题。所以说学不会是很正常的,不怕,除了正则,我们还可以用另外一个强大的库来解析html。所以,今天的主题就是来学习这个强大的库--BeautifulSoup,不过正则还是需要多多练习下的。

因为是第三方库所以我们需要下载,在命令行敲下以下代码进行下载

pip install beautifulsoup4

安装第三方解析库

pip install lxml

pip install html5lib

如果不知道有什么用请往下看

1.相关解析库的介绍

a85acacbfff018c3f8830aec2f6e2028.png

这里官方推荐解析库为lxml,因为它的效率高。下面都是用lxml解析库来进行解析的。

2.详细语法介绍

本文是进行解析豆瓣图书首页https://book.douban.com/

1)创建bs对象

from bs4 import BeautifulSoup

import requests

response = requests.get('https://book.douban.com/').text

# print(response)

# 创建bs对象

soup = BeautifulSoup(response, 'lxml')  # 使用到了lxml解析库

2)获取相关标签

标签:

豆瓣

上面的a就是一个标签名字,最简单的就是这样,可以简单理解为<>里面的第一个单词就是标签名

# 获取标签

print(soup.li)  # 这个只是获取第一个li标签

# 结果

豆瓣

3)获取标签的名字和内容

标签的名字和内容:

豆瓣

如上面所说,a就是标签名字,而两个标签之中所夹杂的内容就是我们所说的内容,如上,豆瓣就是该标签的内容

# 获取标签名字

print(soup.li.name)

# 获取标签内容

print(soup.li.string)  # 这个只能是这个标签没有子标签才能正确获取,否则会返回None

# 结果

li

None

由于这个li标签里面还有个子标签,所以它的文本内容为None

下面这个就可以获取它的文本内容

# 获取标签内的标签

print(soup.li.a)

print(soup.li.a.string)  # 这个标签没有子标签所以可以获取到内容

# 结果

豆瓣

豆瓣

4)获取标签属性,有两种方法

标签属性:

豆瓣

可以简单理解为属性就是在标签名字旁边而且在前一个<>符号里面的,还有是有等号来进行体现的。所以上面的href就是标签属性名字,等号右边的就是属性的值,上面的值是个网址

# 获取标签属性

print(soup.li.a['href'])  # 第一种

print(soup.li.a.attrs['href'])  # 第二种

# 结果

https://www.douban.com

https://www.douban.com

5)获取标签内的子标签

子标签:

豆瓣

比如我们现在获取的li标签,所以a标签就是li标签的子标签

# 获取标签内的标签

print(soup.li.a)

# 结果

豆瓣

6)获取所有子节点

子节点:这个和子标签是差不多的,只不过这里是获取一个标签下的所有子标签,上面的只是获取最接近该标签的子标签

# 获取子节点

print(soup.div.contents)  # 返回一个列表 第一种方法

for n, tag in enumerate(soup.div.contents):

print(n, tag)

# 结果

['\n',

...

0

1

...

这个是获取div下的所有子节点,.content就是获取子节点的属性

7)第二种方法获取所有子节点

# 第二种方法

print(soup.div.children)  # 返回的是一个迭代器

for n, tag in enumerate(soup.div.children):

print(n, tag)

这个是用.children获取所有的子节点,这个方法返回的是一个迭代器

8)获取标签的子孙节点,就是所有后代

子孙节点:

  • 豆瓣

从上面知道,li标签是ul标签的子标签,a标签是li标签的子标签,若此时我们获取的是ul标签,所以li标签和a标签都是ul标签的子孙节点

# 获取标签的子孙节点

print(soup.div.descendants)  # 返回的是一个迭代器

for n, tag in enumerate(soup.div.descendants):

print(n, tag)

# 结果

...

0

1

...

这里用到了.descendants属性,获取的是div标签的子孙节点,而且返回结果是一个迭代器

9)获取父节点和所有祖先节点

既然有了子节点和子孙节点,反过来也是有父节点和祖先节点的,所以都很容易理解的

# 获取父节点

print(soup.li.parent)  # 返回整个父节点

# 获取祖先节点

print(soup.li.parents)  # 返回的是一个生成器

for n, tag in enumerate(soup.li.parents):

print(n, tag)

.parent属性是获取父节点,返回来的是整个父节点,里面包含该子节点。.parents就是获取所有的祖先节点,返回的是一个生成器

10)获取兄弟节点

兄弟节点:

  • 豆瓣1

  • 豆瓣2

  • 豆瓣3

比如上面的html代码,里面的li标签都是ul标签的子节点,而li标签都是处于同级的,所以上面的li标签都是各自的兄弟。这就是兄弟节点。

# 获取兄弟节点

print(soup.li.next_siblings)  # 获取该标签的所有同级节点,不包括本身  返回的是一个生成器

for x in soup.li.next_siblings:

print(x)

# 结果

读书

...

.next_siblings属性是获取该标签的所有在他后面的兄弟节点,不包括他本身。同时返回结果也是一个迭代器

同理,既然有获取他的下一个所有兄弟标签,也有获取他前面的所有兄弟标签

soup.li.previous_siblings

如果只是获取一个即可,可以选择把上面的属性后面的s字母去掉即可,如下

soup.li.previous_sibling  # 获取前一个兄弟节点

soup.li.next_sibling  # 获取后一个兄弟节点

3.bs库的更高级的用法

在前面我们可以获取标签的名字、属性、内容和所有的祖孙标签。但是当我们需要获取任意一个指定属性的标签还是有点困难的,所以,此时有了下面这个方法:

soup.find_all( name , attrs , recursive , text , **kwargs )

name:需要获取的标签名

attrs:接收一个字典,为属性的键值,或者直接用关键字参数来替代也可以,下面

recursive:设置是否搜索直接子节点

text:对应的字符串内容

limit:设置搜索的数量

1)先使用name参数来进行搜索

# 先使用name参数

print(soup.find_all('li'))  # 返回一个列表,所有的li标签名字

# 结果

[

豆瓣

,

...

这里获取了所有标签名字为li的标签

2)使用name和attrs参数

# 使用name和attrs参数

print(soup.find_all('div', {'class': 'more-meta'}))  # 这个对上个进行了筛选,属性参数填的是一个字典类型的

# 结果

[

...

这里搜索了具有属性为class='more-meta'的div标签

3)根据关键字参数来搜索

# 对相关属性进行进行查找也可以这样

print(soup.find_all(class_='more-meta'))  # 使用关键字参数,因为class是python关键字,所以关键字参数时需要加多一个下划线来进行区别

# 结果

和上面的结果一样

...

这里注意,我们找的是class属性为more-meta的标签,用了关键字参数,但是python里面有class关键字,所以为了不使语法出错,所以需要在class加个下划线

其他参数的就不再介绍了,可以自行去官网查看

4)find()方法

此方法与find_all()方法一样,只不过这个方法只是查找一个标签而已,后者是查找所有符合条件的标签。

还有很多类似的方法,用法都差不多,就不再一一演示了,需要的可以去官网查看

5)select()方法

这个方法是使用css选择器来进行筛选标签的。

css选择器:就是根据标签的名字,id和class属性来选择标签。

通过标签名:直接写该标签名,如li a  ,这个就是找li标签下的a标签

通过class属性:用. 符号加class属性值,如 .title .time 这个就是找class值为title下的class值为time的标签

通过id属性:用# 加id属性值来进行查找,如 #img #width这个就是找id值为img下的id值为width的标签

上面三者可以混合使用,如 ul .title #width

如果还不太会的话,可以直接在浏览器上按下f12来查看

9957883dc9ac864dd916b1b9ea3c70a8.png

位置在箭头所指的位置就是选择器的表达

代码如下

# 还可以用标签选择器来进行筛选元素, 返回的都是一个列表

print(soup.select('ul li div'))  # 这个是根据标签名进行筛选

print(soup.select('.info .title'))  # 这个是根据class来进行筛选

print(soup.select('#footer #icp'))  # 这个是根据id来进行筛选

# 上面的可以进行混合使用

print(soup.select('ul li .cover a img'))

这里的获取属性和文本内容

# 获取属性

for attr in soup.select('ul li .cover a img'):

# print(attr.attrs['alt'])

# 也可以这样

print(attr['alt'])

# 获取标签的内容

for tag in soup.select('li'):

print(tag.get_text())  # 里面可以包含子标签,会将子标签的内容连同输出

.get_tex()方法和前面的.string属性有点不一样哈,这里的他会获取该标签的所有文本内容,不管有没有子标签

写在最后

以上的这些都是个人在学习过程中做的一点笔记。还有点不足,如果有错误的话欢迎大佬指出哈。如果想要查看更多相关用法可以去官方文档查看:http://beautifulsoup.readthedocs.io/zh_CN/latest/

学习参考资料:https://edu.hellobi.com/course/157

如果这篇文章对你有用,点个赞,转个发如何?

还有,祝大家今天愚人节快乐

c2fd57eb06b3146fda352dfe9469fbbc.png

日常学python

代码不止bug,还有美和乐趣

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值