本文将根据实践经验说明python中使用requests库编写爬虫程序时,出现【中文乱码】的原因及解决办法。
首先,本文的【中文乱码】情况,指的是原网页中的中文内容在使用requests获取后,中文完全无法识别的情况,区别于\x、\u等编码情况。如下图中的例子:
导致上图中【中文乱码】的原因:
使用requests库时,选择使用的文本响应方法不合适,且没有在代码中添加设置合适的编码,以致于使用【response.text】自动获取到的网页编码,与实际网页的编码不一致,进而产生【中文乱码】。
使用requests库时,可能已经形成了一个习惯,常用【response.text】进行文本响应,而【response.content】常用于图片、视频等。
这两者,最大的一个区别就是:
1、【response.text】会自动根据HTTP头部去推测网页的编码,解码并返回解码后的文本。
2、【response.content】不会解码,直接以二进制形式返回。
两种文本响应方法,如下表:
response.text | 服务器响应的内容,会自动根据响应头部的字符编码进行解码。根据HTTP头部对响应的编码做出有根据的推测,推测文本编码。返回类型:str;常用于:响应文本 |
response.content | 字节方式的响应体,不会根据HTTP头部对响应的编码做出有根据的推测。返回类型:bytes(二进制);常用于:图片、视频 |
最有效的解决方法:
使用response的encoding、apparent_encoding,得到网页编码。
encoding、apparent_encoding两者最大的区别:
encoding是从header中去提取,而apparent_encoding是从网页源码去解析,apparent_encoding得到的结果更准确。
详细如下表:
response.encoding | 从网页响应的header中,提取charset字段中的编码。若header中没有charset字段,则默认为ISO-8859-1编码模式,ISO-8859-1编码无法解析中文,这也是中文乱码的原因。 |
response.apparent_encoding | 从网页的内容中(html源码)中分析网页编码的方式。所以apparent_encoding比encoding更加准确,获取到的才是原网页的实际编码。 |
print(response.apparent_encoding)
print(response.encoding)
使用encoding、apparent_encoding两种方法,所得的结果是不一致的,apparent_encoding才是原网页实际编码。如下图
根据上述方法,获得原网页的实际编码后,手动在代码中指定文本编码格式,即可解决【中文乱码】问题。如下图:
response.encoding=response.apparent_encoding
以上就是使用requests爬虫解决中文乱码的方法,如那位老师有更好的方法还望赐教,谢谢!
clipse运行页面显示中文乱码
页面源码
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="ISO-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>客户列表-BootCRM</title>
</head>
<body>
<h1>解决中文乱码</h1>
</body>
</html>
tomcat运行后
打开浏览器地址栏打就会出现乱码现象
分析问题
首先排查一下服务器是否启动,回看console最下面 server startup 表示服务器已经启动了 没有问题也没有报错。
其次查看页面源码,发现有三处编码为ISO-8859-1。
注意:数字英文都正常显示,只是中文乱码,是因为ISO-8859-1是单字节编码,此字符集支持部分于欧洲使用的语言,这个编码不支持中文,所以要换支持的编码啦,现在一般都通用UTF-8,因为ISO-8859-1是一个8位的容器。因为只有8位, 没那么多地方可以表示中文,但是,由于是单字节编码,和计算机最基础的表示单位一致,所以很多时候,仍旧使用 ISO-8859-1编码来表示。而且在很多协议上,默认使用该编码。
解决办法
将代码中三处的ISO-8859-1 改成UTF-8就好了。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>客户列表-BootCRM</title>
</head>
<body>
<h1>解决中文乱码</h1>
</body>
</html>
此时运行结果就正常了
要使用的是wkhtmltopdf的Python封装——pdfkit
安装
1. Install python-pdfkit:
$ pip install pdfkit
2. Install wkhtmltopdf:
$ sudo apt-get install wkhtmltopdf
sudo yum intsall wkhtmltopdf
brew install Caskroom/cask/wkhtmltopdf
使用
一个简单的例子:
import pdfkit
pdfkit.from_url('http://google.com', 'out.pdf')
pdfkit.from_file('test.html', 'out.pdf')
pdfkit.from_string('Hello!', 'out.pdf')
你也可以传递一个url或者文件名列表:
pdfkit.from_url(['google.com', 'yandex.ru', 'engadget.com'], 'out.pdf')
pdfkit.from_file(['file1.html', 'file2.html'], 'out.pdf')
也可以传递一个打开的文件:
with open('file.html') as f:
pdfkit.from_file(f, 'out.pdf')
如果你想对生成的PDF作进一步处理, 你可以将其读取到一个变量中:
# 设置输出文件为False,将结果赋给一个变量
pdf = pdfkit.from_url('http://google.com', False)
你可以制定所有的 wkhtmltopdf 选项 http://wkhtmltopdf.org/usage/wkhtmltopdf.txt. 你可以移除选项名字前面的 '--' .如果选项没有值, 使用None, False or * 作为字典值:
options = {
'page-size': 'Letter',
'margin-top': '0.75in',
'margin-right': '0.75in',
'margin-bottom': '0.75in',
'margin-left': '0.75in',
'encoding': "UTF-8",
'no-outline': None
}
pdfkit.from_url('http://google.com', 'out.pdf', options=options)
默认情况下, PDFKit 将会显示所有的 wkhtmltopdf 输出. 如果你不想看到这些信息,你需要传递一个 quiet 选项:
options = {
'quiet': ''
}
pdfkit.from_url('google.com', 'out.pdf', options=options)
由于wkhtmltopdf的命令语法 , TOC 和 Cover 选项必须分开指定:
toc = {
'xsl-style-sheet': 'toc.xsl'
}
cover = 'cover.html'
pdfkit.from_file('file.html', options=options, toc=toc, cover=cover)
当你转换文件、或字符串的时候,你可以通过css选项指定扩展的 CSS 文件。
# 单个 CSS 文件
css = 'example.css'
pdfkit.from_file('file.html', options=options, css=css)
# Multiple CSS files
css = ['example.css', 'example2.css']
pdfkit.from_file('file.html', options=options, css=css)
你也可以通过你的HTML中的meta tags传递任意选项:
body = """
<html>
<head>
<meta name="pdfkit-page-size" content="Legal"/>
<meta name="pdfkit-orientation" content="Landscape"/>
</head>
Hello World!
</html>
"""
pdfkit.from_string(body, 'out.pdf') #with --page-size=Legal and --orientation=Landscape
配置
每个API调用都有一个可选的参数。这应该是pdfkit.configuration()API 调用的一个实例. 采用configuration 选项作为初始化参数。可用的选项有:
示例 :针对wkhtmltopdf不在系统路径中(不在$PATH里面)
PATH里面):
config = pdfkit.configuration(wkhtmltopdf='/opt/bin/wkhtmltopdf'))
pdfkit.from_string(html_string, output_file, configuration=config)
问题
IOError:'No wkhtmltopdf executable found':
确保 wkhtmltopdf 在你的系统路径中(PATH), 会通过 configuration进行了配置 (详情看上文描述)。 在Windows系统中使用where wkhtmltopdf命令 或 在 linux系统中使用 which wkhtmltopdf 会返回 wkhtmltopdf二进制可执行文件所在的确切位置.
如果出现这个错误意味着 PDFKit不能处理一个输入。你可以尝试直接在错误信息后面直接运行一个命令来查看是什么导致了这个错误 (某些版本的 wkhtmltopdf会因为段错误导致处理失败)
确保两项:
1)、你的系统中有中文字体
2)、在html中加入
下面是我随便写的一个HTML表格:
<html>
<head><meta charset="UTF-8"></head>
<body>
<table width="400" border="1">
<tr>
<th align="left">Item....</th>
<th align="right">1</th>
</tr>
<tr>
<td align="left">衣服</td>
<td align="right">1.10</td>
</tr>
<tr>
<td align="left">化妆品</td>
<td align="right">.00</td>
</tr>
<tr>
<td align="left">食物</td>
<td align="right">0.40</td>
</tr>
<tr>
<th align="left">tOTAL</th>
<th align="right">01.50</th>
</tr>
</table>
</body>
</html>
下面是生成的PDF截图
*请认真填写需求信息,我们会在24小时内与您取得联系。