2020-10-29 Python爬虫 第二章解析库学习,第一节,学习lxml解析库

第一节,学习lxml解析库

在前面一章中我们说了如何使用requests、ullib取获取网页源代码,这一章我们将说说如何通过解析库去获得我们想要获取的网页信息,而不是像前面那样整页输出。当然若是读者熟悉正则表达式,也能使用正则表达式去获得想要信息,但是正则表达式写起来很是繁琐,而且错误率很高,不到万不得已的时候建议不要使用正则表达式。毕竟python为我们提供了解析网页的强大工具lxml,BeautifulSoup,pyquery等库。这一章我们主要讲这三个库的深入学习,本章分为三个小节,每一节学习一个库。

 

前期熟语表达声明(需要说明的的是下面的html语言并不标准,只是纯粹为了说明下面代码中的熟语)

'''
<a href = "text1_a1.html">text1_a1</a>
称上面东西为标签a
称href为标签a的herf属性,对应属性值为"text1_a1.html"
称text1_a1为标签a的文本值

<body>
	<div class = "content">
		<ul>
			<li class = "text1">
				<a1 href = "text1_a.html">text1_a</a1>
				<a2 href = "text1_a1.html">text1_a1</a2>
				<a3 href = "text1_a2.html">text1_a2</a3>
				<p name = "text1_p">text3_p1
					<a href = "text1_a2.html">text1_p_a2</a>
					</p>
				<a4 href = "text1_a3.html">text1_a3</a4>
			</li></ul></div></body>
对于标签p,我们称他有兄弟标签a1,a2,a3,a4
对于标签p,我们称他有唯一父标签li
对于标签p,我们称他有祖先标签li,ul,div,body
对于标签li,我们称他有子标签a1,a2,a3,a4,p
对于标签ul,我们称他有子孙标签a1,a2,a3,a4,p,li,a
对于其他标签也可以同理推导
'''

lxml为python的第三方库,需要大家自行安装,安装完成后我们就可以结合xpath去解析网页。同样本人只是举一些自己写的html代码(并不规范),目的只是通过这些简单的html语言去熟悉及解析库的使用。我不会去罗列xpath的语法,若是读者想要看xpath总结可以前往http://cnblogs.com/lone5wolf/p/10905339.html ,里面很详细的说了xpath各种用法。我只是以案例形式去解说xpath,尽量把xpath的语言融入到代码中。且下面代码的每一个print都是互不相关的。使用xpath语言去匹配,读者需要秉持着匹配所有的想法(贪婪),且返回的结果均以列表形式返回,即便没有也返回空列表

每一个语法,我会以下面形式罗列出来

# xpath语言解释   输出结果

print(xp.xpath(xpath语言))

#注意事项

 

1、获取所有标签

这里主要熟悉//与/的差异,如何获取文本、属性包括/text()与//text()d的差异,以及如何获取文本、属性。

html ='''<html>
<head>解析库
	<li class = "text">
		<a href = "head_text2_a1.html">head_text2_a</a>
		<a href = "head_text2_a2.html">head_text2_a</a></li></head>
<body>
	<div class = "content">
		<ul>hello ul
			<li class = "text1">hello li
				<a href = "text1_a.html">text1_a</a>
				<a href = "text1_a1.html">text1_a1</a>
				<a href = "text1_a2.html">text1_a2</a>
				<p name = "text1_p">text3_p1
					<a href = "text1_a2.html">text1_p_a2</a></p>
				<a href = "text1_a3.html">text1_a3</a></li>
			<li class = "text2">
				<a href = "text2_a1.html">text2_a</a>
				<a href = "text2_a2.html">text2_a</a></li>
			<li class = "text3">
				<p name = "text3_p">text3_p1</p>
				<p name = "text3_p">text3_p2</p></li></ul></body></html>
'''
# //   从当前节点选取子孙节点
# /    从当前节点选取子节点
# *     任意标签
# @    选取属性
# 注意lxml库获取的属性、属性值、文本值、标签等都是以列表形式返回,若没有也返回空列表
from lxml.etree import HTML
#初始化
xp = HTML(html)
#返回所有li标签(其中li的父标签为任意)     结果:[<Element li at 0x2812c0befc8>, <Element li at 0x2812c0f7048>, <Element li at 0x2812c0f7088>, <Element li at 0x2812c0f70c8>]
print(xp.xpath('//li'))
#返回所有的li标签(其中li的父标签为ul,且ul的父标签为任意)  结果:[<Element li at 0x1cf8959ffc8>, <Element li at 0x1cf895d7088>, <Element li at 0x1cf895d70c8>]
print(xp.xpath('//ul/li'))
# 上面的东西似乎看不出区别来,毕竟它是返回<Element li at 0x2812c0befc8>对象,
# 下面我们通过获取属性或者文本来区别

#获取属性
# 返回所有标签li的class属性值(其中li的父标签任意)  结果:['text', 'text1', 'text2', 'text3']
print(xp.xpath('//li/@class'))
# 返回所有li标签的class属性值('其中li的父标签为ul,ul的父标签为任意) 结果:['text1', 'text2', 'text3']
print(xp.xpath('//ul/li/@class'))

#获取文本
# 返回所有标签ul的文本值(ul的父标签为任意) 结果:['hello ul\n\t\t\t', '\n\t\t\t', '\n\t\t\t']
print(xp.xpath('//ul/text()'))
# 返回所有标签ul下的文本值(ul的父标签为任意)结果 :['hello ul\n\t\t\t', 'hello li\n\t\t\t\t', 'text1_a',
											# '\n\t\t\t\t', 'text1_a1', '\n\t\t\t\t', 'text1_a2', '\n\t\t\t\t', 'text3_p1\n\t\t\t\t\t',
											# 'text1_p_a2', '\n\t\t\t\t', 'text1_a3', '\n\t\t\t', '\n\t\t\t\t', 'text2_a', '\n\t\t\t\t',
											# 'text2_a', '\n\t\t\t', '\n\t\t\t\t', 'text3_p1', '\n\t\t\t\t', 'text3_p2']
print(xp.xpath('//ul//text()'))
# 可以看出'//ul/text()'     是返回当前标签的文本内容
# 可以看出'//ul//text()'  是返回当前标签下的所有文本内容
# 我们只需将上面的列表元素拼接起来,然后区属\n\t就可以了

#返回标签a的文本内容(其中a的父标签为li,li的父标签为任意)  结果:['head_text2_a', 'head_text2_a', 'text1_a', 'text1_a1', 'text1_a2', 'text1_a3', 'text2_a', 'text2_a']
print(xp.xpath('//li/a/text()'))
#返回标签a下所有文本内容(其中a的父标签为li,li的父标签为任意)  结果:['head_text2_a', 'head_text2_a', 'text1_a', 'text1_a1', 'text1_a2', 'text1_a3', 'text2_a', 'text2_a']
print(xp.xpath('//li/a//text()'))
#这里的两个都是一样的,主要是因为标签a下均没有子标签
#这也就说明当前标签下没有子孙标签,则/tetx()与//text()一样


# 返回所有的标签li(其中li的父标签为ul的,ul没有父标签)  结果 :[]
print(xp.xpath('/ul/li'))
#返回所有标签li的class属性值(其中li的父标签为ul,ul的父标签为div,...,html无父标签 )结果:['text1', 'text2', 'text3']
print(xp.xpath('/html/body/div/ul/li/@class'))
#返回所有标签li的class属性值(li的父标签任意) 结果:['text', 'text1', 'text2', 'text3']
print(xp.xpath('//li/@class'))
#由于head中还有li标签,所以两次匹配的结果不一样


#返回所有的标签a(其中a为li的子孙标签,li的父标签为ul,...,html无父标签) 结果:['text1_a', 'text1_a1', 'text1_a2', 'text1_p_a2', 'text1_a3', 'text2_a', 'text2_a']
print(xp.xpath('/html/body/div/ul/li//a/text()'))
#返回所有的标签a(其中a为li的子标签,li的父标签为ul,...,html无父标签) 结果:['text1_a', 'text1_a1', 'text1_a2', 'text1_a3', 'text2_a', 'text2_a']
print(xp.xpath('/html/body/div/ul/li/a/text()'))
#两者在一个子孙标签<a href = "text1_a2.html">text1_p_a2</a></p>上展现了差距
#这也表明了若所有li的下有子孙标签,则...//a与.../a不一样,


#返回所有的标签p(其中p为li的子孙标签,li的父标签为ul,...,html无父标签) 结果:['text3_p1\n\t\t\t\t\t', 'text3_p1', 'text3_p2']
print(xp.xpath('/html/body/div/ul/li//p/text()'))
#返回所有的标签p(其中p为li的子标签,li的父标签为ul,...,html无父标签) 结果:['text3_p1\n\t\t\t\t\t', 'text3_p1', 'text3_p2']
print(xp.xpath('/html/body/div/ul/li/p/text()'))
#这也表明了若所有li的下没有子孙标签,则...//a与.../a一样,

2、按序选择


若我们需要选择上面html中ul/li下的第二个标签a咋办,xpath提供了许多按序选择的方法具体见下

html ='''<html>
<head>解析库
	<li class = "text">
		<a href = "head_text2_a1.html">head_text2_a</a>
		<a href = "head_text2_a2.html">head_text2_a</a></li></head>
<body>
	<div class = "content">
		<ul>hello ul
			<li class = "text1">hello li
				<a href = "text1_a.html">text1_a</a>
				<a href = "text1_a1.html">text1_a1</a>
				<a href = "text1_a2.html">text1_a2</a>
				<p name = "text1_p">text3_p1
					<a href = "text1_a2.html">text1_p_a2</a></p>
				<a href = "text1_a3.html">text1_a3</a></li>
			<li class = "text2">
				<a href = "text2_a1.html">text2_a</a>
				<a href = "text2_a2.html">text2_a</a></li>
			<li class = "text3">
				<p name = "text3_p">text3_p1</p>
				<p name = "text3_p">text3_p2</p></li></ul></body></html>
'''
from lxml.etree import HTML
xp = HTML(html)

#返回标签a的文本(a为li下的第二个子标签,且li在//ul/li下(表示li的父标签为ul,ul的父标签为任意,后续不在重重) 结果:['text1_a1', 'text2_a']
print(xp.xpath('//ul/li/a[2]/text()'))
#返回标签a的文本(a为li下的第一个子标签,且li在//ul/li下  结果:['text1_a', 'text2_a']
print(xp.xpath('//ul/li/a[1]/text()'))
#返回标签a的文本(a为li下的第三个子标签,且li在//ul/li下  结果:['text1_a2']
print(xp.xpath('//ul/li/a[3]/text()'))
#返回标签a的文本(a为li下的最后一个子标签,且li在//ul/li下 结果:['text1_a3', 'text2_a']
print(xp.xpath('//ul/li/a[last()]/text()'))
#返回标签a的文本(a为li下的倒数第二个子标签,且li在//ul/li下  结果['text1_a2', 'text2_a']
print(xp.xpath('//ul/li/a[last()-1]/text()'))
#返回标签a的文本(a为li下的倒数第三个子标签,且li在//ul/li下  结果['text1_a1']
print(xp.xpath('//ul/li/a[last()-2]/text()'))
#//ul/li/a[k],正数第k个(与列表的索引差1),k = 1,2,...
# //ul/li/a[last()-k],倒数第k+1个,k = 0,1,2,...

#返回标签a的文本(a为li下的前三个子标签(不包括第三个) 结果:['text1_a', 'text1_a1', 'text2_a', 'text2_a']
print(xp.xpath('//ul/li/a[position()<3]/text()'))
#返回标签a的文本(a为li下的第三四个子标签   结果:['text1_a2', 'text1_a3']
print(xp.xpath('//ul/li/a[position()>= 3 and position() <= 4]/text()'))

#返回所有标签a的文本(a为li的子标签,li为ul的第二个子标签,ul的父标签任意  结果:['text2_a', 'text2_a']
print(xp.xpath('//ul/li[2]/a/text()'))

#返回所有标签a的文本(a为li的子标签,li为ul的第二个子标签,ul的父标签任意  结果:['text2_a', 'text2_a']
print(xp.xpath('//ul/li[2]/a/text()'))
#返回标签a的文本(a为li下的第二个子标签,且li在//ul/li下  结果:['text1_a1', 'text2_a']
print(xp.xpath('//ul/li/a[2]/text()'))
# //ul/li[2]/a  返回第二个标签li下的所有的a
# //ul/li/a[2]  返回每个li下的第二个标签a   两者是不一样的

3、属性匹配

html = '''<html>
<body>
	<div class="wrapper">
		<div class="content">
			<span class= "password1">wrapper_content_password1</span>
			<span class= "password2">wrapper_content_password1</span>
			<span class= "password3">wrapper_content_password1</span>
			<span class= "password">wrapper_content_password1</span>
			<span class= "password">wrapper_content_password2</span>
			<span class= "password">wrapper_content_password3</span></div>
		<div class="content">
			<div class = "text1" id= "hidden">wrapper_content_hidden_text1</div>
			<div class = "text2" id= "hidden">wrapper_content_hidden_text2</div>
			<div class = "text3" id= "hidden">wrapper_content_hidden_text3</div></div>
		<div class= "content">
			<div id= "text">
				<div class = "content">wrapper_text_text</div>
				<div class = "content text">wrapper_content_text_text1</div>
				<div class = "content text">wrapper_content_text_text2</div>
				<div class = "content text">wrapper_content_text_text3</div>
        </div></div></div></body></html>
'''
from lxml.etree import HTML
xp = HTML(html)
#一个属性一个值匹配
#返回所有span标签的文本(span为//body/div/div的子标签,且class属性为password1) 结果:['wrapper_content_password1']
print(xp.xpath('//body/div/div/span[@class = "password1"]//text()'))
#返回所有span标签的文本(span为‘//div[@class = "wrapper"]/div[@class = "content"]'子标签,且class属性为password1) 结果:['wrapper_content_password1']
print(xp.xpath('//div[@class = "wrapper"]/div[@class = "content"]/span[@class = "password1"]/text()'))
#返回span标签的文本(span为'//div[@class = "wrapper"]/div[@class = "content"]'最后一个子标签,且class属性为password1) 结果:['wrapper_content_password3']
print(xp.xpath('//div[@class = "wrapper"]/div[@class = "content"]/div[@id = "hidden"][last()]/text()'))
#这也就说明,若节点比较多时,我们可以在前面祖辈添加属性,使得匹配更精确
#注意任意属性都可以使用[@属性 = "属性值"]去匹配,但一般我们只是用name,class,id这三个
# [@id = "hidden"][last()] 表示这三个同时满足

#多个属性,每个属性每个值匹配
#返回所有的div标签内容(div为//div/div[@class = "content"]的子标签,且div的属性class = "text2" and id= "hidden  结果:['wrapper_content_hidden_text2']
print(xp.xpath('//div/div[@class = "content"]/div[@class = "text2" and @id = "hidden"]/text()'))
#返回所有的div标签内容(div为//div/div[@class = "content"]的子标签,且div的属性class = "text2" and id= "hidden  结果:['wrapper_content_hidden_text2']
print(xp.xpath('//div/div[@class = "content"]/div[@class = "text2" ][ @id = "hidden"]/text()'))
#返回所有的div标签内容(div为//div/div[@class = "content"]的子标签,且div的属性class = "text2" or id= "hidden
# 结果:['wrapper_content_hidden_text1','wrapper_content_hidden_text2', 'wrapper_content_hidden_text3']
print(xp.xpath('//div/div[@class = "content"]/div[@class = "text2" or @id = "hidden"]/text()'))

#一个属性多值匹配
#返回所有div标签的文本(div为//div[@class = "content"]/div[@id = "text"]的子标签,且class属性包含“text”,
# 结果:['wrapper_content_text_text1', 'wrapper_content_text_text2', 'wrapper_content_text_text3']
print(xp.xpath('//div[@class = "content"]/div[@id = "text"]/div[contains(@class,"text")]/text()'))
#返回所有div标签的文本(div为//div[@class = "content"]/div[@id = "text"]的子标签,且class属性值中包含“con”字眼的,
# 结果:['wrapper_text_text', 'wrapper_content_text_text1', 'wrapper_content_text_text2', 'wrapper_content_text_text3']
print(xp.xpath('//div[@class = "content"]/div[@id = "text"]/div[contains(@class,"con")]/text()'))
#返回所有div标签的文本(div为//div[@class = "content"]/div[@id = "text"]的子标签,且class属性包含“content”,
# 结果:['wrapper_text_text', 'wrapper_content_text_text1', 'wrapper_content_text_text2', 'wrapper_content_text_text3']
print(xp.xpath('//div/div[@id = "text"] /div[contains(@class,"content")]/text()'))
#[contains(@属性a,属性值1)]匹配属性a包含属性值1的标签

#文本匹配 匹配wrapper_content_password1文本对应标签的class属性值
#返回所有span标签对应的class属性值(span为//div[@class = "wrapper"]/div[@class = "content"]的子标签,且span的文本值包含wrapper_content_password1
#结果: ['password1', 'password2', 'password3', 'password']
print(xp.xpath('//div[@class = "wrapper"]/div[@class = "content"]/span[contains(text(),"wrapper_content_password1")]/@class'))

4、xpath与正则结合

html = '''<html>
<body>
	<div class="wrapper">
		<div class="content">
			<span class= "password1">wrapper_content_password1</span>
			<span class= "password2">wrapper_content_password1</span>
			<span class= "password3">wrapper_content_password1</span>
			<span class= "password">wrapper_content_password1</span>
			<span class= "password">wrapper_content_password2</span>
			<span class= "password">wrapper_content_password3</span>
		</div>
		<div class="content">
			<div class = "text1" id= "hidden">wrapper_content_hidden_text1</div>
			<div class = "text2" id= "hidden">wrapper_content_hidden_text2</div>
			<div class = "text3" id= "hidden">wrapper_content_hidden_text3</div>
		</div>
		<div class= "content">
			<div id= "text">
				<div class = "content">wrapper_text_text</div>
				<div class = "content text">wrapper_content_text_text1</div>
				<div class = "content text">wrapper_content_text_text2</div>
				<div class = "content text">wrapper_content_text_text3</div>
			</div>
		</div>
	</div>
</body>
</html>
'''
from lxml.etree import HTML
xp = HTML(html)
namespaces = {"re": "http://exslt.org/regular-expressions"}
#返回所有span标签的class属性值(span在//div[@class = "wrapper"]/div[@class = "content"]子标签,且span的class属性以password开头数字结尾
#结果 : ['password1', 'password2', 'password3']
print(xp.xpath('//div[@class = "wrapper"]/div[@class = "content"]/span[re:match(@class,"password\d")]/@class',namespaces =  namespaces))
# 返回div标签的文本值(div为//div/div的子标签,且class属性以text开头,012数字结尾,
# 结果 :['wrapper_content_hidden_text1', 'wrapper_content_hidden_text2']
print(xp.xpath('//div/div/div[re:match(@class,"text[0-2]")]/text()',namespaces = namespaces))
# 返回div标签的文本值(div为//div/div[@id = "text"]的子标签,且div的文本值满足".*_text_text\d"(正则语句))
# ['wrapper_content_text_text1', 'wrapper_content_text_text2', 'wrapper_content_text_text3']
print(xp.xpath('//div/div[@id = "text"]/div[re:match(text(),".*_text_text\d")]/text()',namespaces = namespaces))
#div[re:match(text(),“正则语句”]  根据文本匹配
# div[re:match(@属性,”正则语句“]   根据属性匹配
#注意正则语句,一定要用引号引起,且一定要传入namespaces参数(namespaces = {"re": "http://exslt.org/regular-expressions"})

5、嵌套匹配

#嵌套匹配
html ='''<html>
<body>
	<div class = "content">
		<ul>hello ul
			<li class = "text1">hello li
				<a href = "text1_a.html">text1_a</a>
				<a href = "text1_a1.html">text1_a1</a>
				<a href = "text1_a2.html">text1_a2</a>
				<p name = "text1_p">text3_p1
					<a href = "text1_a2.html">text1_p_a2</a></p>
				<a href = "text1_a3.html">text1_a3</a></li>
			<li class = "text2">
				<a href = "text2_a1.html">text2_a</a>
				<a href = "text2_a2.html">text2_a</a></li>
			<li class = "text3">
				<p name = "text3_p">text3_p1</p>
				<p name = "text3_p">text3_p2</p></li></ul></body></html>
'''
from lxml.etree  import HTML
xp = HTML(html)
#第一步  返回所有的li标签(li为//ul的子标签)
result = xp.xpath('//ul/li')
# 第二步 返回所有标签a的文本值(标签a为//ul/li[1]/p的子标签) 结果:['text1_p_a2']
print(result[0].xpath('p/a/text()'))
#返回所有的标签a的文本值(a为//ul/li的子标签,且href属性为"text2_a2.html")结果:['text2_a']
print(result[1].xpath('a[@href = "text2_a2.html"]/text()'))

# 返回所有标签a的文本值(标签a为//ul/li[1]/p[1]的子标签) 结果:['text1_p_a2']
print(xp.xpath('//ul/li[1]')[0].xpath('p')[0].xpath('a/text()'))
# 结果:[]
print(xp.xpath('//ul/li[1]')[0].xpath('p')[0].xpath('/a/text()'))
# 若a后面还有标签就可以一直嵌套下去
# 若是嵌套匹配后一个xpath第一标签前不要带有/,否则返回空列表

6、节点轴选择

若把上面的看完就可以使用xpath进行许多东西的学习,至于这一小节的内容熟悉便可,我们爬虫中很少用到下面的东西

#节点轴选择
html ='''<html>
<body>
	<div class = "content">
		<ul>hello ul
			<li class = "text1">hello li
				<a href = "text1_a.html">text1_a</a>
				<a href = "text1_a1.html">text1_a1</a>
				<a href = "text1_a2.html">text1_a2</a>
				<p name = "text1_p">text3_p1
					<a href = "text1_a2.html">text1_p_a2</a></p>
				<a href = "text1_a3.html">text1_a3</a></li>
			<li class = "text2">
				<a href = "text2_a1.html">text2_a</a>
				<a href = "text2_a2.html">text2_a</a></li>
			<li class = "text3">
				<p name = "text3_p">text3_p1</p>
				<p name = "text3_p">text3_p2</p></li></ul></body></html>
'''
#获取子标签、子孙标签
from lxml.etree import HTML
xp = HTML(html)
# 返回所有子标签的class属性值(//ul的孩子标签)  结果:['text1', 'text2', 'text3']
print(xp.xpath('//ul/child::*/@class'))
# 返回所有子孙标签的name属性值(//ul的子孙标签,//ul/li[1]/a没有name属性) 结果:['text1_p', 'text3_p', 'text3_p']
print(xp.xpath('//ul/descendant::*/@name'))
# 返回所有的标签a的文本值(a为//ul/li[1]的孩子标签)(排除孩子p)  结果:['text1_a', 'text1_a1', 'text1_a2', 'text1_a3']
print(xp.xpath('//ul/li[1]/child::a/text()'))
#返回所有的标签a的文本值(a为//ul/li[1]的子孙,且a[@href = "text1_a2.html"]  结果:['text1_a2', 'text1_p_a2']
print(xp.xpath('//ul/li[1]/descendant::a[@href = "text1_a2.html"]/text()'))

#获取父标签,祖先标签
#返回所有标签p的父标签的class属性(p的names = text1_p) 结果: ['text1']
print(xp.xpath('//p[@name ="text1_p"]/parent::*/@class'))
#返回所有的标签p的祖先标签
# 结果:[<Element html at 0x27769964308>, <Element body at 0x27769964848>, <Element div at 0x27769964888>, <Element ul at 0x27769964948>, <Element li at 0x277699647c8>]
print(xp.xpath('//p[@name = "text1_p"]/ancestor::*'))
#返回所有的标签p的祖先标签ul 结果:[<Element ul at 0x28b9cb54908>]
print(xp.xpath('//p[@name = "text1_p"]/ancestor::ul'))

#兄弟标签
#返回标签p的后面所有兄弟标签的文本值(p为//ul/li[1]的子标签)  结果:['text1_a3']
print(xp.xpath('//ul/li[1]/p/following-sibling::*/text()'))
#返回标签p的前面所有兄弟标签的文本值(p为//ul/li[1]的子标签)  结果:['text1_a', 'text1_a1', 'text1_a2']
print(xp.xpath('//ul/li[1]/p/preceding-sibling::*/text()'))

到这为止xpath语言也差不多说完了,使用lxml很容易就能得到我们想要的内容,但是他也有它的缺点比如它返回的结果是一个对象,我们很难看不同标签之间出差距来,而且它返回的文本内容带有\n\t,对于获得文本我们还需要进一步处理。但也有优势的是它的匹配很灵活(有正则表达式)。下一节我们学习BeautifulSoup,这个库的学习比较简单,而且返回文本不需要处理,但就是不是很灵活。

# xpath语言内容远超出这些,但是对于爬虫解析网页这些足够我们用了

#转载则请标明文章出处,谢谢。

#文中若有任何错误,欢迎大家积极指出,小编洗耳恭听。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值