2024 高级爬虫笔记(一)bs4和xpath使用教程
一、数据解析利器——beautifulsoup
1.1 安装
pip install beautifulsoup4
1.2 安装解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。
安装方式:python pip install lxml
1.3 快速使用:
# 导入bs
from bs4 import BeautifulSoup
# 初始化bs对象,html_doc为解析文本,'lxml'为解析器
soup = BeautifulSoup(html_doc, 'lxml')
# 对html进行美化
print(soup.prettify())
# 获取第一个title标签
soup.title
soup.title.name # 获取标签名称
soup.title.string # 获取标签title内的内容
soup.title.parent # 获取父级标签
soup.title.parent.name # 获取父级标签名称
soup.p # 获取第一个p标签
soup.p['class'] # 获取p的class属性值
soup.a # 获取第一个a标签
soup.find_all('a') # 获取所有a标签
soup.find(id="link3") # 获取id为link3的标签
1.4 获取标签内容相关方法:
1.4.1 .content、.strings和.text
1.4.1.1 相同点与区别:
.content、.strings和.text方法都可以返回标签内所有的文本内容,区别在于.content返回列表,.strings返回生成器,.text返回字符串
1.4.1.2 使用示例:
# 获取第一个head标签
head_tag = soup.head
# 获取head标签下所有子标签的内容
head_tag.contents
head_tag.strings
head_tag.text
for string in soup.strings:
print(repr(string))
# 获取第一个子标签的内容
title_tag = head_tag.contents[0]
1.4.2 .string
1.4.2.1 使用场景:
如果标签里面没有标签了,那么 .string 就会返回标签里面的内容。
如果标签里面只有唯一的一个标签了,那么 .string 也会返回最里面的内容。
如果标签里面包含了多个子标签,.string 的输出结果是 None
1.4.3 .stripped_strings
1.4.3.1 使用场景:
输出的字符串中可能包含了很多空格或空行,使用 `.stripped_strings`可以去除多余空白内容
for string in soup.stripped_strings:
print(repr(string))
1.5 搜索相关方法:
1.5.1 find_all方法
1.5.1.1 使用场景及示例:
`find_all()` 方法搜索当前标签的所有子标签,并判断是否符合过滤器的条件
# 搜索所有title标签
soup.find_all("title")
# 搜索所有class为title的p标签
soup.find_all("p", "title")
# 搜索所有a标签
soup.find_all("a")
# 搜索所有id为link2的标签
soup.find_all(id="link2")
# 使用正则匹配
import re
# 模糊查询所有文本内容包含sisters的标签
soup.find_all(string=re.compile("sisters"))
1.5.1.2 传入参数解析:
1、name参数解析:
`name` 参数可以查找所有名字为 `name` 的标签,字符串对象会被自动忽略掉
`name` 参数的值可以是字符串,正则表达式,列表,方法或是 `True`
传入字符串:
最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容
下面的例子用于查找文档中所有的<b>标签:
soup.find_all('b')
传入正则表达式:
如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 `match()` 来匹配内容.
下面例子中找出所有以b开头的标签,这表示\<body>和\<b>标签都应该被找到:
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
传列表:
如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回
下面代码找到文档中所有\<a>标签和\<b>标签:
soup.find_all(["a", "b"])
2、keyword 参数解析:
如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索
比如如果包含一个名字为 `id` 的参数,Beautiful Soup会搜索每个标签的”id”属性:
soup.find_all(id='link2')
其他示例:
import re
# 超链接包含elsie标签
print(soup.find_all(href=re.compile("elsie")))
# 以The作为开头的字符串
print(soup.find_all(text=re.compile("^The")))
使用多个指定名字的参数可以同时过滤tag的多个属性:
soup.find_all(href=re.compile("elsie"), id='link1')
如果我们想用 class 过滤,不过 class 是 python 的关键词,需要加个下划线:
print(soup.find_all("a", class_="sister"))
3、attrs 参数解析:
通过`attrs` 参数定义一个字典参数来搜索包含特殊属性的tag:
data_soup.find_all(attrs={"data-foo": "value"})
注意:如何查看条件id和class同时存在时的写法
print(soup.find_all('b', class_="story", id="x"))
print(soup.find_all('b', attrs={"class":"story", "id":"x"}))
4、text 参数解析:
通过 `text` 参数可以搜搜文档中的字符串内容:
# 只要包含Dormouse就可以
print(soup.find_all(text=re.compile("Dormouse")))
5、limit 参数解析:
`find_all()` 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢
如果我们不需要全部结果,可以使用 `limit` 参数限制返回结果的数量:
print(soup.find_all("a",limit=2))
1.6 css选择器
1、通过标签名查找
print(soup.select("title"))
print(soup.select("b"))
2、通过类名查找
print(soup.select(".sister"))
3、通过id名查找
print(soup.select("#link1"))
4、组合查找
组合查找和写 class 文件时,标签名与类名、id名进行的组合原理是一样的
例如查找 p 标签中,id 等于 link1的内容,二者需要用空格分开
print(soup.select("p #link2"))
5、直接子标签查找
print(soup.select("p > #link2"))
6、查找既有class也有id选择器的标签
a_string = soup.select(".story#test")
7、查找有多个class选择器的标签
a_string = soup.select(".story.test")
8、查找有多个class选择器和一个id选择器的标签
a_string = soup.select(".story.test#book")
9、属性查找
查找时还可以加入属性元素,属性需要用中括号括起来
注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。
print(soup.select("a[href='http://example.com/tillie']"))
10、select 方法返回的结果都是列表形式,可以遍历形式输出,然后用 get_text() 方法来获取它的内容:
for title in soup.select('a'):
print (title.get_text())
二、数据解析利器——xpath
2.1、xpath安装 pip install lxml
2.2、快速使用
# 解析网络的html字符串
html_tree = etree.HTML(html字符串)
html_tree.xpath()
使用xpath路径查询信息,返回一个列表
2.3、xpath语法
2.3.1、路径表达式:
| / | 从根节点选取。 |
| // | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
| ./ | 当前节点再次进行xpath |
| @ | 选取属性。 |
在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:
| /html | 选取根元素。 |
| //li | 选取所有li 子元素,而不管它们在文档中的位置。 |
| //ul//li | 选择属于 ul元素的后代的所有 li元素,而不管它们位于 ul之下的什么位置。 |
| 节点对象.xpath('./div') | 选择当前节点对象里面的第一个div节点 |
| //@href | 选取名为 href 的所有属性。 |
2.3.2、谓语(Predicates):
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:
| 路径表达式 | 结果 |
| /ul/li[1] | 选取属于 ul子元素的第一个 li元素。 |
| /ul/li[last()] | 选取属于 ul子元素的最后一个 li元素。 |
| /ul/li[last()-1] | 选取属于 ul子元素的倒数第二个 li元素。 |
| //ul/li[position()<3] | 选取最前面的两个属于 ul元素的子元素的 li元素。 |
| //a[@title] | 选取所有拥有名为 title的属性的 a元素。 |
| //a[@title='xx'] | 选取所有 a元素,且这些元素拥有值为 xx的 title属性。 |
| //a[@title>10] `> < >= <= !=` | 选取 a元素的所有 title元素,且其中的 title元素的值须大于 10。 |
| /bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
2.3.3、选取未知节点:
XPath 通配符可用来选取未知的 XML 元素。
| 通配符 | 描述 |
| * | 匹配任何元素节点。 一般用于浏览器copy xpath会出现 |
| @* | 匹配任何属性节点。 |
| node() | 匹配任何类型的节点。 |
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 |
| /ul/* | 选取 ul元素的所有子元素。 |
| //* | 选取文档中的所有元素。 |
| //title[@*] | 选取所有带有属性的 title 元素。 |
| //node() | 获取所有节点 |
2.3.4、选取若干路径:
通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
| 路径表达式 | 结果 |
| //book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
| //title | //price | 选取文档中的所有 title 和 price 元素。 |
| /bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
2.3.5、逻辑运算
查找所有id属性等于head并且class属性等于s_down的div标签
//div[@id="head" and @class="s_down"]
选取文档中的所有 title 和 price 元素。
//title | //price
注意: “|”两边必须是完整的xpath路径
2.3.6、属性查询
查找所有包含id属性的div节点
//div[@id]
查找所有id属性等于maincontent的div标签
//div[@id="maincontent"]
查找所有的class属性
//@class
获取li标签中name为xx的里面的文本内容
//li[@name="xx"]//text()
2.3.7、查询相关
查询所有id属性中包含he的div标签
//div[contains(@id, "he")]
查询所有id属性中包以he开头的div标签
//div[starts-with(@id, "he")]
查找所有div标签下的直接子节点h1的内容
//div/h1/text()
2.3.8、获取节点内容转换成字符串
c = tree.xpath('//li/a')[0]
result=etree.tostring(c, encoding='utf-8')
print(result.decode('UTF-8'))
原文地址:https://blog.csdn.net/qq_40652101/article/details/142490135
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!