Python网络爬虫中的编码乱码如何解决

项目场景:

开发一个Python爬虫程序,需要爬取某电商网站的商品信息(包括商品名称、价格、评论等),并将数据保存为CSV文件。项目使用requests库进行网页请求,Beautiful Soup进行解析,需要处理大量包含中文、emoji等特殊字符的数据。


问题描述

在运行爬虫程序时,遇到以下问题:

  1. 保存的CSV文件打开后显示乱码
  2. 某些特殊商品名称显示为问号或方块
  3. emoji表情无法正确显示
  4. 读取CSV文件时出现UnicodeDecodeError异常

问题代码示例:

import requests
from bs4 import BeautifulSoup
import csvdef crawl_product_info():url = "http://example.com/products"response = requests.get(url)soup = BeautifulSoup(response.text, 'html.parser')# 提取商品信息products = []for item in soup.find_all('div', class_='product-item'):name = item.find('h2').textprice = item.find('span', class_='price').textcomments = item.find('div', class_='comments').textproducts.append([name, price, comments])# 保存到CSVwith open('products.csv', 'w') as f:writer = csv.writer(f)writer.writerows(products)

原因分析:

  1. 网页编码问题:

    • requests默认使用其自动识别的编码
    • 某些网站的编码声明可能不准确
    • response.text可能使用错误的编码解码
  2. CSV文件编码问题:

    • 默认使用系统编码(Windows中文系统通常是cp936)
    • 没有指定UTF-8 BOM标记
    • Excel打开UTF-8文件可能无法正确识别编码
  3. 特殊字符处理:

    • emoji字符超出基本Unicode平面
    • 某些特殊符号需要特殊编码处理
    • 不同Python版本的默认编码处理可能不同

解决方案:

  1. 完整的改进版代码:
import requests
from bs4 import BeautifulSoup
import csv
import codecs
from typing import List, Dictclass ProductCrawler:def __init__(self):self.session = requests.Session()# 设置默认请求头self.session.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}def get_page_content(self, url: str) -> str:"""获取页面内容并确保编码正确"""response = self.session.get(url)# 显式设置编码response.encoding = response.apparent_encodingreturn response.textdef parse_product(self, html: str) -> List[Dict]:"""解析商品信息"""soup = BeautifulSoup(html, 'html.parser')products = []for item in soup.find_all('div', class_='product-item'):try:product = {'name': self._clean_text(item.find('h2').text),'price': self._clean_text(item.find('span', class_='price').text),'comments': self._clean_text(item.find('div', class_='comments').text)}products.append(product)except AttributeError as e:print(f"解析商品信息失败: {e}")continuereturn productsdef _clean_text(self, text: str) -> str:"""清理文本数据"""if text is None:return ""# 移除特殊字符和空白return text.strip().replace('\n', ' ').replace('\r', '')def save_to_csv(self, products: List[Dict], filename: str):"""保存数据到CSV文件"""try:# 使用utf-8-sig编码(带BOM),确保Excel能正确识别with codecs.open(filename, 'w', encoding='utf-8-sig') as f:writer = csv.DictWriter(f, fieldnames=['name', 'price', 'comments'])writer.writeheader()writer.writerows(products)except Exception as e:print(f"保存CSV文件失败: {e}")raisedef crawl_and_save(self, url: str, output_file: str):"""爬取并保存数据的主函数"""try:html = self.get_page_content(url)products = self.parse_product(html)self.save_to_csv(products, output_file)print(f"成功爬取并保存{len(products)}条商品信息")except Exception as e:print(f"爬取过程发生错误: {e}")
  1. 使用示例:
def main():crawler = ProductCrawler()url = "http://example.com/products"try:crawler.crawl_and_save(url, "products.csv")except Exception as e:print(f"程序执行失败: {e}")if __name__ == "__main__":main()
  1. 关键改进点:
  • 使用response.apparent_encoding自动识别网页编码
  • 使用utf-8-sig编码保存CSV(带BOM标记)
  • 添加文本清理函数处理特殊字符
  • 使用异常处理机制提高程序稳定性
  • 采用类的方式组织代码,提高可维护性
  1. 读取CSV文件的正确方式:
def read_csv(filename: str) -> List[Dict]:"""正确读取CSV文件的方法"""try:with codecs.open(filename, 'r', encoding='utf-8-sig') as f:reader = csv.DictReader(f)return list(reader)except UnicodeDecodeError:# 尝试使用其他编码with codecs.open(filename, 'r', encoding='gb18030') as f:reader = csv.DictReader(f)return list(reader)

通过以上优化,程序可以正确处理各种编码情况,确保数据的完整性和可读性。特别是在处理中文和特殊字符时,不会再出现乱码问题。

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

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

相关文章

开发环境搭建-1:配置 WSL (类 centos 的 oracle linux 官方镜像)

一些 Linux 基本概念 个人理解,并且为了便于理解,可能会存在一些问题,如果有根本上的错误希望大家及时指出 发行版 WSL 的系统是基于特定发行版的特定版本的 Linux 发行版 有固定组织维护的、开箱就能用的 Linux 发行版由固定的团队、社…

从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CICD)

从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CI/CD) 目录 项目初始化:构建一个简单的 Node.js 应用设置 Docker 环境:容器化你的应用配置 CI/CD:自动化构建与部署上线前的最后检查:…

安卓动态设置Unity图形API

命令行方式 Unity图像api设置为自动,安卓动态设置Vulkan、OpenGLES Unity设置 安卓设置 创建自定义活动并将其设置为应用程序入口点。 在自定义活动中,覆盖字符串UnityPlayerActivity。updateunitycommandlineararguments (String cmdLine)方法。 在该方法中,将cmdLine…

python如何导出数据到excel文件

python导出数据到excel文件的方法: 1、调用Workbook()对象中的add_sheet()方法 wb xlwt.Workbook() ws wb.add_sheet(A Test Sheet) 2、通过add_sheet()方法中的write()函数将数据写入到excel中,然后使用save()函数保存excel文件 ws.write(0, 0, 1234…

虚幻基础-1:cpu挑选(14600kf)

能帮到你的话,就给个赞吧 😘 文章目录 ue非常吃cpu拉满主频打开项目编写蓝图运行原因 时间长 关于压力测试 本文以14600kf为例,双12购入,7月份产。 ue非常吃cpu 经本人测试,ue是非常吃cpu的。 拉满主频 无论任何时间…

MECD+: 视频推理中事件级因果图推理--VLM长视频因果推理

论文链接:https://arxiv.org/pdf/2501.07227v1 1. 摘要及主要贡献点 摘要: 视频因果推理旨在从因果角度对视频内容进行高层次的理解。然而,目前的研究存在局限性,主要表现为以问答范式执行,关注包含孤立事件和基本因…

mapbox加载geojson,鼠标移入改变颜色,设置样式以及vue中的使用

全国地图json数据下载地址 目录 html加载全部代码 方式一:使用html方式加载geojson 1. 初始化地图 2. 加载geojson数据 设置geojson图层样式,设置type加载数据类型 设置线条 鼠标移入改变颜色,设置图层属性,此处是fill-extru…

接上篇基于Alertmanager 配置钉钉告警

Alertmanager 是一个用于处理和管理 Prometheus 警报的开源工具。它负责接收来自 Prometheus 服务器的警报,进行去重、分组、静默、抑制等操作,并通过电子邮件、PagerDuty、Slack 等多种渠道发送通知。 主要功能 去重:合并相同或相似的警报&a…

通过视觉语言模型蒸馏进行 3D 形状零件分割

大家读完觉得有帮助记得关注和点赞!!!对应英文要求比较高,特此说明! Abstract This paper proposes a cross-modal distillation framework, PartDistill, which transfers 2D knowledge from vision-language models …

PID 控制算法(二):C 语言实现与应用

在本文中,我们将用 C 语言实现一个简单的 PID 控制器,并通过一个示例来演示如何使用 PID 控制算法来调整系统的状态(如温度、速度等)。同时,我们也会解释每个控制参数如何影响系统的表现。 什么是 PID 控制器&#xf…

数据结构——实验一·线性表

海~~欢迎来到Tubishu的博客🌸如果你也是一名在校大学生,正在寻找各种变成资源,那么你就来对地方啦🌟 Tubishu是一名计算机本科生,会不定期整理和分享学习中的优质资源,希望能为你的编程之路添砖加瓦⭐&…

vector的使用,以及部分功能的模拟实现(C++)

1.vector的介绍及使用 1.1 vector的介绍 vector是STL容器中的一种常用的容器,和数组类似,由于其大小(size)可变,常用于数组大小不可知的情况下来替代数组。 vector也是一种顺序容器,在内存中连续排列,因此可以通过下标…

【Postgres_Python】使用python脚本批量创建和导入多个PG数据库

之前批量创建和导入数据库分为2个python脚本进行,现整合优化代码合并为一个python脚本,可同步实现数据库的创建和数据导入。之前的文章链接: 【Postgres_Python】使用python脚本批量创建PG数据库 【Postgres_Python】使用python脚本将多个.S…

U-Net - U型网络:用于图像分割的卷积神经网络

U-Net是一种专为图像分割任务设计的卷积神经网络(CNN),最初由Olaf Ronneberger等人于2015年提出。它被广泛应用于医学影像分析、遥感图像分割、自动驾驶和其他许多需要对图像进行像素级分类的任务中。U-Net具有强大的特征提取和恢复能力&…

ceph基本概念,架构,部署(一)

一、分布式存储概述 1.存储分类 存储分为封闭系统的存储和开放系统的存储,而对于开放系统的存储又被分为内置存储和外挂存储。 外挂存储又被细分为直连式存储(DAS)和网络存储(FAS),而网络存储又被细分网络接入存储(NAS)和存储区域网络(SAN)等。 DAS(D…

联想电脑怎么用u盘装系统_联想电脑用u盘装win10系统教程

联想电脑怎么重装系统?在当今科技发展迅猛的时代,联想电脑已经成为了人们生活中不可或缺的一部分。然而,随着时间的推移,我们可能会遇到一些问题,例如系统崩溃或者需要更换操作系统。这时,使用U盘来重新安装…

基于ESP32-IDF驱动GPIO输出控制LED

基于ESP32-IDF驱动GPIO输出控制LED 文章目录 基于ESP32-IDF驱动GPIO输出控制LED一、点亮LED3.1 LED电路3.2 配置GPIO函数gpio_config()原型和头文件3.3 设置GPIO引脚电平状态函数gpio_set_level()原型和头文件3.4 代码实现并编译烧录 一、点亮LED 3.1 LED电路 可以看到&#x…

电路研究9.1.1——合宙 Air780EP 模组外围线路

本来要继续研究AT指令来着,结果发现后面还有之前用到的电路设计资料,所以就贴过来了。 5.3.2 工作模式: 注意:  当模块进入休眠模式或深度休眠模式后, VDD_EXT 电源会掉电,相应电压域的 GPIO 以及串口…

Apache Hive3定位表并更改其位置

Apache Hive3表 1、Apache Hive3表概述2、Hive3表存储格式3、Hive3事务表4、Hive3外部表5、定位Hive3表并更改位置6、使用点表示法引用表7、理解CREATE TABLE行为 1、Apache Hive3表概述 Apache Hive3表类型的定义和表类型与ACID属性的关系图使得Hive表变得清晰。表的位置取决于…

Flutter 改完安卓 applicationId 后App 闪退问题。

一、问题 当我们项目创建完,想 build.gradle 改 applicationId 的时候,再次执行的时候可能会出现 app 闪退问题, 控制台不显示任何错误提示 也不出现 Exit 停止运行的情况。(像下方这样, 而 app 只是在模拟器中一闪而…