Python中类似于jquery的pyquery库用法分析

本文实例讲述了Python中类似于jquery的pyquery库用法。分享给大家供大家参考,具体如下:

pyquery:一个类似于jquery的Python库

pyquery可以使你在xml文档上做jquery查询,它的API尽可能地类似于jquery。pyquery使用lxml执行快速的xml和html操作。

这并非(至少目前还不是)一个生成javascript代码或者与javascript代码做交互的库。pyquery的作者只是由于非常喜欢jquery的API因而将其用python实现。

该项目目前托管在Github仓库中并且处于活跃开发状态。作者可以为任何想要贡献源码的开发者赋予push权限,并且会对其做的变更做回顾。如果你想要贡献源码,可以发Email给项目作者。

项目的Bug可以通过Github Issue Tracker进行提交。

快速入门

你可以使用PyQuery类从一个字符串,一个lxml文档,一个文件或者一个url钟载入一个xml文档:

>>> 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)

现在,d就相当于jquery里的$:

>>> d("#hello")
[<p#hello.hello>]
>>> p = d("#hello")
>>> print(p.html())
Hello world !
>>> p.html("you know <a href='http://python.org/'>Python</a> rocks")
[<p#hello.hello>]
>>> print(p.html())
you know <a href="http://python.org/" rel="external nofollow" >Python</a> rocks
>>> print(p.text())
you know Python rocks

你也可以使用某些jQuery中可用而并非css标准的伪类,诸如 :first :last :even :odd :eq :lt :gt :checked :selected :file:等

>>> d('p:first')
[<p#hello.hello>]

参见http://pyquery.rtfd.org/查看全部文档

CSS

你可以像这样添加、切换、移除CSS:

>>> p.addClass("toto")
[<p#hello.hello.toto>]
>>> p.toggleClass("titi toto")
[<p#hello.hello.titi>]
>>> p.removeClass("titi")
[<p#hello.hello>]

或者操作CSS样式:

>>> p.css("font-size", "15px")
[<p#hello.hello>]
>>> p.attr("style")
'font-size: 15px'
>>> p.css({"font-size": "17px"})
[<p#hello.hello>]
>>> p.attr("style")
'font-size: 17px'

使用更加Pythonic的方式完成同样的功能 (‘_' 字符转换为 ‘-‘):

>>> p.css.font_size = "16px"
>>> p.attr.style
'font-size: 16px'
>>> p.css['font-size'] = "15px"
>>> p.attr.style
'font-size: 15px'
>>> p.css(font_size="16px")
[<p#hello.hello>]
>>> p.attr.style
'font-size: 16px'
>>> p.css = {"font-size": "17px"}
>>> p.attr.style
'font-size: 17px'

使用伪类:

  • :button

匹配所有按钮输入元素和按钮元素 Matches all button input elements and the button element

  • :checkbox

匹配所有复选框输入元素 Matches all checkbox input elements

  • :checked

匹配选中的元素,下标从0开始 Matches odd elements, zero-indexed

  • :child

右边是左边的直接子元素 right is an immediate child of left

  • :contains()

包含元素 Matches all elements that contain the given text

  • :descendant

右边是左边的子元素、孙元素或者更远的后继元素 right is a child, grand-child or further descendant of left

  • :disabled

匹配所有被禁用的元素 Matches all elements that are disabled

  • :empty

匹配所有不包括任何其他元素的元素 Match all elements that do not contain other elements

  • :enabled

匹配所有启用的元素 Matches all elements that are enabled

  • :eq()

使用下标匹配 Matches a single element by its index

  • :even

从下标0开始,匹配所有偶数元素 Matches even elements, zero-indexed

  • :file

匹配所有文件类型的输入元素 Matches all input elements of type file

  • :first

匹配第一个被选择的元素 Matches the first selected element

  • :gt()

匹配下标大于指定值的元素 Matches all elements with an index over the given one

  • :header

匹配所有标题元素 Matches all header elelements (h1, ..., h6)

  • :image

匹配所有图像输入元素 Matches all image input elements

  • :input

匹配所有输入元素 Matches all input elements

  • :last

匹配最后一个选择的元素 Matches the last selected element

  • :lt()

匹配所有下标小于指定值的元素 Matches all elements with an index below the given one

  • :odd

匹配奇元素,下标从0开始 Matches odd elements, zero-indexed

  • :parent

匹配所有包含其他元素的元素 Match all elements that contain other elements

  • :password

匹配所有密码输入元素 Matches all password input elements

  • :radio

匹配单选按钮输入元素 Matches all radio input elements

  • :reset

匹配所有重置输入元素 Matches all reset input elements

  • :selected

匹配所有被选中的元素 Matches all elements that are selected

  • :submit

匹配所有提交输入元素 Matches all submit input elements

  • :text¶

匹配所有文本输入元素 Matches all text input elements

操作

你也可以向标签的尾部追加元素:

>>> d = pq('<p class="hello" id="hello">you know Python rocks</p>')
>>> d('p').append(' check out <a href="http://reddit.com/r/python" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><span>reddit</span></a>')
[<p#hello.hello>]
>>> print(d)
<p class="hello" id="hello">you know Python rocks check out <a href="http://reddit.com/r/python" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" ><span>reddit</span></a></p>

或者加至开头:

>>> p = d('p')
>>> p.prepend('check out <a href="http://reddit.com/r/python" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >reddit</a>')
[<p#hello.hello>]
>>> print(p.html())
check out <a href="http://reddit.com/r/python" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >reddit</a>you know ...

在其他元素之前或者之后追加元素:

>>> d = pq('<html><body><div id="test"><a href="http://python.org" rel="external nofollow" rel="external nofollow" >python</a> !</div></body></html>')
>>> p.prependTo(d('#test'))
[<p#hello.hello>]
>>> print(d('#test').html())
<p class="hello" ...

在其他元素之后插入元素:

>>> p.insertAfter(d('#test'))
[<p#hello.hello>]
>>> print(d('#test').html())
<a href="http://python.org" rel="external nofollow" rel="external nofollow" >python</a> !

或者插入其他元素之前:

>>> p.insertBefore(d('#test'))
[<p#hello.hello>]
>>> print(d('body').html())
<p class="hello" id="hello">...

对每个元素做一些事情:

>>> p.each(lambda i, e: pq(e).addClass('hello2'))
[<p#hello.hello.hello2>]

移除一个元素:

>>> d = pq('<html><body><p id="id">Yeah!</p><p>python rocks !</p></div></html>')
>>> d.remove('p#id')
[<html>]
>>> d('p#id')
[]

移除选中元素的内容:

>>> d('p').empty()
[<p>]

你可以获得修改后的html内容:

>>> print(d)
<html><body><p/></body></html>

你可以生成html片段:

>>> from pyquery import PyQuery as pq
>>> print(pq('<div>Yeah !</div>').addClass('myclass') + pq('<b>cool</b>'))
<div class="myclass">Yeah !</div><b>cool</b>

移除所有命名空间:

>>> d = pq('<foo xmlns="http://example.com/foo"></foo>')
>>> d
[<{http://example.com/foo}foo>]
>>> d.remove_namespaces()
[<foo>]

遍历

一些jQuery遍历方法也可以支持。这里有几个例子。

你可以使用字符串选择器过滤选择列表:

>>> d = pq('<p id="hello" class="hello"><a/></p><p id="test"><a/></p>')
>>> d('p').filter('.hello')
[<p#hello.hello>]

可以使用eq选择器选中单个元素:

>>> d('p').eq(0)
[<p#hello.hello>]

你可以找出嵌套元素:

>>> d('p').find('a')
[<a>, <a>]
>>> d('p').eq(1).find('a')
[<a>]

也支持使用end从一级遍历中跳出:

>>> d('p').find('a').end()
[<p#hello.hello>, <p#test>]
>>> d('p').eq(0).end()
[<p#hello.hello>, <p#test>]
>>> d('p').filter(lambda i: i == 1).end()
[<p#hello.hello>, <p#test>]

网络 Scraping

pyquery也可以从一个url载入html文档:

>>> pq(your_url)
[<html>]

缺省使用的是python的urllib。

如果安装了requests就使用requests。你可以使用大部分requests的参数。

>>> pq(your_url, headers={'user-agent': 'pyquery'})
[<html>]
>>> pq(your_url, {'q': 'foo'}, method='post', verify=True)
[<html>]

pyquery C PyQuery完整API参见:http://pyquery.readthedocs.org/en/latest/api.html

pyquery.ajax C PyQuery AJAX 扩展

如果安装了WebOb(它并不是pyquery的依赖项目),你可以查询一些wsgi app。在本例中,测试app在/处返回一个简单的输入,在/submit处返回一个提交按钮: IN this example the test app returns a simple input at / and a submit button at /submit:

>>> d = pq('<form></form>', app=input_app)
>>> d.append(d.get('/'))
[<form>]
>>> print(d)
<form><input name="youyou" type="text" value=""/></form>

app在新节点中也可用: The app is also available in new nodes:

>>> d.get('/').app is d.app is d('form').app
True

你也可以请求另外一个路径:

>>> d.append(d.get('/submit'))
[<form>]
>>> print(d)
<form><input name="youyou" type="text" value=""/><input type="submit" value="OK"/></form>

如果安装了restkit,你就可以直接从一个HostProxy app获取url:

>>> a = d.get(your_url)
>>> a
[<html>]

你可以获取到app的响应:

>>> print(a.response.status)
200 OK

小贴士 Tips

你可以使链接转化为绝对链,在屏幕抓取时还会比较有用: You can make links absolute which can be usefull for screen scrapping:

>>> d = pq(url=your_url, parser='html')
>>> d('form').attr('action')
'/form-submit'
>>> d.make_links_absolute()
[<html>]

使用不同的解析器

缺省情况下,pyquery使用lxml xml解析器并且如果它不能工作的话,继续尝试lxml.html中的html解析器。xml解析器在解析xhtml页面时可能出现一些问题,因为解析器不会抛出一个错误,而是给出一个不能用的树。 The xml parser can sometimes be problematic when parsing xhtml pages because the parser will not raise an error but give an unusable tree (on w3c.org for example).

你也可以显式地声明使用哪一个解析器:

>>> pq('<html><body><p>toto</p></body></html>', parser='xml')
[<html>]
>>> pq('<html><body><p>toto</p></body></html>', parser='html')
[<html>]
>>> pq('<html><body><p>toto</p></body></html>', parser='html_fragments')
[<p>]

html和html_fragments解析器都在lxml.html当中。

更多关于Python相关内容感兴趣的读者可查看本站专题:《Python数据结构与算法教程》、《Python加密解密算法与技巧总结》、《Python编码操作技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

相关推荐