https://pyquery.readthedocs.io/en/latest/
pyquery allows you to make jquery queries on xml documents. The API is as much as possible the similar to jquery. pyquery uses lxml for fast xml and html manipulation.
pyquery庫是jQuery的Python實現,能夠以jQuery的語法來操作解析 HTML 文檔
pyquery uses lxml for fast xml and html manipulation
參考網站
https://pyquery.readthedocs.io/en/latest/
https://www.jianshu.com/p/770c0cdef481
https://pythonhosted.org/pyquery/css.html
https://www.osgeo.cn/pyquery/index.html
https://pyquery.readthedocs.io/en/latest/api.html
初始化對象
##############字符串初始化
from pyquery import PyQuery as pq
#初始化為PyQuery對象
doc = pq(html)
print(type(doc))
print(doc)
####html 文件初始化
#filename參數為html文件路徑
test_html = pq(filename = 'test.html')
print(type(test_html))
print(test_html)
####網址獲取
response = pq(url = 'https://www.baidu.com')
print(type(response))
print(response)
###官方初始化
>>> from pyquery import PyQuery as pq
>>> from lxml import etree
>>> import urllib
>>> d = pq("<html></html>")
>>> d = pq(etree.fromstring("<html></html>"))
>>> d = pq(url=your_url)
>>> d = pq(url=your_url,
... opener=lambda url, **kw: urlopen(url).read())
>>> d = pq(filename=path_to_html_file)
獲取元素
根據html 標簽獲取元素
from pyquery import PyQuery
html = '''
<div>
<p>test 1</p>
<p>test 2</p>
</div>
'''
p = PyQuery(html)
# 獲取所有p標簽
p('p') #這種方式獲取的結果對象為 <class 'pyquery.pyquery.PyQuery'>
>>> [<p>, <p>]
print(p('p'))
>>> <p>test 1</p>
<p>test 2</p>
p.find('p') #獲取的結果為<class 'lxml.html.HtmlElement'>
eq 根據給定的索引號得到指定元素
# 獲取第一個p標簽的內容
p('p').eq(0).html()
>>> 'test 1'
# 獲取第二個p標簽的內容
p('p').eq(1).html()
>>> 'test 2'
# 不用 eq 方法默認返回第一個
p('p').html()
>>> 'test 1'
類名id獲取元素
from pyquery import PyQuery as pq
html = '''<div>
<ul id = 'haha'>
<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>'''
doc = pq(html)
print(doc)
#id等於haha下面的class等於item-0下的a標簽下的span標簽(注意層級關系以空格隔開)
print(doc('#haha .item-0 a span'))
#####
# 根據id名獲取元素
p('#1').html()
>>> 'test 1'
# 根據class名獲取元素
>>> p('.abc').html()
'test 2'
html 函數
獲取相應的 HTML 塊
text()
:獲取文本塊
from pyquery import PyQuery as pq
html = '''<div>
<ul id = 'haha'>
<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>'''
doc = pq(html)
print(doc)
# id等於haha下面的class等於item-0下的a標簽下的span標簽(注意層級關系以空格隔開)
# print(doc('#haha .item-0 a span'))
print("\n")
print(doc.html())
print("text")
print(doc.text())
###結果
<div>
<ul id="haha">
<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>
<ul id="haha">
<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>
doc.text() 函數
first item
second item
third item
fourth item
fifth item
獲取屬性值
html = '''
<p id='my_id'>
<a href='http://hello.com'>hello</a>
</p>
'''
p('a').attr('href')
####
html = '''
<p id='my_id'>
<a href='http://hello.com'>hello</a>
</p>
'''
>>doc = pq(html)
>>doc('a').attr('href') ##print(item.attr.href)
'http://hello.com'
>>doc('a')
[<a>]
>>doc('a')[0].values()
['http://hello.com']
>>a = doc('a')[0]
>>a.get("href")
'http://hello.com'
獲取子元素
from pyquery import PyQuery
html = '''
<span>
<p id='1'>hello</p>
<p id='2'>world</p>
</span>
'''
p = PyQuery(html)
# 提取div的所有子元素
p.children()
>>> [<p#1>, <p#2>]
# 提取div下id=‘1’的子元素
p.children('#1')
>>> [<p#1>]
父元素
#######################分離_________________________________________________
常用的CCS選擇器
打印id為container的標簽
print(doc('#container'))
print(type(doc('#container')))
打印class為object-1的標簽
print(doc('.object-1'))
打印標簽名為body的標簽
print(doc('body'))
多種css選擇器使用
print(doc('html #container'))
偽類選擇器
print(pseudo_doc('li:nth-child(2)'))
#打印第一個li標簽
print(pseudo_doc('li:first-child'))
#打印最后一個標簽
print(pseudo_doc('li:last-child'))
contains
#找到含有Python的li標簽
print(pseudo_doc("li:contains('Python')"))
#找到含有好的li標簽
print(pseudo_doc("li:contains('好')"))
查找標簽
按照條件在Pyquery對象中查找符合條件的標簽,類似於BeautifulSoup中的find方法。
打印id=container的標簽
print(doc.find('#container'))
print(doc.find('li'))
子輩標簽-children方法
#id=container的標簽的子輩標簽
container = doc.find('#container')
print(container.children())
父輩標簽-parent方法
object_2 = doc.find('.object-2')
print(object_2.parent())
兄弟標簽-siblings方法
object_2 = doc.find('.object-2')
print(object_2.siblings())
獲取標簽的信息
定位到目標標簽后,我們需要標簽內部的文本或者屬性值,這時候需要進行提取文本或屬性值操作
標簽屬性值的提取
.attr() 傳入 標簽的屬性名,返回屬性值
object_2 = doc.find('.object-2')
print(object_2.attr('class'))
標簽內的文本
html_text = """
<html lang="en">
<head>
簡單好用的
<title>PyQuery</title>
</head>
<body>
<ul id="container">
Hello World!
<li class="object-1">Python</li>
<li class="object-2">大法</li>
<li class="object-3">好</li>
</ul>
</body>
</html>
"""
docs = pq(html_text)
print(docs.text())
######
object_1 = docs.find('.object-1')
print(object_1.text())
container = docs.find('#container')
print(container.text())
tips:如果我只想獲得Hello World這個,不想得到其他的文本,可以使用remove方法將li標簽去掉,然后再使用text方法
container = docs.find('#container')
container.remove('li')
print(container.text())
pyquery一些自定義的用法
PyQuery與BeautifulSoup對比,我們會發現PyQuery可以對網址發起請求
from pyquery import PyQuery
PyQuery(url = 'https://www.baidu.com')
opener參數
這是PyQuery對百度網址進行請求,並將請求返回的響應數據處理為PyQuery對象。一般pyquery庫會默認調用urllib庫,如果想使用selenium或者requests庫,可以自定義PyQuery的opener參數。
opener參數作用是告訴pyquery用什么請求庫對網址發起請求。常見的請求庫如urllib、requests、selenium。這里我們自定義一個selenium的opener。
from pyquery import PyQuery
from selenium.webdriver import PhantomJS
#用selenium訪問url
def selenium_opener(url):
#我沒有將Phantomjs放到環境變量,所以每次用都要放上路徑
driver = PhantomJS(executable_path = 'phantomjs的路徑')
driver.get(url)
html = driver.page_source
driver.quit()
return html
#注意,使用時opener參數是函數名,沒有括號的!
PyQuery(url='https://www.baidu.com/', opener=selenium_opener)
cookies、headers
在requests用法中,一般為了訪問網址更加真實,模仿成瀏覽器。一般我們需要傳入headers,必要的時候還需要傳入cookies參數。而pyquery庫就有這功能,也能偽裝瀏覽器。
from pyquery import PyQuery
cookies = {'Cookie':'你的cookie'}
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'}
PyQuery(url='https://www.baidu.com/',headers=headers,cookies=cookies)
讓你的selenium帶上pyquery功能
from pyquery import PyQuery
from selenium.webdriver import PhantomJS
class Browser(PhantomJS):
@property
def dom(self):
return PyQuery(self.page_source)"""
這部分property是裝飾器,需要知道@property下面緊跟的函數,實現了類的屬性功能。
這里browser.dom,就是browser的dom屬性。
"""
browser = Browser(executable_path='phantomjs的路徑')
browser.get(url='https://www.baidu.com/')
print(type(browser.dom))
PyQuery-獲取數據
初始化
初始化的時候一般有三種傳入方式:傳入字符串,傳入url,傳入文件
字符串初始化
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)
print(type(doc))
print(doc('li'))
# 代碼中的doc其實就是一個pyquery對象,我們可以通過doc可以進行元素的選擇,其實這里就是一個css選擇器,所以CSS選擇器的規則都可以用,直接doc(標簽名)就可以獲取所有的該標簽的內容,如果想要獲取class 則doc('.class_name'),如果是id則doc('#id_name')....
URL初始化
from pyquery import PyQuery as pq
doc = pq(url="http://www.baidu.com",encoding='utf-8')
print(doc('head'))
文件初始化
pq(filename='index.html')
基本的CSS選擇器
html = '''
<div id="container">
<ul class="list">
<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('#container .list li'))
# doc('#container .list li'),這里的三者之間的並不是必須要挨着,只要是層級關系就可以
常用的CSS選擇器方法:
.class .color 選擇class="color"的所有元素
#id .info 選擇id="info"的所有元素
* * 選擇所有元素
element p 選擇所有的p元素
element,element div,p 選擇所有的div元素和所有的p元素
element element div p 選擇div標簽內部所有的p元素
[attribute] [target] 選擇帶有target屬性的元素
[attribute=value] [target=_blank] 選擇target=_blank的所有元素
查找元素
子元素
children,find
html = '''
<div id="container">
<ul class="list">
<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)
items = doc('.list')
print(type(items))
print(items)
lis = items.find('li')
print(type(lis))
print(lis)
# 通過pyquery找到結果其實還是一個pyquery對象,可以繼續查找,上述中的代碼中的items.find('li') 則表示查找ul里的所有的li標簽
通過children可以實現同樣的效果,並且通過.children方法得到的結果也是一個pyquery對象
li = items.children()
print(type(li))
print(li)
# 同時在children里也可以用CSS選擇器
li2 = items.children('.active') print(li2)
父元素
parent,parents方法
通過.parent就可以找到父元素的內容
html = '''
<div id="container">
<ul class="list">
<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)
items = doc('.list')
container = items.parent()
print(type(container))
print(container)
通過.parents就可以找到祖先節點的內容
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
items = doc('.list')
parents = items.parents()
print(type(parents))
print(parents)
同樣我們通過.parents查找的時候也可以添加css選擇器來進行內容的篩選
兄弟元素
siblings
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.list .item-0.active')
print(li.siblings())
代碼中doc('.list .item-0.active') 中的.tem-0和.active是緊挨着的,所以表示是並的關系,這樣滿足條件的就剩下一個了:thired item的那個標簽了
這樣在通過.siblings就可以獲取所有的兄弟標簽,當然這里是不包括自己的
同樣的在.siblings()里也是可以通過CSS選擇器進行篩選
遍歷
單個元素
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.item-0.active')
print(li)
lis = doc('li').items()
print(type(lis))
for li in lis:
print(type(li))
print(li)
##通過items()可以得到一個生成器,並且我們通過for循環得到的每個元素依然是一個pyquery對象
獲取信息
獲取屬性
pyquery對象.attr(屬性名)
pyquery對象.attr.屬性名
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
a = doc('.item-0.active a')
print(a)
print(a.attr('href'))
print(a.attr.href)
#獲得屬性值的時候可以直接a.attr(屬性名)或者a.attr.屬性名
獲取文本
在很多時候我們是需要獲取被html標簽包含的文本信息,通過.text()就可以獲取文本信息
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
a = doc('.item-0.active a')
print(a)
print(a.text())
獲取html
我們通過.html()的方式可以獲取當前標簽所包含的html信息,
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.item-0.active')
print(li)
print(li.html())
DOM操作
addClass、removeClass
熟悉前端操作的話,通過這兩個操作可以添加和刪除屬性
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.item-0.active')
print(li)
li.removeClass('active')
print(li)
li.addClass('active')
print(li)
attr,css
同樣的我們可以通過attr給標簽添加和修改屬性,
如果之前沒有該屬性則是添加,如果有則是修改
我們也可以通過css添加一些css屬性,這個時候,標簽的屬性里會多一個style屬性
html = '''
<div class="wrap">
<div id="container">
<ul class="list">
<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>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.item-0.active')
print(li)
li.attr('name', 'link')
print(li)
li.css('font-size', '14px')
print(li)
remove
有時候我們獲取文本信息的時候可能並列的會有一些其他標簽干擾,這個時候通過remove就可以將無用的或者干擾的標簽直接刪除,從而方便操作
html = '''
<div class="wrap">
Hello, World
<p>This is a paragraph.</p>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
wrap = doc('.wrap')
print(wrap.text())
wrap.find('p').remove()
print(wrap.text())