AIGC标识 pyquery和parsel

pyquery 库和 parsel 的使用笔记

说明:示例中的 html 变量沿用前文定义;单独运行某段代码时,请先定义对应的 html 字符串。原笔记中的本地截图路径已省略,发布时可替换为图床图片。

一、pyquery

图示:pyquery 安装/使用示意(原笔记截图,略)

1. 准备工作

在终端中运行:

pip install pyquery

2. 初始化

初始化简单来说就是:创建一个对象,并给它赋予初始状态的过程。

2.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'))

2.2 URL 初始化

from pyquery import PyQuery as pq

doc = pq(url='https://cuiqingcai.com')
print(doc('title'))

2.3 文件初始化

from pyquery import PyQuery as pq

doc = pq(filename='demo.html')
print(doc('li'))

3. 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'))
print(type(doc('#container .list li')))

for item in doc('#container .list li').items():
    print(item.text())

4. 子节点与父节点

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)

说明:

  • find():查找所有子孙节点。
  • children():只查找直接子节点。
  • parent():查找父节点。
  • parents():查找祖先节点。

5. 兄弟节点

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)
li = doc('.list .item-0.active')
print(li.siblings())

说明:siblings() 用于获取兄弟节点,默认不包含当前节点自身。

6. 节点操作

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)
li = doc('.item-0.active')
print(li)

li.remove_class("active")
print(li)

li.add_class("active")
print(li)

这里主要使用 remove_class() 和 add_class() 来增删 class 属性。

7. attr、text、html

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)
li = doc('.item-0.active')
print(li)

li.attr('name', 'link')
print(li)

li.text('change World')
print(li)

li.html('<span>change World</span>')
print(li)

说明:

  • attr():修改属性;传一个参数时通常用于获取属性,传两个参数时用于设置属性。
  • text():修改文本内容。
  • html():修改内部 HTML 标签及内容。

8. 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())

上面代码删除了 p 节点,只保留 .wrap 中的其他文本内容。

9. 伪类选择器

from pyquery import PyQuery as pq

doc = pq(html)

li = doc('li:first-child')
print(li)

li = doc('li:last-child')
print(li)

li = doc('li:gt(2)')
print(li)

li = doc('li:nth-child(2n)')
print(li)

li = doc('li:contains(second)')
print(li)

伪类选择器是 CSS 中的概念,用于根据元素的“位置”或“状态”提取元素。上面的示例分别选取:

  • 第一个 li;
  • 最后一个 li;
  • 索引大于 2 的 li(即第三个之后的节点,注意索引从 0 开始);
  • 偶数位置的 li;
  • 文本中包含 second 的 li。

其中 :gt() 属于 jQuery/pyquery 风格的扩展伪类,不是标准 CSS 选择器。

10. 常见报错:忘记加 .items()

图示:忘记加 .items() 时的报错截图(原笔记截图,略)

如果忘记加 .items(),可能会产生类似“字符串不能被调用”的类型错误。正确写法如下:

for item in doc('li').items():
    print(item.text())

.items() 的核心作用是:当提取到多个元素后,在 for 循环遍历它们时,把每一个单独的节点重新包装成 PyQuery 对象,从而能够继续使用 PyQuery 的全部方法。


二、parsel

图示:parsel 使用示意(原笔记截图,略)

1. 准备工作

pip install parsel

2. Selector

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 parsel import Selector

selector = Selector(text=html)

items = selector.css('.item-0')
print(len(items), type(items), items)

items2 = selector.xpath('//li[contains(@class, "item-0")]')
print(len(items2), type(items2), items2)

说明:contains(@class, "item-0") 表示只要 class 属性中包含 "item-0" 这个字符串,就算匹配成功。需要注意,class 是空格分隔的多值属性,contains() 是子串匹配;如果需要精确匹配某个 class,可使用 CSS 选择器或更严格的 XPath 写法。

3. 提取文本

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 parsel import Selector

selector = Selector(text=html)
items = selector.css('.item-0')

for item in items:
    text = item.xpath('.//text()').get()
    print(text)

说明:.get() 用于获取第一个匹配结果;如果需要获取全部结果,应使用 .getall()。

提取所有文本

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 parsel import Selector

selector = Selector(text=html)
result = selector.xpath('//li[contains(@class, "item-0")]//text()').getall()
print(result)

同样,也可以使用 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 parsel import Selector

selector = Selector(text=html)
result = selector.css('.item-0 *::text').getall()
print(result)

说明:这里的 * 用于匹配后代元素,::text 用于提取文本节点。如果希望确保提取元素自身的直接文本和所有后代文本,优先使用 XPath 的 .//text() 写法。

4. 属性提取

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 parsel import Selector

doc = Selector(text=html)

result = doc.css('.item-0.active a::attr(href)').get()
print(result)

result = doc.xpath('//li[contains(@class, "item-0") and contains(@class, "active")]/a/@href').get()
print(result)

说明:

  • CSS 选择器选取属性需要加 ::attr(),并传入对应属性名称。
  • XPath 中直接用 /@属性名 即可选取属性。
  • 最后统一使用 get() 提取单个结果,或使用 getall() 提取全部结果。

5. 正则提取

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 parsel import Selector

doc = Selector(text=html)

# 提取所有包含 link 的结果
result = doc.css('.item-0').re('link.*')
print(result)

# 提取所有匹配 .*item 的文本结果
result = doc.css('.item-0 *::text').re('.*item')
print(result)

# re_first 提取第一个匹配结果;小括号表示捕获分组,输出捕获分组中的内容
result = doc.css('.item-0').re_first('<span class="bold">(.*?)</span>')
print(result)

说明:如果在调用 CSS 方法时已经提取了进一步的结果,例如提取了节点文本值,那么 re() 方法只会针对这些结果进行正则提取。re() 返回列表,re_first() 返回第一个匹配结果;若正则中包含捕获分组,返回内容会对应捕获分组。


三、额外补充:正则表达式速查

1. 限定符

写法 含义
a* a 出现 0 次或多次
a+ a 出现 1 次或多次
a{6} a 出现 6 次
a{2,6} a 出现 2 到 6 次
a{2,} a 出现 2 次以上

2. 或运算符

写法 含义
`(a b)`
`(ab) (cd)`

3. 字符类

写法 含义
[abc] 匹配 a 或 b 或 c
[a-c] 同上,匹配 a 到 c
[a-fA-F0-9] 匹配小写字母、大写字母和数字
[^0-9] 匹配非数字字符

4. 元字符

写法 含义
\d 匹配数字字符
\D 匹配非数字字符
\w 匹配单词字符(英文、数字、下划线)
\W 匹配非单词字符
\s 匹配空白符(Tab 键、换行符等)
\S 匹配非空白字符
. 匹配任意字符(换行符除外)
\bword\b 标定字符边界
^ 匹配行首
$ 匹配行尾

5. 贪婪匹配与懒惰匹配

写法 含义
<.+> 默认贪婪匹配“任意字符”
<.+?> 懒惰匹配“任意字符”

四、简单总结

库 特点 常用方法
pyquery 类似 jQuery 的链式操作,节点查找和修改较方便 pq()、find()、items()、attr()、text()、html()、add_class()、remove_class()
parsel 常用于 Scrapy,支持 CSS 与 XPath,结果通常为 SelectorList Selector(text=...)、css()、xpath()、get()、getall()、re()、re_first()
posted @ 2026-10-19 21:25  洛奈chs  阅读(2)  评论(0)    收藏  举报