Python爬虫技术 第17节 使用BeautifulSoup

使用Python进行网页爬取是一个常见的任务,特别是当需要从网站上批量获取数据时。BeautifulSoup是一个非常流行的Python库,用于解析HTML和XML文档,非常适合用来提取网页中的信息。

下面我将通过一个简单的案例来介绍如何使用Python和BeautifulSoup来抓取网页上的数据。

安装依赖库

首先确保你安装了requestsbeautifulsoup4这两个库。如果还没有安装,可以通过pip来安装:

pip install requests beautifulsoup4

示例代码

假设我们想要从一个新闻网站上抓取最新的头条新闻标题。这里以一个虚构的新闻网站为例。

1. 导入必要的库
import requests
from bs4 import BeautifulSoup
2. 发送HTTP请求

我们需要向目标网站发送一个GET请求,并获取响应的内容。

url = 'https://example.com/news'  # 假设这是我们要爬取的新闻网站URL
response = requests.get(url)
html_content = response.text
3. 解析HTML文档

接下来,我们使用BeautifulSoup来解析HTML文档。

soup = BeautifulSoup(html_content, 'html.parser')
4. 提取所需的数据

假设我们想要获取所有的新闻标题,这些标题通常会被包含在一个特定的HTML标签中,比如<h2>或者<a>标签内。

titles = soup.find_all('h2', class_='news-title')  # 这里的class_='news-title'是假设的类名,请根据实际情况调整
for title in titles:print(title.text.strip())

完整示例

让我们把上述代码整合到一个完整的脚本中:

import requests
from bs4 import BeautifulSoupdef fetch_news_titles(url):response = requests.get(url)if response.status_code == 200:soup = BeautifulSoup(response.text, 'html.parser')titles = soup.find_all('h2', class_='news-title')return [title.text.strip() for title in titles]else:print(f"Failed to retrieve data from {url}")return []if __name__ == '__main__':url = 'https://example.com/news'news_titles = fetch_news_titles(url)for title in news_titles:print(title)

注意事项

  • 在实际使用中,你需要替换上面示例中的URL为真实的新闻网站URL,并且可能需要调整CSS选择器或HTML标签来匹配实际网站的结构。
  • 有些网站可能使用JavaScript动态加载内容,这种情况下直接抓取HTML可能无法获取所有数据。此时可以考虑使用像Selenium这样的工具。
  • 记得遵守目标网站的robots.txt文件规定以及相关法律法规,尊重网站的版权和数据使用政策。

接下来我们可以进一步扩展之前的案例,使其能够处理更复杂的网页结构,并添加一些额外的功能,如错误处理、日志记录等。此外,还可以增加对动态加载内容的支持。

扩展案例

1. 错误处理与日志记录

在实际爬虫项目中,错误处理非常重要。我们应该考虑到网络连接失败、服务器返回错误、网页结构变化等情况。同时,良好的日志记录可以帮助我们追踪程序运行的状态和问题。

2. 处理动态加载的内容

有些网站使用JavaScript来动态加载内容,这使得直接抓取HTML变得不够全面。在这种情况下,我们可以使用Selenium来模拟浏览器行为。

3. 存储数据

最后,我们需要考虑如何存储抓取的数据。这里我们可以简单地将其写入文本文件或数据库。

示例代码

1. 引入必要的库
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import logging
import time
2. 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
3. 定义函数来抓取静态内容
def fetch_static_content(url):try:logger.info(f"Fetching static content from: {url}")response = requests.get(url)response.raise_for_status()  # 抛出HTTP错误(如404)return response.textexcept requests.RequestException as e:logger.error(f"Error fetching content: {e}")return None
4. 定义函数来抓取动态加载的内容
def fetch_dynamic_content(url):options = webdriver.ChromeOptions()options.add_argument('--headless')  # 无头模式运行service = Service('path/to/chromedriver')  # 指定chromedriver路径driver = webdriver.Chrome(service=service, options=options)try:logger.info(f"Fetching dynamic content from: {url}")driver.get(url)# 假设有一个“加载更多”按钮需要点击load_more_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "load-more")))load_more_button.click()# 等待新内容加载完成time.sleep(3)# 获取页面源码html_content = driver.page_sourcereturn html_contentexcept Exception as e:logger.error(f"Error fetching dynamic content: {e}")return Nonefinally:driver.quit()
5. 定义函数来解析内容并提取数据
def parse_and_extract_data(html_content):if not html_content:return []soup = BeautifulSoup(html_content, 'html.parser')# 假设新闻标题都在<h2>标签里,并且有特定的class属性titles = soup.find_all('h2', class_='news-title')news_items = [{'title': title.text.strip()} for title in titles]return news_items
6. 定义主函数
def main():url = 'https://example.com/news'# 静态内容抓取static_html = fetch_static_content(url)static_news_items = parse_and_extract_data(static_html)logger.info("Static content parsed.")# 动态内容抓取dynamic_html = fetch_dynamic_content(url)dynamic_news_items = parse_and_extract_data(dynamic_html)logger.info("Dynamic content parsed.")# 合并数据all_news_items = static_news_items + dynamic_news_items# 写入文件with open('news_items.txt', 'w', encoding='utf-8') as f:for item in all_news_items:f.write(f"{item['title']}\n")logger.info("Data saved to file.")if __name__ == '__main__':main()

注意事项

  • 在使用Selenium时,确保已经安装了ChromeDriver,并将其路径设置正确。
  • 请根据实际网站结构调整CSS选择器或HTML标签。
  • 如果网站有反爬措施,可能还需要添加其他策略,例如使用代理、设置合理的延时等。

以上就是一个更完整的示例,它包含了错误处理、日志记录、动态内容抓取等功能。如果你有任何疑问或需要进一步的帮助,请随时告诉我!

我们可以进一步优化代码,使其更加健壮和高效。以下是一些改进点:

  1. 异常处理和重试机制:在网络不稳定的情况下,可以添加重试逻辑来提高爬虫的稳定性。
  2. 异步请求:使用异步IO来并发处理多个请求,提高爬虫效率。
  3. 更详细的日志记录:记录更多的信息以便于调试和监控。
  4. 更优雅的退出机制:确保在发生错误时,程序能够安全地结束。

下面是优化后的代码示例:

1. 异步请求

我们将使用asyncioaiohttp来进行异步请求,以提高效率。

2. 重试机制

对于网络请求,我们可以添加重试机制,以应对偶尔的网络波动。

3. 日志记录

我们将使用更详细的日志记录,包括请求状态、异常信息等。

4. 安全退出

确保在发生错误时,程序能够安全地结束。

示例代码

1. 安装额外依赖
pip install aiohttp
2. 更新导入模块
import asyncio
import logging
from bs4 import BeautifulSoup
from aiohttp import ClientSession, ClientResponseError
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
3. 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
4. 定义异步请求函数
async def fetch(session, url, max_retries=3):for retry in range(max_retries):try:async with session.get(url) as response:response.raise_for_status()logger.info(f"Fetched {url} successfully.")return await response.text()except ClientResponseError as e:logger.warning(f"Failed to fetch {url}, status code: {e.status}. Retrying...")except Exception as e:logger.error(f"Error fetching {url}: {e}. Retrying...")await asyncio.sleep(2 * (retry + 1))  # Exponential backofflogger.error(f"Failed to fetch {url} after {max_retries} retries.")return None
5. 定义异步抓取静态内容函数
async def fetch_static_content(url, session):html_content = await fetch(session, url)return html_content
6. 定义抓取动态内容函数
def fetch_dynamic_content(url):options = webdriver.ChromeOptions()options.add_argument('--headless')  # 无头模式运行service = Service('path/to/chromedriver')  # 指定chromedriver路径driver = webdriver.Chrome(service=service, options=options)try:logger.info(f"Fetching dynamic content from: {url}")driver.get(url)# 假设有一个“加载更多”按钮需要点击load_more_button = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "load-more")))load_more_button.click()# 等待新内容加载完成time.sleep(3)# 获取页面源码html_content = driver.page_sourcereturn html_contentexcept Exception as e:logger.error(f"Error fetching dynamic content: {e}")return Nonefinally:driver.quit()
7. 定义解析内容并提取数据函数
def parse_and_extract_data(html_content):if not html_content:return []soup = BeautifulSoup(html_content, 'html.parser')# 假设新闻标题都在<h2>标签里,并且有特定的class属性titles = soup.find_all('h2', class_='news-title')news_items = [{'title': title.text.strip()} for title in titles]return news_items
8. 定义主函数
async def main():url = 'https://example.com/news'async with ClientSession() as session:# 静态内容抓取static_html = await fetch_static_content(url, session)static_news_items = parse_and_extract_data(static_html)logger.info("Static content parsed.")# 动态内容抓取dynamic_html = fetch_dynamic_content(url)dynamic_news_items = parse_and_extract_data(dynamic_html)logger.info("Dynamic content parsed.")# 合并数据all_news_items = static_news_items + dynamic_news_items# 写入文件with open('news_items.txt', 'w', encoding='utf-8') as f:for item in all_news_items:f.write(f"{item['title']}\n")logger.info("Data saved to file.")if __name__ == '__main__':asyncio.run(main())

注意事项

  • 确保安装了aiohttp库。
  • 调整fetch函数中的重试次数和等待时间以适应你的需求。
  • 如果使用Selenium,确保已经安装了ChromeDriver,并将其路径设置正确。
  • 请根据实际网站结构调整CSS选择器或HTML标签。

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

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

相关文章

Skyeye云智能制造企业版源代码全部开放

智能制造一体化管理系统 [SpringBoot2 - 快速开发平台]&#xff0c;适用于制造业、建筑业、汽车行业、互联网、教育、政府机关等机构的管理。包含文件在线操作、工作日志、多班次考勤、CRM、ERP 进销存、项目管理、EHR、拖拽式生成问卷、日程、笔记、工作计划、行政办公、薪资模…

vue3 快速入门 (六) : vue中调用HTTP请求

1. 本文环境 Vue版本 : 3.4.29Node.js版本 : v20.15.0系统 : Windows11 64位IDE : VsCode 1.91.0 2. 访问HTTP 在Vue中&#xff0c;访问HTTP&#xff0c;可以使用axios第三方库。 axios 是一个基于 promise 的网络请求库&#xff0c;可以用于浏览器和 node.js。 axios使用简…

DelegateExecution和EXecution有啥区别

DelegateExecution 和 Execution 都是 Activiti 引擎中用于表示流程实例的执行对象&#xff0c;但它们在具体使用上有一些区别&#xff1a; DelegateExecution • 接口&#xff1a;DelegateExecution 是一个接口&#xff0c;继承自 VariableScope 接口。它主要在扩展点&#…

遗传算法与深度学习实战——进化深度学习

遗传算法与深度学习实战——进化深度学习 0. 前言1. 进化深度学习1.1 进化深度学习简介1.2 进化计算简介 2. 进化深度学习应用场景3. 深度学习优化3.1 优化网络体系结构 4. 通过自动机器学习进行优化4.1 自动机器学习简介4.2 AutoML 工具 5. 进化深度学习应用5.1 模型选择&…

【mybatis的批量操作】

在日常开发中&#xff0c;如果要操作数据库的话&#xff0c;或多或少都会遇到批量数据的处理&#xff0c;我们公司使用的mybaits-plus作为持久层的框架&#xff0c;今天就简单介绍一下mybaits批量操作数据库的几种方式。 1.循环插入 其实这种方式并不是批量插入&#xff0c;只…

功能实现——使用 OpenPDF 将 HTML 转换为 PDF,并将其上传到 FTP 服务器

目录 1.需求分析2.项目环境搭建3.将 HTML 转换为 PDF3.1.代码实现mail.htmlHtmlToPDFController.javaPDFConverterService.javaPDFConverterServiceImpl.java 3.2.测试3.3.注意事项 4.将生成的 PDF 上传到 FTP 服务器4.1.搭建 FTP 服务器4.2.配置文件4.3.代码实现FtpUtil.javaF…

谷粒商城实战笔记-75-商品服务-API-品牌管理-品牌分类关联与级联更新

文章目录 一&#xff0c;引入Mybatis Plus分页插件二&#xff0c;品牌列表的模糊查询三&#xff0c;增加品牌测试数据四&#xff0c;开发后台品牌关联分类接口1&#xff0c;接口product/categorybrandrelation/catelog/list2&#xff0c;接口product/categorybrandrelation/sav…

拓扑排序与有向无环图 -- Kahn算法和深度优先搜索

拓扑排序与有向无环图 文章目录 拓扑排序与有向无环图1. 什么是拓扑排序快速排序&#xff08;Quick Sort&#xff09;拓扑排序&#xff08;Topological Sort&#xff09;主要区别 2. 拓扑排序与有向无环图之间的契合性3. Kahn算法实现拓扑排序算法思想算法步骤算法代码 4. 深度…

线性回归从零实现

《李沐动手学深度学习》P30 import numpy as np import matplotlib.pyplot as plt import random# y x * w b noise # x dimension: (num_samples, 2) # w dimension: (2, 1) # b dimension: (1, 1) # noise dimension: (num_samples, 1) def generate_data(num_samples, w…

汽车长翅膀:GPU 是如何加速深度学习模型的训练和推理过程的?

编者按&#xff1a;深度学习的飞速发展离不开硬件技术的突破&#xff0c;而 GPU 的崛起无疑是其中最大的推力之一。但你是否曾好奇过&#xff0c;为何一行简单的“.to(‘cuda’)”代码就能让模型的训练速度突飞猛进&#xff1f;本文正是为解答这个疑问而作。 作者以独特的视角&…

数仓架构解析(第45天)

系列文章目录 经典数仓架构传统离线大数据架构 文章目录 系列文章目录烂橙子-终生成长群群主前言1. 经典数仓架构2. 传统离线大数据架构 烂橙子-终生成长群群主 前言 经典数仓架构 传统离线大数据架构 背景解析 1. 经典数仓架构 1991年&#xff0c;比尔恩门&#xff08;Bill…

Python 中 Caffe 库的使用方法

Caffe 是一个由伯克利视觉与学习中心 (Berkeley Vision and Learning Center, BVLC) 开发的深度学习框架。它特别适用于图像分类和图像分割任务。以下是一个关于如何使用 Caffe 库的详细指南&#xff0c;包括安装、配置、构建和训练模型的步骤。 1. 安装 Caffe 安装 Caffe 可以…

Pinokio:一键安装开源 AI 应用

整合了几乎所有市面上开源的 AI 工具傻瓜式地一键安装AI 工具支持全平台&#xff1a;Windows、Mac、Linux官网&#xff1a;https://pinokio.computer项目仓库&#xff1a;GitHub - pinokiocomputer/pinokio: AI Browser文章地址&#xff1a;https://blog.i68.ltd/archives/Pino…

牛客算法题解:数字统计、两个数组的交集、点击消除

目录 BC153 [NOIP2010]数字统计 ▐ 题解 NC313 两个数组的交集 ▐ 题解 AB5 点击消除 ▐ 题解 BC153 [NOIP2010]数字统计 题目描述&#xff1a; 题目链接&#xff1a; [NOIP2010]数字统计_牛客题霸_牛客网 (nowcoder.com) ▐ 题解 题目要求统计出某段数组中一共有多少个…

关于Buffer和Channel的注意事项和细节

1.举例 package org.example.demo;import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.RandomAccess;/*** MappedByteBuffer可…

Linux入门级常用命令行(二)

目录 1、mv指令 2、rm指令 3、通配符* 4、chmod指令 5、tar指令 1、mv指令 功能 用于移动或重命名文件和目录的命令 基本用法 mv [选项] 源文件或目录 目标文件或目录 常用选项 -i&#xff1a;在覆盖文件之前提示用户确认。-f&#xff1a;强制移动或重命名&#xff0…

动量参数(Momentum Parameter)

动量参数&#xff08;Momentum Parameter&#xff09;在机器学习中指的是一种用于加速梯度下降算法的技术&#xff0c;特别是深度学习中优化神经网络权重时。简单来说&#xff0c;动量参数是一种帮助优化过程加速并减少震荡的技术。 具体来说&#xff0c;动量参数具有以下特点…

网络编程——wireshark抓包、tcp粘包

目录 一、前言 1.1 什么是粘包 1.2 为什么UDP不会粘包 二、编写程序 文件树 客户端程序 服务器程序 tcp程序 头文件 makefile 三、 实验现象 四、改进实验 五、小作业 一、前言 最近在做网络芯片的驱动&#xff0c;验证功能的时候需要借助wireshark这个工具&…

猫头虎分享:Numpy知识点一文带你详细学习np.random.randn()

&#x1f42f; 猫头虎分享&#xff1a;Numpy知识点一文带你详细学习np.random.randn() 摘要 Numpy 是数据科学和机器学习领域中不可或缺的工具。在本篇文章中&#xff0c;我们将深入探讨 np.random.randn()&#xff0c;一个用于生成标准正态分布的强大函数。通过详细的代码示…

Android Studio 一键删除 Recent Projects信息的方法

Android Studio打开项目多了就一堆最近项目的记录&#xff0c;在IDE里面只能一个个手动删除。 File - Recent Projects 解决方案&#xff1a;修改配置文件 Note&#xff1a;方法不唯一。 Android Studio 存储了一个包含最近打开项目信息的配置文件。通过手动编辑或删除recentP…