我正在通过Python脚本下载和解析网页。我需要它 被编码为7位ASCII以供进一步处理。我正在使用 请求库中的库(http://docs.python-requests.org/en/master/) virtualenv基于Ubuntu 16.04 LTS所拥有的。
我想请求包或一些包来处理 转换成ASCII,不需要我做进一步的翻译 编码字符,因为我知道我会想念一些 字符。详情如下:
我当前的Python脚本(如下所示)使用ISO-8859-1编码 试图强制将结果数据转换为7位ASCII, 取得了一定的成功。但是,我已将结果编码为和 当文本出来时也对文本进行编码。这看起来很奇怪,事实上, 彻头彻尾的错。但即使我忍受了这一点,我也有主要问题 如下:
即使在编码之后,我看到破折号编码在似乎是什么 一些非ASCII字符集。就像短划线字符滑落一样 通过请求编码。下面的脚本围绕着这个 使用ASCII搜索和替换多字节短划线编码 破折号。如果它是一个多字节,这不是什么大问题 角色,但怀疑还有其他角色需要 在我希望处理的其他网页中翻译。我只是 需要使用除“ISO-8859-1”之外的其他一些编码 请求对象?
这是我的脚本(在x86_64上的Ubuntu 16.04 LTS上使用Python 2.7.11):
#!/bin/bash
import sys
import os
import string
import re
import requests
url = "https://system76.com/laptops/kudu"
r = requests.get(url)
#
# Why do I have to BOTH set r.encoding AND call r.text.encode
# in order to avoid the errors?:
#
encoding = 'ISO-8859-1'
r.encoding = encoding
data = r.text.encode(encoding)
#
# Split the lines out, find the offending line,
# and translate the multi-byte characters:
#
lines = data.splitlines()
for line in lines:
m = re.search(r'2.6 up to 3.5 GHz', line)
if m:
print "line: {}".format(line)
m = re.search(r'\xe2\x80\x93', line)
# The '-' in the next line is a ASCII dash character:
fixed_line = re.sub(r'\xe2\x80\x93', '-', line)
print "fixed_line {}".format(line)
在virtualenv中调用simple_wget.py显示:
theuser@thesystem:~$ simple_wget.py
line: <td>2.6 up to 3.5 GHz – 6 MB cache – 4 cores – 8 threads</td>
fixed_line <td>2.6 up to 3.5 GHz - 6 MB cache - 4 cores - 8 threads</td>
通过oc -cb
传递该输出以查看八进制值(“342 200
223“)与r'\xe2\x80\x93'
对应的短划线字符
上面的脚本:
theuser@thesystem:~$ simple_wget.py | od -cb
0000000 l i n e : \t \t \t \t \t
154 151 156 145 072 040 040 040 040 040 040 011 011 011 011 011
0000020 \t < t d > 2 . 6 u p t o 3
011 074 164 144 076 062 056 066 040 165 160 040 164 157 040 063
0000040 . 5 G H z 342 200 223 6 M B
056 065 040 107 110 172 040 342 200 223 040 066 040 115 102 040
0000060 c a c h e 342 200 223 4 c o r e
143 141 143 150 145 040 342 200 223 040 064 040 143 157 162 145
0000100 s 342 200 223 8 t h r e a d s <
163 040 342 200 223 040 070 040 164 150 162 145 141 144 163 074
0000120 / t d > \n f i x e d _ l i n e
057 164 144 076 012 146 151 170 145 144 137 154 151 156 145 040
0000140 \t \t \t \t \t \t < t d > 2 . 6 u p
011 011 011 011 011 011 074 164 144 076 062 056 066 040 165 160
0000160 t o 3 . 5 G H z - 6
040 164 157 040 063 056 065 040 107 110 172 040 055 040 066 040
0000200 M B c a c h e - 4 c o r
115 102 040 143 141 143 150 145 040 055 040 064 040 143 157 162
0000220 e s - 8 t h r e a d s < /
145 163 040 055 040 070 040 164 150 162 145 141 144 163 074 057
0000240 t d > \n
164 144 076 012
0000244
theuser@thesystem:~$
我尝试过的事情:
https://stackoverflow.com/a/19645137/257924意味着使用编码
ascii
的{{1}},但它在请求库中窒息。改变了
脚本是:
#encoding = 'ISO-8859-1'
encoding = 'ascii' # try https://stackoverflow.com/a/19645137/257924
r.encoding = encoding
data = r.text.encode(encoding)
的产率:
theuser@thesystem:~$ ./simple_wget
Traceback (most recent call last):
File "./simple_wget.py", line 18, in <module>
data = r.text.encode(encoding)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 10166-10168: ordinal not in range(128)
将上面的最后一行更改为
data = r.text.encode(encoding, "ignore")
导致破折号被删除,而不是翻译,这不是我想要的。
这根本不起作用:
encoding = 'ISO-8859-1'
r.encoding = encoding
data = r.text.encode(encoding)
charmap = {
0x2014: u'-', # em dash
0x201D: u'"', # comma quotation mark, double
# etc.
}
data = data.translate(charmap)
因为它会出现此错误:
Traceback (most recent call last):
File "./simple_wget.py", line 30, in <module>
data = tmp2.translate(charmap)
TypeError: expected a string or other character buffer object
据我所知 https://stackoverflow.com/a/10385520/257924,因为“数据”不是 unicode字符串。一个256个字符的转换表是不行的 无论如何我需要什么。除此之外是过度杀伤:内心的东西 Python应该不需要翻译这些多字节字符 我的脚本级别的黑客代码。
顺便说一句,我对多语种页面翻译不感兴趣。所有 翻译的页面预计为美国或英国英语。
答案 0 :(得分:1)
Python提供了干净地处理非ASCII字符所需的一切......只要您声明正确的编码即可。您的输入文件是UTF8编码,而不是ISO-8859-1,因为r'\xe2\x80\x93'
是EN DASH字符或unicode U+2013
的UTF8编码。
所以你应该:
将请求中的文本作为真正的unicode字符串加载:
url = "https://system76.com/laptops/kudu"
r = requests.get(url)
r.encoding = "UTF-8"
data = r.text # ok, data is a true unicode string
在unicode中翻译违规字符 :
charmap = {
0x2014: u'-', # em dash
0x201D: u'"', # comma quotation mark, double
# etc.
}
data = data.translate(charmap)
它现在可以工作,因为translate
映射对于byte和unicode字符串是不同的。对于字节字符串,转换表必须是长度为256的字符串,而对于unicode字符串,它必须是Unicode序列到Unicode序列,Unicode字符串或无(ref: Python Standard Library Reference Manual)的映射。
然后您可以安全地将数据编码为ascii字节字符串:
tdata = data.encode('ascii')
如果某些未翻译的非ascii字符保留在data
unicode字符串中,则上述命令将抛出异常。您可以看到这是一个帮助,以确保所有内容都已成功转换。