介绍
pyquery是一个专门用来解析html的库,从名字很容易想到jQuery,没错,这完全是仿照jQuery的语法实现的。如果用过jQuery,俺么pyquery很容易实现
初始化html
pyquery可以接收一个网址,自动下载内容,也可以接收已经下载好的字符串格式的html,当然也可以传入一个本地html文件。但是我们一般都会使用requests下载html页面,然后再将html页面以字符串的格式传进去
from pyquery import PyQuery
html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>古明地觉</title>
</head>
<body>
<p id="bili"><a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a></p>
<p class="s1">my name is satori</p>
<div>
<p class="s1">古明地恋</p>
</div>
<table >
<tbody>
<tr>
<td>姓名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr class="tr">
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</tbody>
</table>
<a href="http://www.baidu.com" target="_blank">百度</a>
<a href="http://www.yahoo.com">雅虎</a>
</body>
</html>
'''
p = PyQuery(html) # 此时得到的是一个pyquery对象
print(type(p)) # <class 'pyquery.pyquery.PyQuery'>
# 如果打印p的话,会直接将我们传入的html打印出来,只不过p的类型是PyQuery
使用选择器
from pyquery import PyQuery
html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>古明地觉</title>
</head>
<body>
<p id="bili"><a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a></p>
<p class="s1">my name is satori</p>
<div>
<p class="s1">古明地恋</p>
</div>
<table >
<tbody>
<tr>
<td>姓名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr class="tr">
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</tbody>
</table>
<a href="http://www.baidu.com" target="_blank">百度</a>
<a href="http://www.yahoo.com">雅虎</a>
</body>
</html>
'''
p = PyQuery(html)
# 标签选择器
# 打印出标签为head的内容
print(p("head"))
"""
<head>
<meta charset="UTF-8"/>
<title>古明地觉</title>
</head>
"""
# 但是需要注意的是,这个打印出来的依旧是一个PyQuery类型
# 意味着我们可以进一步过滤,但是如果我想要字符串的话呢?直接调用str方法即可
print(str(p("head")))
"""
<head>
<meta charset="UTF-8"/>
<title>古明地觉</title>
</head>
"""
# 或者调用html方法,但是此时获取到的不包括相应的标签名
# head标签本身没了,只保留里面的内容,此时也是一个字符串的类型
print(p("head").html())
"""
<meta charset="UTF-8"/>
<title>古明地觉</title>
"""
# 但如果有很多标签,比如p标签,在调用html方法的时候,只会打印第一个p标签里面的内容
print(p("p"))
"""
<p id="bili"><a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a></p>
<p class="s1">my name is satori</p>
<p class="s1">古明地恋</p>
"""
print(p("p").html())
"""
<a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a>
"""
# 获取文本
print(p("head").text())
"""
古明地觉
"""
# 可以看到只获取了纯文本,因为只能title标签里面有文本,而title在head里面
# css选择器
# 获取id=bili的标签
print(p("#bili"))
"""
<p id="bili"><a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a></p>
"""
# 获取class=s1的标签
print(p(".s1"))
"""
<p class="s1">my name is satori</p>
<p class="s1">古明地恋</p>
"""
# 获取tbody下的class=tr的标签下的所有td标签
print(p("tbody .tr td"))
"""
<td>密码:</td>
<td><input type="password" name="password"/></td>
"""
# 可以看到这和jQuery的语法基本上是一致的
# 如果我只想获取第一个的话,索引要是越界的话,也不会报错,会打印空行
print(p("tbody .tr td").eq(0))
"""
<td>密码:</td>
"""
# 常用方法:
'''
p(".color"):获取class=color的标签
p("#color"):获取id=color的标签
p("*"):获取所有的标签
p("p"):获取所有的p标签
p("div,p"):获取所有的div标签和p标签
p("div p"):获取所有div标签内部的p标签
p("[target]"):选择带有target属性的所有元素
p("[target=_blank]"):选择带有target=_blank的所有元素
'''
filter和find
from pyquery import PyQuery
html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>古明地觉</title>
</head>
<body>
<p id="bili"><a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a></p>
<p class="s1">my name is satori</p>
<div>
<p class="s1">古明地恋</p>
</div>
<table >
<tbody>
<tr>
<td>姓名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr class="tr">
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</tbody>
</table>
<a href="http://www.baidu.com" target="_blank">百度</a>
<a href="http://www.yahoo.com">雅虎</a>
</body>
</html>
'''
p = PyQuery(html)
print(p("p")) # 这是所有的p标签
"""
<p id="bili"><a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a></p>
<p class="s1">my name is satori</p>
<p class="s1">古明地恋</p>
"""
# 我只要class=s1的p标签,可以使用filter过滤
print(p("p").filter(".s1")) # 表示在找到的p标签中,过滤出class=s1的p标签
"""
<p class="s1">my name is satori</p>
<p class="s1">古明地恋</p>
"""
# 如果要按照文本过滤呢?比如我想找出文本内容等于'古明地恋'的p标签
print(p("p").filter(lambda _, this: PyQuery(this).text() == '古明地恋'))
"""
<p class="s1">古明地恋</p>
"""
# find
# 首先filter是过滤得到符合条件的标签
# 而find是在符合条件的标签里面找
# 举个例子
"""
p("p").filter(".fuck")表示的是有很多的p标签,我在选出的这么多p标签中,找到class=fuck的p标签
p("p").find(".fuck")表示的是有很多的p标签,我在选出的这么多p标签中,找到其内部满足class=fuck的其他标签
"""
print(p("div").filter(".s1"))
"""
"""
print(p("div").find(".s1"))
"""
<p class="s1">古明地恋</p>
"""
# 可以看到p("div").filter(".s1")是空的,因为这表示在选出来的div标签中,找出class=s1的div
# 而p("div").find(".s1")表示找到div里面满足class=s1的其他标签
# filter和find可以无限使用的,因为返回的都是一个PyQuery类型
# p("div p .cls li a") == p("div").find("p").find(".cls").find("li").find("a")
获取属性
from pyquery import PyQuery
html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>古明地觉</title>
</head>
<body>
<p id="bili"><a href="http://www.bilibili.com">想进入基佬的大门吗?还等什么,快点击吧</a></p>
<p class="s1">my name is satori</p>
<div>
<p class="s1">古明地恋</p>
</div>
<table >
<tbody>
<tr>
<td>姓名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr class="tr">
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</tbody>
</table>
<a href="http://www.baidu.com" target="_blank">百度</a>
<a href="http://www.yahoo.com">雅虎</a>
</body>
</html>
'''
p = PyQuery(html)
a_tag = p("a")
print(a_tag.attr("href")) # http://www.bilibili.com
"""
可以直接调用attr方法,传入要获取的属性值即可。
但是注意到即便满足条件的标签有多个,和html一样,调用attr获取的时候只会得到第一个
"""
# 因此可以使用eq
print(p("a").eq(0).attr("href")) # http://www.bilibili.com
print(p("a").eq(1).attr("href")) # http://www.baidu.com
# 但是还有一个问题,就是我们不知道获得了几个p标签
# 难道要一个一个的数吗?
# 当然不用,一种笨的方法,就是我不断的循环,如果没有内容了就break
# 但是PyQuery内部给我们提供了一个items方法,可以自动的迭代,如果迭代完毕自动退出。
for i in p("a").items():
print(i.attr("href"))
"""
http://www.baidu.com
http://www.yahoo.com
"""