Traduzindo caracteres de vários bytes em ASCII de 7 bits em Python

Estou baixando e analisando uma página da web por meio de um script Python. Eu preciso que ele seja codificado em ASCII de 7 bits para processamento adicional. Estou usando a biblioteca de solicitações (http://docs.python-requests.org/en/master/) em um virtualenv baseado em qualquer Ubuntu 16.04 LTS.

Gostaria que o pacote de pedidos, ou algum pacote, manipulasse a tradução para ASCII, sem exigir que eu fizesse uma tradução adicional dos caracteres codificados, porque sei que vou sentir falta de alguns caracteres. Detalhes a seguir:

Meu script Python atual, mostrado abaixo, usa uma codificação ISO-8859-1 na tentativa de forçar os dados do resultado a serem convertidos em ASCII de 7 bits, com algum sucesso parcial. Mas, eu configurei a codificação do resultadoe também codifica o texto quando sai. Isso parece estranho e, de fato, totalmente errado. Mas mesmo se eu viver com isso, tenho o problema principal, que é o seguinte:

Mesmo após a codificação, vejo traços codificados no que parece estar em algum conjunto de caracteres não ASCII. É como se os caracteres do traço escapassem da codificação das solicitações. O script abaixo soluciona esse problema pesquisando e substituindo a codificação de traços de vários bytes por um caractere de traço ASCII. Isso não é grande coisa se for um caractere de vários bytes, mas suspeito que existem outros caracteres que precisarão ser traduzidos em outras páginas da web que desejo processar. Eu simplesmente preciso usar outra codificação diferente de 'ISO-8859-1' com o objeto de solicitações?

Aqui está o meu script (usando Python 2.7.11 no Ubuntu 16.04 LTS em x86_64):

 #!/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)

Invocar simple_wget.py dentro do virtualenv shows:

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>

Passando essa saída atravésoc -cb para ver os valores octais ("342 200 223") dos caracteres de traço correspondentes aor'\xe2\x80\x93' no script acima:

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:~$

Coisas que tentei:

https://stackoverflow.com/a/19645137/257924 implica usar uma codificação deascii, mas engasga dentro da biblioteca de solicitações. Alterando o script para:

#encoding = 'ISO-8859-1'
encoding = 'ascii' # try https://stackoverflow.com/a/19645137/257924
r.encoding = encoding
data = r.text.encode(encoding)

rendimentos:

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)

Alterando a última linha acima para

data = r.text.encode(encoding, "ignore")

resulta nos traços sendo removidos, não traduzidos, o que não é o que eu quero.

E isso também não funciona:

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)

porque dá este erro:

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

que é, tanto quanto eu posso entenderhttps://stackoverflow.com/a/10385520/257924, devido a "dados" não serem uma sequência unicode. Uma tabela de tradução de 256 caracteres não fará o que eu preciso. E, além disso, é um exagero: algo dentro do Python deve traduzir esses caracteres de vários bytes sem exigir código de invasão no meu nível de script.

A propósito, não estou interessado em tradução de páginas em vários idiomas. Todas as páginas traduzidas devem estar em inglês americano ou britânico.

questionAnswers(1)

yourAnswerToTheQuestion