网络爬虫之XPath、Beautiful Soup、PyQuery的使用

网络爬虫解析库的引入

  • 之前爬取网页信息是基于re正则,比较繁琐,出错率较高
  • 爬取信息大多基于html结构的web页面, 网页节点较多,各种层级关系。
  • 使用xpath解析器、BeautifulSoup解析器、pyquery css解析器抽取结构化数据,使用正则表达式抽取非结构化数据

常见的Python解析库

待提取HTML代码——供三个解析库使用(存在my.html中):

<!DOCTYPE html>
<html>
<head>
    <title>我的网页</title>
</head>
<body>
    <h3 id="hid">我的常用链接</h3>
    <ul>
        <li class="item-0"><a class="aa" href="http://www.baidu.com">百度</a></li>
        <li class="item-1 shop"><a href="http://www.jd.com">京东</a></li>
        <li class="item-2"><a href="http://www.sohu.com">搜狐</a></li>
        <li class="item-3"><a href="http://www.sina.com">新浪</a></li>
        <li class="item-4 shop"><a href="http://www.taobao.com">淘宝</a></li>
    </ul>

</body>
</html>

(一)、关于 XPath 的使用

一、xpath前言

  • XPath(XML Path Language)是一门在XML文档中查找信息的语言。
  • XPath 可用来在XML文档中对元素和属性进行遍历。
  • XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。
    • 注:XQuery 是用于 XML 数据查询的语言(类似SQL查询数据库中的数据)
    • 注:XPointer 由统一资源定位地址(URL)中#号之后的描述组成,类似于HTML中的锚点链接.
  • XPath 术语
    • XPath 节点——七种类型:在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。
    • 节点关系:父、子、同胞、先辈、后代。
python中简易使用XPath流程
 -: pip install lxml #安装 lxml 库。
 -: from lxml import etree
 -: Selector = etree.HTML(网页源代码)	#得到一个`lxml.etree._Element`对象
 -: Selector.xpath(一段神奇的符号)

二、xpath详细使用:

1、初始化工作(读取HTML文件,解析文档返回节点对象)

语法:html = etree.HTML(网页源代码) #得到一个lxml.etree._Element对象

# 导入模块
from lxml import etree

# 读取html文件信息(在真实代码中是爬取的网页信息)
f = open("./my.html",'r',encoding="utf-8")
content = f.read()
f.close()

# 解析HTML文档,返回根节点对象
html = etree.HTML(content)
#print(html)  		# <Element html at 0x103534c88>
print(html.xpath("."))	#[<Element html at 0x103534c88>]
#print(type(html))	#<class 'lxml.etree._Element'>
2、假如原网页标签不完整使用 “tostring()” 来补齐
html1 = etree.tostring(html).decode("utf-8")
html = etree.HTML(html1)	#就得到正常的根节点对象了
3、获取指定节点对象

语法:html.xpath("")
参数:传入"/"、"//"等节点规则获取指定节点对象列表(默认从根节点开始匹配节点)。
注意:XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
补充知识:XPath选取节点规则

表达式描述
nodename选取此节点的所有子节点。
/从当前节点选取直接子节点
/child::从当前节点选取直接子节点(效果和“/”是一致的)
//从匹配选择的当前节点选择所有子孙节点,而不考虑它们的位置
.选取当前节点。
..选取当前节点的父节点。
@选取属性。
*通配符,表示:所有
#result = html.xpath("/*")	#只得到根节点
result = html.xpath("//*")	#获取所有节点对象列表
4、获取子节点、子孙节点

子节点:"/*""/child::*"
子孙节点:"/descendant::*","//*"

result = html.xpath("//li") # 获取所有li节点
result = html.xpath("//li/*") # 获取所有li节点下的所有直接子节点
result1 = html.xpath("//li/child::*")	#获取所有li节点下的所有直接子节点
result = html.xpath("//ul//*") # 获取所有ul下所有a子孙节点)
result = html.xpath("//li/child::a[@href='http://www.sohu.com']") #获取li子节点中属性href值的a节点
result = html.xpath("//body/descendant::a") # 获取body中的所有子孙节点a
5、获取祖先节点、父节点

父节点:"/..""/parent::"
祖先节点:"/ancestor:: "

result = html.xpath("//a/ancestor::*")	# “*”代表所有;所有a标签的父标签li:5个,以及所有祖先节点标签3个(ul、body、html)
result = html.xpath("//li[1]/a/ancestor::ul")	#返回第一个li标签下的a标签的祖先标签ul标签
result1 = html.xpath("//a/parent::*")	#获取所有a节点的父节点
result2 = html.xpath("//a/..") #获取所有a节点的父节点
#print(result)
6、按序选择

语法:html.xpath("//li[index]")
说明:使用 “[index]” 选择指定顺序位置的节点,index从1开始

result = html.xpath("//li[1]/a/text()") # 获取每组li中的第一个li节点里面的a的文本
result = html.xpath("//li[last()]/a/text()") # 获取每组li中最后一个li节点里面的a的文本
result = html.xpath("//li[position()<3]/a/text()") # 获取每组li中前两个li节点里面的a的文本
result = html.xpath("//li[last()-2]/a/text()") # 获取每组li中倒数第三个li节点里面的a的文本
print(result) 
result = html.xpath("//li[3]") #获取li中的第三个节点    
result = html.xpath("//li[3]/following::li") #获取第三个li节点之后所有li节点
result = html.xpath("//li[3]/following-sibling::*") #获取第三个li节点之后所有同级li节点
7、获取文本内容(该节点标签中需要含有文本值才会返回有效值)

语法:三种写法

  1. html.xpath("//li/a/text()")
  2. html.xpath("//li/a")[0].xpath("text()")
  3. html.xpath("//li/a")[0].text
    # 7.1、方法一:("/text()"),得到的是文本列表
    result = html.xpath("//li/a/text()") #获取所有li下所有直接子a节点内的文本内容
    print(result) #['百度', '京东', '搜狐', '新浪', '淘宝']
    
    #注意:方法二和方法三都是在返回节点列表的基础上进行操作,所以要对节点列表遍历或者使用索引取值得到目标节点
    
    # 7.2、方法二("xpath('text()')"),得到的是列表
    result = html.xpath("//li/a")	#返回a标签节点对象列表
    for i in result:
    	print(i.xpath("text()"))	#遍历输出每个a标签文本内容,列表格式:['百度']['京东']['搜狐']
    	print(i.xpath("string()"))	#遍历输出每个a标签文本内容,字符串格式: 百度 京东 搜狐
    
    # 7.3、获取文本内容方法三(".text"),直接得字符串内容
    result = html.xpath("//li/a")	#返回节点对象列表
    result1 = result[0].text	#获取第一个a标签文本内容
    
8、获取节点属性值,原理和获取文本值一样

语法:三种写法

  1. html.xpath("//li/a/@属性名")
  2. html.xpath("//li/a")[0].xpath("/@属性名")
  3. html.xpath("//li/a")[0].attrib
    # 8.1、方法一:("/@属性名";"/attribute::属性名"),得到的是列表
    result = html.xpath("//li/a/@href") #获取所有li下所有直接子a节点的href属性值
    print(result) #
    ['http://www.baidu.com', 'http://www.jd.com', 'http://www.sohu.com', 'http://www.sina.com', 'http://www.taobao.com']
    result = html.xpath("//li[1]/a/@*") 	 # 获取第一个li中a节点的所有属性值
    result = html.xpath("//li[1]/a/attribute::*") 	# 获取第一个li中a节点的所有属性值
    
    #注意:方法二和方法三都是在返回节点列表的基础上进行操作,所以要对节点列表遍历或者使用索引取值得到目标节点
    
    # 8.2、方法二("xpath('@属性名')";"xpath('/attribute::属性名')"),得到的是列表
    result = html.xpath("//li/a")	#返回节点对象列表
    print(result[0].xpath("@href"))	#获取第一个a标签href属性值列表
    #等价于:
    print(result[0].xpath("attribute::href"))
    
    # 8.3、方法三、使用“attrib”获取节点属性名和属性值,返回字典
    result = html.xpath("//li/a")	#返回节点对象列表
    result1 = result[0].attrib 	#获取第一个a标签属性名及属性值
    print(result1)	#{'href': 'http://www.jd.com'}
    
9、使用@来进行属性过滤选择

语法:html.xpath("//li/a[@class],返回指定属性的节点对象列表

result = html.xpath("//li/a[@class]/text()") #获取所有li下所有直接含有class属性子a节点内的文本内容
print(result) #['百度', '搜狐', '新浪']

#获取所有li下所有直接含有class属性值为aa的子a节点内的文本内容
result = html.xpath("//li/a[@class='aa']/text()") 
print(result) #['搜狐', '新浪']

#针对class属性有多个值的情况,使用“contains”来获取class属性值中含有shop的li节点下所有直接a子节点内的文本内容
result = html.xpath("//li[contains(@class,'shop')]/a/text()") 
print(result) #['搜狐', '新浪']
10、HTML元素的属性、方法
'''
HTML元素的属性(该节点对象需要含有标签、文本值才能返回有效值)
    tag:元素标签名
    text:标签中间的文本
HTML元素的方法:
	该节点对象需要有子节点:
    find()    查找一个匹配的元素
    findall() 查找所有匹配的元素
    
    get(key, default=None) 获取指定属性值
    items()获取元素属性,作为序列返回
    keys()获取属性名称列表
    values()将元素属性值作为字符串序列
'''
# 节点对象方法:
result = html.xpath("//ul/li")	#返回li节点对象列表
for v in result:
	print(v.find("a"))		#查找子节点中是a标签的节点对象
	print(v.findall("a"))	#因为这里每一个li标签下只有一个a标签,所以find和findall在此得到结果看起来一样。
	print(v.get("class"), default=None)	#查询li节点对象的class属性值,没有就返回None
	print(v.items())	#获取元素属性,作为序列返回:[('class', 'item-0')]
	print(v.attrib)		#获取元素属性,返回字典:{'class': 'item-0'}
	print(v.keys())	#获取属性名称列表:['class']
	print(v.values())	#将元素属性值作为字符串序列:['item-0']

(二)、关于 Beautiful Soup 的使用

一、前言

1、安装相关库

注意:Beautiful Soup是一个依赖于lxml的解析库,所以在安装之前要先确保lxml库已安装。

 pip3 install lxml
 pip3 install beautifulsoup4
2、简介

作用: BeautifulSoup是Python的一个HTML或XML解析库,最主要的功能就是从网页爬取我们需要的数据。
作用原理: BeautifulSoup将html解析为对象进行处理,全部页面转变为字典或者数组,相对于正则表达式的方式,可以大大简化处理过程。
Beautiful Soup3 目前已经停止开发,我们推荐在现在的项目中使用Beautiful Soup4。
官方文档
中文文档

3、主要的解析器的优缺点:
解析器使用方法(第二个参数是解析器)优势劣势
Python标准库BeautifulSoup(markup, “html.parser”)Python的内置标准库,执行速度适中,文档容错能力强Python 2.7.3 or 3.2.2前的版本中文档容错能力差
lxml HTML 解析器BeautifulSoup(markup, “lxml”)速度快 文档容错能力强需要安装C语言库
lxml XML 解析器BeautifulSoup(markup, [“lxml-xml”]);BeautifulSoup(markup, “xml”)速度快 唯一支持XML的解析器需要安装C语言库
html5libBeautifulSoup(markup, “html5lib”)最好的容错性,以浏览器的方式解析文档,生成HTML5格式的文档速度慢、不依赖外部扩展

补充:lxml解析器有解析html和xml的功能,而且速度快,容错能力强,比较推荐这个。

二、详细使用说明

1、初始化工作

语法:BeautifulSoup(content,"lxml")
参数:“content”传入网页源码文本;"lxml"是解析器
注意:此代码会自动格式化源码:补齐不完整代码等

#导入模块
from bs4 import BeautifulSoup

#读取HTML文件信息
with open("./my.html","r",encoding="utf-8") as f1:
	content = f1.read()

#实例化HTML文档解析对象,创建解析器,并对不完整、不规范的HTML文本内容进行缩进格式化(自动更正格式)(补全、对齐)
soup = BeautifulSoup(content,"lxml")	#使用"lxml"解析器

# 输出网页内容
#print(soup.prettify())
2.1、解析方式一:节点选择器

直接调用节点的名称就可以选择节点元素,再调用string属性就可以得到节点内的文本了,这种方式速度非常快。
语法:
soup.标签名——直接选择获取第一个指定标签对象;
soup.标签名.标签名——嵌套选择获取第一个指定标签对象;

① 直接选择元素:
print(soup.title) #<title>我的网页</title>
print(type(soup.title)) #<class 'bs4.element.Tag'>
print(soup.head) #获取整个head元素,及内部元素
print(soup.li) #获取第一个li元素(后面其他li不会获取)
# <li class="item-0"><a class="bb" href="http://www.baidu.com">百度</a></li>

② 嵌套选择:
print(soup.li.a) #获取网页中第一个li中的第一个a元素节点
#输出 <a class="bb" href="http://www.baidu.com">百度</a>

print(type(soup.body.h3))  ##获取body中的第一个h3元素的类型:<class 'bs4.element.Tag'>
print(soup.body.h3.string)  #获取body中的第一个h3中的文本内容: 我的常用链接
2.2、解析方式二:方法选择器

语法:

  1. find(name,attrs,recursive,text, limit,**kwargs )——传入属性或文本,返回所有符合条件的第一个元素节点对象
  2. find_all(name,attrs,recursive,text, limit,**kwargs )
    ——传入属性或文本,返回符合条件的所有元素节点对象,列表格式 。

参数说明:

  • name=“标签名”:搜索指定HTML标签名的节点;
  • attrs={"属性名":"属性值"}:搜索含有指定属性的节点;
  • keyword参数:所谓关键字参数其实就是通过一个html标签的idhref(这个主要指的是a标签的 )和title等;注意:class是python保留词,所以需要改成class_
  • sting/text="文本":搜索文档中的字符串内容.(接受 字符串 , 正则表达式 , 列表, True;)
  • limit=num:控制我们获取数据的数量,效果和SQL语句中的limit一样;
  • recursive参数:调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False;(理解不了:链接

补充重要知识:

  • 有此说法:soup.标签名其实是soup.find(‘标签名’)的简写,只返回第一个<bs.element.Tag>对象;但节点选择器方法选择器的find方法还是不一样的;节点选择器还可以进行嵌套选择;方法选择器还可以传入其他参数进行精确查询;
  • soup.find_all(‘节点’)返回所有节点的一个列表<bs.element.ResultSet>对象。(.find_all可以省略不写,效果也一样)。
# 1、通过name指定li值,获取所有li元素节点,返回列表
lilist = soup.find_all(name="li")

# 2、通过attrs指定属性来获取所有元素节点(使用关键字参数时某些关键字和python保留字冲突时(比如class等),便可以使用此方法解决)
lilist = soup.find_all(attrs={"class":"aa"})
lilist = soup.find_all(attrs={'href':'http://www.baidu.com'})

# 3、通过关键字参数来获取所有元素节点
lilist = soup.find_all(class_="aa") #同上(class属性中包含就可以了)
lilist = soup.find_all(class_="shop") #class属性值中包含shop的所有节点
lilist = soup.find_all(id="hid") #<h3 id="hid">我的常用链接</h3>
lilist = soup.find_all(href=re.compile("com"), id='link1')	#获取href属性含有“com”字符串,并且属性id='link1'的节点
lilist = soup.find_all(id=True)	#这里的true指的就是选中所有有id这个属性的标签;

# 4、通过文本内容获取
lilist = soup.find_all(text='百度') # 百度
lilist = soup.find_all(string='百度') # 百度
lilist = soup.find_all(string="百度")[0].parent	#获取文本内容是百度的节点的父节点:<a href="http://www.baidu.com">百度</a>
lilist = soup.find(string="百度").parent	#获取文本内容是百度的第一个节点的父节点:<a href="http://www.baidu.com">百度</a>
lilist = soup.find_all(text=re.compile('张')) # 张翠山 张无忌
for i in lilist:
    print(i)

# 5、通过limit参数控制我们获取数据的数量,
print(soup.find_all("a",limit=2))
#[<a href="http://www.baidu.com">百度</a>, <a href="http://www.jd.com">京东</a>]
2.3、解析方式三:CSS选择器

语法:soup.select(" ")——向select()方法中传入字符串参数(遵循CSS选择器规则),以列表形式返回所有结果;(可传入参数包括:标签名、类属性、id属性、一般属性等)

# 创建解析器
soup = BeautifulSoup(content,"lxml")

# 1、通过标签名获取节点,到下一级标签使用 空格 连接。
print(soup.select("ul li a")) #获取ul里面li下面的a元素节点

# 2、通过id属性获取节点
print(soup.select("#hid")) #获取id属性值为hid的元素节点

# 3、通过class类属性获取节点
print(soup.select("li.shop a")) #获取class属性为shop的li元素里面所有的a元素节点,标签与属性是通过.连接的 

# 4、通过【属性】查找,当然也适用于class、id等
soup.select("a[href]")	# 选择含有href属性的所有a标签节点

soup.select("a[href='http://example.com/lacie']")	# 选择含有属性href=http://example.com/lacie的所有a标签节点:[<a href="http://www.baidu.com">百度</a>]

soup.select('a[href^="http"]')	# 选择href属性以http开头的a标签

soup.select('a[href$="com"]')	# 选择a标签,其href属性以lacie结尾

soup.select('a[href*=".com"]')	# 选择a标签,其href属性包含.com
3、关联选择(获取子,父,兄弟节点对象):

我们在做选择的时候,难免有时候不能够一步就选到想要的节点元素。
需要先选中某一个节点元素,然后再基于这些继续向下选择(子,父,兄弟)。

  • 3.1、子或子孙节点
    # 以下获取的节点列表都可以使用for...in遍历
    print(soup.ul.contents) #获取第一个ul下面的所有直接子节点,返回列表
    print(soup.ul.children) #获取ul下面的所有直接子节点,返回一个:<list_iterator object at 0x110346a20>
    
    print(soup.ul.descendants) # 获取第一个ul下的所有子孙节点。
    for v in soup.ul.descendants:
        print("a:",v)
    
  • 3.2、 父节点、祖先节点
    print(soup.a.parent.name) #通过parent属性获取第一个a的父节点 li
    print(list(soup.a.parents)) # 获取所有祖先节点
    
  • 3.3、兄弟节点
    print(soup.li.next_siblings)    #获取指定li节点的所有后面的兄弟节点,返回:<generator object PageElement.next_siblings at 0x00000275AF55F900>
    print(soup.li.previous_siblings)#获取指定li节点的所有前面的兄弟节点
    #for v in soup.li.next_siblings:
    #    print(v)
    
4、提取节点对象信息

name:标签名、attrs:属性(返回字典格式)、sttrs[“属性名”]得到:属性值、string:文本内容,text:当前节点中所有节点内容

print(soup.a) #获取第一个a元素标签: <a class="bb" href="http://www.baidu.com">百度</a>
print(soup.a.name)    #获取标签名: a
print(soup.a.attrs)    #获取所有属性:{'class': ['bb'], 'href': 'http://www.baidu.com'}
print(soup.a.attrs['href']) #获取其中一个属性值:http://www.baidu.com
print(soup.a["href"])	#直接使用“["属性名"]”获取指定属性值:http://www.baidu.com
print(soup.a.string) # 获取元素标签中间的文本内容:百度
print(soup.a.text)	# 获取元素标签中间的文本内容:百度

注意:

  • .string可以返回当前节点中的内容,但是当前节点包含子节点时,.string不知道要获取哪一个节点中的内容,故返回空。
  • .text(或者.get_text())可以返回当前节点所包含的所有文本内容,包括当前节点的子孙节点。
    print(soup.ul.text)	#获取ul节点中(可以是子孙节点的)包含的所有文本内容:
    #输出:(字符串格式)
    百度
    京东
    搜狐
    新浪
    淘宝
    print(soup.ul.string)	#当前节点没有直接的文本内容,所以返回None。
    
5、补充
[s.extract() for s in soup('script')]	# 从html中排除某标签,此时soup中不再有script标签
[s.extract() for s in soup(['script','fram']	# 排除多个

print(soup.find_all("h3")[0].extract())	#返回h3标签节点,并在HTML排除该标签。(只对后续代码起作用,不改变原HTML内容,将此句代码删除以后该标签又出现)
print(soup)	#此时的html中就没有h3标签及其内部内容了(把上面那句“.extract()”删除后该标签又有了)

(三)、关于 PyQuery 的使用

一、 PyQuery介绍与安装

1、PyQuery简介
  • PyQuery库也是一个非常强大又灵活的网页解析库,如果你有前端开发经验的,都应该接触过jQuery,那么PyQuery就是你非常绝佳的选择。
  • PyQuery 是 Python 仿照 jQuery 的严格实现。语法与 jQuery 几乎完全相同,所以不用再去费心去记一些奇怪的方法了。
  • pyquery——可以直接解析 DOM 节点的结构,并通过 DOM 节点的一些属性快速进行内容提取。
  • 官网地址:http://pyquery.readthedocs.io/en/latest/
  • jQuery参考文档:可以用来查找选择器
2、PyQuery的安装
pip install lxml	#pyquery依赖于lxml解析库
pip install pyquery

二、 PyQuery的使用

1、初始化工作(会自动补齐不完整html标签)

在解析 HTML 文本的时候,首先需要将其初始化为一个 pyquery 对象。PyQuery的初始化方式有多种:传入字符串URL文件名,等等。

1.1、 字符串初始化
html = '''
<div>
    <ul>
         <li class="item-0">first item</li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-1 active"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
print(doc('li'))
1.2、URL 初始化(初始化的参数还可以传入网页的 URL,此时只需要指定参数为 url 即可)
from pyquery import PyQuery as pq
doc = pq(url='http://www.baidu.com',encoding="utf-8")
print(doc('title'))
1.2.0、注意:初始化URL时推荐先使用爬虫库(urllib、resquests)封装URL后再传递给pyquery(爬取数据和解析数据分开):
from pyquery import PyQuery as pq
import requests

res = requests.get('http://www.baidu.com')
res.encoding="utf-8"
doc = pq(res.text)
print(doc('title'))
3、文件初始化(传递一个本地的文件名,参数指定为 filename 即可)
from pyquery import PyQuery as pq
doc = pq(filename='demo.html')
print(doc('li'))
2、查找节点
2.1、直接查找节点名

语法:doc("节点名")——通过CSS选择器来获取目标内容(满足CSS语法)。

# 选取class为list的节点
items = doc('.list')

#关联选择符的使用
print(doc("ul li.shop a")) 
2.2、使用函数查找嵌套元素(等价于:doc(""),嵌套元素用空格隔开
  • 语法:doc("节点名").find("节点名")
  • 注意:find 的查找范围是节点的所有子孙节点,而如果我们只想查找子节点,那可以用 children 方法。
    #查找 <ul> 内部的 a 元素
    print(doc('ul').find('a')) 
    print(doc("ul a"))
    
    #查找 <ul> 内的直接子 a 子标签
    print(doc('ul').children('a')) 
    print(doc("ul > a"))
    
2.3、根据 class、id 筛选指定元素。
  • 语法:doc("节点名").filter()
    #查找 class 为 item-1 的 li 元素()
    print(doc('li').filter('.item-1'))
    print(doc("li.item-1"))
    
    #查找 id 为 item-0 的 li元素
    print(doc('li').filter('#item-0'))
    print(doc("li#item-0")
    
3、根据索引号获取指定元素(index 从 0 开始)
  • 语法:doc("节点名").eq(index)
    print (d('p').eq(1).text())
    
4、遍历
  • pyquery的选择结果可能是单个节点(可以直接打印输出,也可以直接转成字符串);
    也可能是多个节点,类型都是PyQuery类型,多个结果时所以需要遍历来获取。
  • 这时候需要调用 items() 方法;调用 items 方法后,会得到一个生成器,遍历一下,就可以逐个得到 单节点对象了。
  • 语法:doc("节点名").items()
lis = doc('li').items()
for li in lis:
    print(li)
5、获取信息、修改信息

提取到节点之后,我们的最终目的当然是提取节点所包含的信息了。比较重要的信息有两类,一是获取属性,二是获取文本。

5.1、获取、修改文本信息

语法:

  • doc("节点名").html()——用html()获取HTML文本;
  • doc("节点名").text()——用text()来获取文本(只返回纯文字内容)。

注意:当选中的结果是多个节点时

  • html 方法返回的是第 1 个目标节点的内部 HTML 文本;(如果想要得到的结果是多个节点,并且需要获取每个节点的内部 HTML 文本,则需要遍历每个节点。)
  • text 则返回了所有的 目标节点内部的纯文本,中间用一个空格分割开,即将所有节点获取文本之后合并成一个字符串返回。

修改信息:使用 text 和 html 方法时如果不传参数,则是获取节点内纯文本和 HTML 文本,如果传入参数,则进行赋值修改文本值

print(doc("a").html())	#只返回第一个a标签内容:“百度”
print(doc("a").html("阿里"))	#会将所有a标签内容修改为“阿里”
输出:
'''
<li class="item-0" id="aa">阿里</li>
<li class="item-1 shop">阿里</li>
<li class="item-2">阿里</li>
<li class="item-3">阿里</li>
<li class="item-4 shop">阿里</li>
'''
#获取相应的文本内容
print (doc('a').text())	#返回所有a标签文本内容:百度 京东 搜狐 新浪 淘宝
print (doc('a').text("阿里"))	#会将所有a标签内容修改为“阿里”
输出:
'''
<li class="item-0" id="aa">阿里</li>
<li class="item-1 shop">阿里</li>
<li class="item-2">阿里</li>
<li class="item-3">阿里</li>
<li class="item-4 shop">阿里</li>
'''
5.2:获取、修改属性值
  • 语法:doc("节点名").attr(“属性名”)或者doc("节点名").attr.属性名”
  • 修改属性:doc("节点名").attr(“属性名”,“新属性值”)
  • 注意:当返回结果包含多个节点时,调用 attr 方法,只会得到第 1 个节点的属性。如果想获取所有的目标节点的属性,就要用到遍历
    #获取 <li> 标签的属性 id
    print(doc('li').attr('id'))	#item-0
    print(doc('li').attr.id)	#item-0
    
    #修改 <a> 标签的 class 属性为 new
    print(d('a').attr('class','new'))	#<a class="new">百度</a>
    
6、获取祖先节点、子孙节点:
# 子节点
lis = items.children()
# class为active的子节点
lis = items.children('.active')
# 父节点
lis = items.parent()
# 祖先节点,如果需要筛选,也可以传入CSS选择器
container = items.parents()
# 兄弟节点
lis = ltems.siblings()
7、节点操作

pyquery 提供了一系列方法来对节点进行动态修改,比如为某个节点添加一个 class,移除某个节点等,这些操作有时会为提取信息带来极大的便利。

li = doc('item-0.active')
# 删除class属性
li.removeClass('active')
# 添加class属性
li.addClass('active')
# 改变属性
li.attr('name', 'link')
# 改变文本内容
li.text(str)
# 改变html
li.html(html)
# 移除指定节点
li.remove()
li.find("a").remove()	#移除子节点a标签
8、伪类选择器
# 第一个li节点
li = doc('li:first-hild')
# 最后一个li节点
li = doc('li:last-child')
# 第二个li节点
li = doc('li:nth-child(2)')
# 第三个li之后的li节点
li = doc('li:gt(2)')
# 偶数位置的li节点
li = doc('li:nth-child(2n)')
# 包含second文本的li节点
li = doc('li:contains(second)')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值