Python爬虫技术 第15节 CSS选择器基础

在使用Python进行网页爬取时,CSS选择器是提取HTML文档中特定元素的常用方法之一。CSS选择器基于HTML元素的结构和属性来定位和选择页面中的元素。结合Python中的BeautifulSoup库或PyQuery库等,可以非常高效地解析和筛选出你想要的数据。

CSS选择器基础

  1. 标签选择器
    使用元素名称作为选择器,如 diva

  2. 类选择器
    使用点前缀加上类名,如 .classname

  3. ID选择器
    使用井号前缀加上ID名,如 #idname

  4. 属性选择器
    可以选择具有特定属性的元素,如 [href][class="myclass"]

  5. 子元素选择器
    用于选择某个元素的直接子元素,如 ul > li

  6. 后代选择器
    用于选择某个元素的所有后代元素,如 div p(选择所有在div内的p标签)。

  7. 相邻兄弟选择器
    用于选择紧接在另一个元素后的元素,如 h1 + p

  8. 一般兄弟选择器
    用于选择同级的元素,如 h1 ~ p

  9. 组合选择器
    可以将多个选择器用逗号分隔,如 div, span

在Python中使用CSS选择器

使用BeautifulSoup

假设你有以下HTML代码:

<div id="content"><h1>My Title</h1><p class="description">This is a description.</p><ul><li>Item 1</li><li>Item 2</li></ul>
</div>

使用BeautifulSoup来解析并提取数据:

from bs4 import BeautifulSouphtml_doc = """
<div id="content"><h1>My Title</h1><p class="description">This is a description.</p><ul><li>Item 1</li><li>Item 2</li></ul>
</div>
"""soup = BeautifulSoup(html_doc, 'html.parser')# 获取标题
title = soup.select_one('h1').text
print("Title:", title)# 获取描述
description = soup.select_one('.description').text
print("Description:", description)# 获取列表项
items = [item.text for item in soup.select('li')]
print("Items:", items)
使用PyQuery

PyQuery库的使用方式更接近jQuery:

from pyquery import PyQuery as pqhtml_doc = """
<div id="content"><h1>My Title</h1><p class="description">This is a description.</p><ul><li>Item 1</li><li>Item 2</li></ul>
</div>
"""doc = pq(html_doc)# 获取标题
title = doc('h1').text()
print("Title:", title)# 获取描述
description = doc('.description').text()
print("Description:", description)# 获取列表项
items = doc('li').map(lambda i, e: pq(e).text())
print("Items:", list(items))

以上就是使用CSS选择器结合Python进行网页数据抓取的基本方法。通过这些工具,你可以更加灵活和精确地从网页中提取所需信息。

当然,我们可以处理更复杂的HTML结构、使用更多的CSS选择器以及处理可能出现的异常情况。下面是一个更详细的示例,展示如何使用BeautifulSoup和PyQuery处理一个包含更多元素和属性的HTML文档。

假设我们有以下HTML结构:

<html>
<head><title>Sample Page</title>
</head>
<body><div id="header"><h1>Welcome to Our Site</h1></div><div id="content"><section class="main"><article class="post" data-id="1"><h2>Post Title 1</h2><p>Some text here...</p><a href="/post/1" class="read-more">Read more</a></article><article class="post" data-id="2"><h2>Post Title 2</h2><p>Some other text here...</p><a href="/post/2" class="read-more">Read more</a></article></section><aside><h3>Latest Comments</h3><ul><li>User 1 commented on Post 1</li><li>User 2 commented on Post 2</li></ul></aside></div><footer><p>Copyright © 2024</p></footer>
</body>
</html>

我们将使用这个HTML结构来演示如何提取特定的帖子标题、文本和链接。

使用BeautifulSoup
from bs4 import BeautifulSouphtml_doc = """
<html>
<head><title>Sample Page</title>
</head>
<body><div id="header"><h1>Welcome to Our Site</h1></div><div id="content"><section class="main"><article class="post" data-id="1"><h2>Post Title 1</h2><p>Some text here...</p><a href="/post/1" class="read-more">Read more</a></article><article class="post" data-id="2"><h2>Post Title 2</h2><p>Some other text here...</p><a href="/post/2" class="read-more">Read more</a></article></section><aside><h3>Latest Comments</h3><ul><li>User 1 commented on Post 1</li><li>User 2 commented on Post 2</li></ul></aside></div><footer><p>Copyright © 2024</p></footer>
</body>
</html>
"""soup = BeautifulSoup(html_doc, 'html.parser')# 提取所有帖子的标题
titles = [post.h2.text for post in soup.select('.post')]
print("Titles:", titles)# 提取所有帖子的链接
links = [post.a['href'] for post in soup.select('.post .read-more') if 'href' in post.a.attrs]
print("Links:", links)# 提取第一个帖子的文本
first_post_text = soup.select_one('.post:first-of-type p').text
print("First Post Text:", first_post_text)# 检查是否有最新评论
latest_comments = soup.select_one('#content aside ul')
if latest_comments:print("Latest Comments Found!")
else:print("No latest comments found.")
使用PyQuery
from pyquery import PyQuery as pqhtml_doc = """
<html>
<!-- HTML content here -->
</html>
"""doc = pq(html_doc)# 提取所有帖子的标题
titles = doc('.post h2').map(lambda i, e: pq(e).text())
print("Titles:", list(titles))# 提取所有帖子的链接
links = doc('.post .read-more').map(lambda i, e: pq(e).attr('href'))
print("Links:", list(links))# 提取第一个帖子的文本
first_post_text = doc('.post:first-of-type p').text()
print("First Post Text:", first_post_text)# 检查是否有最新评论
latest_comments = doc('#content aside ul')
if latest_comments.length:print("Latest Comments Found!")
else:print("No latest comments found.")

以上代码展示了如何使用CSS选择器与Python库来处理和提取复杂HTML文档中的信息。注意,在实际应用中,你可能需要处理网络请求错误、HTML解析错误或页面结构不一致的情况,因此在真实环境中,你可能需要添加更多的错误检查和异常处理逻辑。

接下来,我们可以添加异常处理机制,确保在遇到网络错误、无效的HTML结构或者缺少预期元素时,程序能够优雅地处理这些情况。同时,我们还可以增强代码的健壮性,例如通过使用更具体的CSS选择器来减少误匹配的可能性,并且在处理大量数据时考虑性能优化。

以下是使用BeautifulSoup和PyQuery对上述HTML代码进行数据提取的改进版代码:

使用BeautifulSoup
from bs4 import BeautifulSoup
import requestsdef fetch_data(url):try:response = requests.get(url)response.raise_for_status()  # 如果响应状态码不是200,则抛出HTTPError异常return response.textexcept requests.RequestException as e:print(f"Error fetching URL: {url}")print(e)return Nonedef parse_html(html):if html is None:return []soup = BeautifulSoup(html, 'html.parser')posts = []for post in soup.select('.post'):try:title = post.h2.text.strip()text = post.p.text.strip()link = post.find('a', class_='read-more')['href']posts.append({'title': title,'text': text,'link': link})except AttributeError:print("Missing element in post, skipping...")continuereturn postsdef main():url = "http://example.com"html = fetch_data(url)posts = parse_html(html)print(posts)if __name__ == "__main__":main()
使用PyQuery
from pyquery import PyQuery as pq
import requestsdef fetch_data(url):try:response = requests.get(url)response.raise_for_status()return response.textexcept requests.RequestException as e:print(f"Error fetching URL: {url}")print(e)return Nonedef parse_html(html):if html is None:return []doc = pq(html)posts = []doc('.post').each(lambda i, e: posts.append({'title': pq(e)('h2').text(),'text': pq(e)('p').text(),'link': pq(e)('a.read-more').attr('href')}) if pq(e)('h2') and pq(e)('p') and pq(e)('a.read-more') else None)return [post for post in posts if post is not None]def main():url = "http://example.com"html = fetch_data(url)posts = parse_html(html)print(posts)if __name__ == "__main__":main()

在这两个示例中,我们做了如下改进:

  • 添加了网络请求函数fetch_data,它会处理网络错误和HTTP错误。
  • parse_html函数中,我们添加了对缺失元素的异常处理,避免因为某个元素不存在而导致整个程序崩溃。
  • 使用了strip()方法来去除文本中的空白字符,保证数据的整洁。
  • 在使用PyQuery时,使用了.each()方法来迭代每个.post元素,这样可以更自然地处理每个帖子的提取过程,并且通过列表推导式过滤掉任何可能为None的帖子。

这些改进使得代码更加健壮,能够在面对各种意外情况时给出适当的反馈,而不是突然崩溃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/876019.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【H.264】H.264详解(二)—— H264视频码流解析示例源码

文章目录 一、前言二、示例源码【1】目录结构【2】Makefile源码【3】h264parser.c源码【4】编译运行【5】源码下载地址 声明&#xff1a;此篇示例源码非原创&#xff0c;原作者雷霄骅。雷霄骅&#xff0c;中国传媒大学通信与信息系统专业博士生&#xff0c;在此向雷霄骅雷神致敬…

OpenHarmony 开发

本心、输入输出、结果 文章目录 OpenHarmony 开发前言JonathanOpenHarmony 并不是 AndroidOpenHarmony 应用迁移OpenHarmony 的开发流程OpenHarmony 开发 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csdn.net/qq_15071263 如果觉得本文对你有帮助,欢迎点赞、收藏、评…

2023IMO预选题几何第6题

锐角 △ A B C \triangle ABC △ABC 的外接圆为 ω \omega ω, 圆 I I I 与 ω \omega ω 内切于 A A A, 且与 B C BC BC 切于点 D D D. 设直线 A B AB AB, A C AC AC 分别与 I I I 交于点 P P P, Q Q Q, 点 M M M, N N N 在直线 B C BC BC 上, 满足 B B B 是 …

CeoMax总裁主题最新3.8.1破解免授权版/WordPress付费资源素材下载主题

CeoMax总裁主题最新3.8.1破解免授权版&#xff0c;一套WordPress付费资源素材下载的主题&#xff0c;感觉这是做资源站唯一一个可以和ripro媲美甚至超越的模板&#xff0c;UI很美&#xff0c;功能也很强大&#xff0c;有想学习的可下载搭建学习一下&#xff0c;仅供学习研究借鉴…

仿学校网页

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,initial-scale1.0"><title>学校网页</title> <style>.WebTop{backg…

誉天网络安全课程怎么样

学员服务质量保障讲师团队&#xff1a;平均5年课程交付经验&#xff0c;授课质量有保障辅导团队&#xff1a;实验论述辅导讲师&#xff0c;实验备考环境复刻&#xff0c;备考资料完善&#xff0c;及时更新就业服务&#xff1a;简历制作培训&#xff0c;面试技巧培训&#xff0c…

昇思MindSpore学习入门-轻量化数据处理

在资源条件允许的情况下&#xff0c;为了追求更高的性能&#xff0c;一般使用Pipeline模式执行数据变换Transforms。 基于Pipeline模式执行的最大特点是需要使用map方法&#xff0c;如下图中将Resize、Crop、HWC2CHW交由map调度&#xff0c;由其负责启动和执行给定的Transform…

R语言统计分析——控制流

参考资料&#xff1a;R语言实战【第2版】 语句&#xff08;statement&#xff09;是一条单独的R语言或一组复合语言&#xff08;包含在花括号{}中的一组R语言&#xff0c;使用分号分隔&#xff09; 条件&#xff08;cond&#xff09;是一条最终被解析为真&#xff08;TRUE&…

python黑马笔记

运算符&#xff1a; 算术运算符&#xff1a; 加 - 减 * 乘 / 除 // 整除 % 取余 ** 求平方 除法计算得出的结果都是小数 赋值运算符&#xff1a; 标准赋值&#xff1a; 复合赋值&#xff1a; 、 - 、 * 、 / 、// 、 ** 字符串&#xff1a; 字符串拓展内容&#xf…

护网紧急情况应对指南:Linux 应急响应手册

继上一篇&#xff1a;护网紧急情况应对指南&#xff1a;Windows版v1.2全新升级版 之后 收到小伙伴后台要Linux应急手册&#xff0c;今天给大家安排上。 《Linux应急手册》是一本为Linux系统管理员和运维工程师量身打造的实用指南&#xff0c;旨在帮助他们快速应对各种突发状况…

基于FFMPEG和SDL的音视频解码播放的实现过程与相关细节

目录 1、视频播放器原理 2、FFMPEG解码 2.1 FFMPEG库 2.2、数据类型 2.3、解码 2.3.1、接口函数 2.3.2、解码流程 3、SDL播放 3.1、接口函数 3.2、视频播放 3.3、音频播放 4、音视频的同步 4.1、获取音频的播放时间戳 4.2、获取当前视频帧时间戳 4.3、获取视…

MATLAB仿真:数字信号处理用FFT对信号分析

目录 1.实验目的 2 实验原理 3.实验仪器及设备 4.实验步骤及内容 (1)对以下序列进行谱分析。 (2)对以下周期序列进行谱分析。 (3)对模拟周期信号进行谱分析 1.实验目的 学习用 FFT 对连续信号和时域离散信号进行谱分析的方法,了解可能出现的分析误差及其原因,…

CAS算法

CAS算法 1. CAS简介 CAS叫做CompareAndSwap&#xff0c;比较并交换&#xff0c;主要是通过处理器的指令来保证操作的原子性。 CAS基本概念 内存位置 (V)&#xff1a;需要进行CAS操作的内存地址。预期原值 (A)&#xff1a;期望该内存位置上的旧值。新值 (B)&#xff1a;如果旧…

The Llama 3 Herd of Models.Llama 3 模型论文全文

现代人工智能(AI)系统是由基础模型驱动的。本文提出了一套新的基础模型,称为Llama 3。它是一组语言模型,支持多语言、编码、推理和工具使用。我们最大的模型是一个密集的Transformer,具有405B个参数和多达128K个tokens的上下文窗口。本文对Llama 3进行了广泛的实证评价。我们…

DNS 污染/毒化——华为ensp

实验原理:1&#xff0c;用户正常访问 Web页面&#xff0c;会查询本地DNS服务器&#xff0c;一般情况下&#xff0c;本地DNS服务器会设置为 网关地址。2&#xff0c; 攻击者在 用户和网关之间&#xff0c;开启ARP攻击即可&#xff0c;这样&#xff0c;就可以让 用户访问本地DNS服…

【Ant Design Pro】快速上手

初始化 初始化脚手架&#xff1a;快速开始 官方默认使用 umi4&#xff0c;这里文档还没有及时更新&#xff08;不能像文档一样选择 umi 的版本&#xff09;&#xff0c;之后我选择 simple。 然后安装依赖。 在 package.json 中&#xff1a; "start": "cross-e…

卷积的意义及其派生(一)

1.卷积的意义 1.1从LTI的角度看 卷积最开始其实是信号处理中用来描述线性移不变系统Linear time-invariant systems的。线性&#xff0c;表明可以叠加&#xff0c;信号可以拆分成脉冲的响应&#xff1b;时不变&#xff0c;指信号不随着时间的迁移改变&#xff0c;意味着能量守…

【iOS】——通知机制及底层原理

通知传值概要 通知传值可以跨越多个界面进行传值&#xff0c;一般用于后一个界面向前一个界面传值。 通知传值支持多个接收者&#xff0c;多个对象可以同时接收同一个通知并进行处理。这样可以实现一对多的通信&#xff0c;方便跨多个对象进行值传递。 使用步骤 1.在发送者中…

Latent Factor Analysis via Dynamical Systems:LFADS (Nature methods 2018)

Nature Methods&#xff1a;https://www.nature.com/articles/s41592-018-0109-9 LFADS Run Manager for Matlab&#xff1a;https://lfads.github.io/lfads-run-manager/ 目录 Single session:假设&#xff1a;方法&#xff1a;结果&#xff1a; Multi-sessions:假设&#xff…

【C++】位运算:两整数之和

1.题目 2.算法思路 本题不能只用 -&#xff0c;那大概率用到位运算符。 异或的作用是无进位相加&#xff0c;所以需要通过异或运算&#xff08;^&#xff09;来替代加法运算&#xff0c;但是我们无法确定进位的信息。所以需要与运算&#xff08;&&#xff09;来得到进位的…