文章

pyquery使用指南

pyquery使用指南

PyQuery 是一个强大的 Python 库,它提供了类似 jQuery 的语法来解析和操作 HTML/XML 文档。

1. 安装 PyQuery

安装 PyQuery:

1
pip install pyquery

2. 基本用法

2.1 导入模块

1
from pyquery import PyQuery as pq

2.2 创建 PyQuery 对象

有多种方式可以创建 PyQuery 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 从字符串创建
html_string = """
<html>
    <body>
        <div id="container">
            <p class="item">第一个段落</p>
            <p class="item">第二个段落</p>
            <a href="https://example.com">链接</a>
        </div>
    </body>
</html>
"""
doc = pq(html_string)

# 从 URL 创建(自动下载)
doc = pq(url='https://example.com')

# 从文件创建
doc = pq(filename='example.html')

# 从 lxml 元素创建
from lxml import etree
element = etree.fromstring('<div>测试</div>')
doc = pq(element)

3. 选择器

PyQuery 支持 CSS 选择器语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 通过标签名选择
p_elements = doc('p')

# 通过类名选择
items = doc('.item')

# 通过 ID 选择
container = doc('#container')

# 通过属性选择
link = doc('a[href="https://example.com"]')

# 组合选择器
div_p = doc('div p')  # div 下的所有 p 元素

4. 遍历和操作元素

4.1 遍历元素

1
2
3
4
5
6
7
8
9
10
11
12
# 遍历每个元素
for item in doc('.item').items():
    print(item.text())

# 获取第一个元素
first_item = doc('.item').eq(0)

# 获取最后一个元素
last_item = doc('.item').eq(-1)

# 切片
some_items = doc('.item')[1:3]  # 获取第2和第3个元素

4.2 获取内容

1
2
3
4
5
6
7
8
9
10
11
12
13
# 获取文本内容
text = doc('.item').text()  # 所有匹配元素的文本合并
text_list = [item.text() for item in doc('.item').items()]  # 分别获取

# 获取 HTML 内容
html = doc('#container').html()

# 获取属性值
href = doc('a').attr('href')

# 获取多个属性
for a in doc('a').items():
    print(a.attr('href'), a.attr('title'))

4.3 操作 DOM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 添加元素
doc('#container').append('<p>新段落</p>')
doc('#container').prepend('<p>开头段落</p>')

# 添加类
doc('p').add_class('new-class')

# 移除类
doc('p').remove_class('item')

# 设置属性
doc('a').attr('target', '_blank')

# 设置文本
doc('p:first').text('修改后的文本')

# 设置 HTML
doc('#container').html('<div>新内容</div>')

# 移除元素
doc('p:last').remove()

# 替换元素
doc('p:first').replace_with('<span>替换内容</span>')

5. 筛选元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 过滤元素
active_items = doc('.item').filter('.active')

# 排除元素
non_active = doc('.item').not_('.active')

# 查找子元素
children = doc('#container').find('p')

# 查找直接子元素
direct_children = doc('#container').children()

# 查找父元素
parent = doc('.item').parent()

# 查找祖先元素
ancestors = doc('.item').parents()

# 查找兄弟元素
siblings = doc('.item:first').siblings()

6. 实际示例

示例 1:解析网页并提取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
from pyquery import PyQuery as pq

# 从 URL 加载
doc = pq(url='https://news.ycombinator.com')

# 提取所有新闻标题
news_items = doc('.athing')
for item in news_items.items():
    title = item.find('.titleline a').text()
    link = item.find('.titleline a').attr('href')
    print(f"标题: {title}")
    print(f"链接: {link}")
    print("-" * 50)

示例 2:处理本地 HTML 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
from pyquery import PyQuery as pq

# 从文件加载
doc = pq(filename='data.html')

# 提取表格数据
table_data = []
for row in doc('table tr').items():
    columns = [col.text() for col in row('td').items()]
    if columns:  # 跳过表头(如果表头是 th 标签)
        table_data.append(columns)

print(table_data)

示例 3:修改和生成 HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pyquery import PyQuery as pq

# 创建新的 HTML 文档
doc = pq('<html><body><div id="content"></div></body></html>')

# 添加内容
doc('#content').append('<h1>标题</h1>')
doc('#content').append('<p class="intro">介绍文本</p>')
doc('#content').append('<ul id="list"></ul>')

# 添加列表项
items = ['项目1', '项目2', '项目3']
for item in items:
    doc('#list').append(f'<li>{item}</li>')

# 添加样式
doc('head').append('<style>body { font-family: Arial; }</style>')

# 输出结果
print(doc)

7. 高级技巧

7.1 处理编码问题

1
2
3
4
5
6
7
8
# 指定编码
doc = pq(url='https://example.com', encoding='utf-8')

# 或者手动处理
import requests
response = requests.get('https://example.com')
response.encoding = 'utf-8'
doc = pq(response.text)

7.2 结合 requests 使用

1
2
3
4
5
6
7
8
9
10
11
12
import requests
from pyquery import PyQuery as pq

# 使用 requests 获取更灵活的控制
response = requests.get('https://example.com', headers={'User-Agent': 'Mozilla/5.0'})
doc = pq(response.content)  # 使用 content 避免编码问题

# 处理需要登录的页面
session = requests.Session()
session.post('https://example.com/login', data={'username': 'user', 'password': 'pass'})
response = session.get('https://example.com/dashboard')
doc = pq(response.text)

7.3 XPath 支持

虽然 PyQuery 主要使用 CSS 选择器,但也可以使用 XPath:

1
2
# 使用 XPath
elements = doc.xpath('//div[@class="content"]/p')

8. 注意事项

  1. 性能考虑:对于大规模 HTML 解析,lxml 本身非常快,但 PyQuery 的便利性会带来一些开销。
  2. 错误处理:网络请求可能失败,需要适当的异常处理。
  3. 内存使用:处理非常大的文档时,注意内存使用情况。
  4. 依赖:PyQuery 依赖于 lxml,确保已正确安装。

9. 常见问题解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 1. 处理缺失的元素
element = doc('.non-existent')
if element:  # PyQuery 对象总是真值
    print("元素存在")
else:
    print("元素不存在")

# 更好的检查方式
if len(doc('.non-existent')) > 0:
    print("元素存在")

# 2. 处理多层嵌套
# 使用 find() 而不是直接使用选择器
doc('#container').find('.item')

# 3. 保留原始文档
original_doc = pq(html_string)
modified_doc = original_doc.clone()  # 创建副本进行修改

PyQuery 是解析和操作 HTML/XML 的强大工具,特别适合熟悉 jQuery 语法的开发者。通过结合 CSS 选择器的便利性和 Python 的强大功能,可以高效地处理各种网页解析任务。

本文由作者按照 CC BY 4.0 进行授权