2016-07-04 11 views
0

私はPythonスクリプトを使ってWebページをダウンロードして解析しています。それ以上の処理のためには、 を7ビットASCIIにエンコードする必要があります。私は、 リクエストライブラリ(http://docs.python-requests.org/en/master/)を、Ubuntu 16.04 LTSにあるものに基づいて virtualenvに使用しています。マルチバイト文字をPythonで7ビットASCIIに変換する

、私はいくつかの 文字を欠場するつもりです知っているので、私は、要求パッケージが好き、またはいくつかのパッケージ、ASCIIに 翻訳を処理するために、エンコードされた文字のさらなる翻訳 を行うために私を必要としないでしょう。詳細は以下のとおりです。次に示す

私の現在のPythonスクリプトは、7ビットのASCII、いくつかの部分的な成功と に変換する結果データを強制しようとする試みにはISO-8859-1 のエンコーディングを使用しています。しかし、私は のエンコーディング結果が出てきたらエンコードした結果を設定しました。それは奇妙に思われ、実際には が間違っています。しかし、私がそれに住んでいても、主な問題は次の通りです 符号化した後でさえ、 ASCII文字以外の文字セットにあるように符号化されています。これは、ダッシュ文字が要求エンコーディングを介して を滑ったかのようです。以下のスクリプトでは、 のマルチバイトダッシュエンコーディングを検索し、ASCIIの ダッシュ文字で置き換えて、これをハックします。マルチバイトの 文字であれば大したことではありませんが、処理したい他のWebページで翻訳する必要がある文字が他にもあると思われます( )。 は、 リクエストオブジェクトで 'ISO-8859-1'以外のエンコーディングを使用する必要がありますか?ここで

は(x86_64の上のUbuntu 16.04 LTSでPython 2.7.11を使用して)私のスクリプトです:virtualenvの内simple_wget.pyを呼び出す

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

は示しています

[email protected]:~$ 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てその出力を渡しますr'\xe2\x80\x93'に対応するダッシュ文字の8進数値(「342 200 223」)を表示するには、上記のスクリプト:

https://stackoverflow.com/a/19645137/257924エンコードasciiの を使用することを意味しますが、リクエストライブラリ内チョーク:

[email protected]:~$ 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 
[email protected]:~$ 

物事は私が試してみました。

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

利回り:

[email protected]:~$ ./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") 

結果だけで削除され、翻訳されないように上記の最後の行を変更することにする スクリプトを変更します私が望むもの

そして、これはまた、全く動作しません:

​​

それは、このエラー与えるので:

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から、あります"は ユニコード文字列ではありません。 256文字の変換テーブルは、私がどうしても必要なものを するつもりはありません。それ以外に余計なことがあります。 Pythonはスクリプトレベルで ハックコードを使わなくても、これらのマルチバイト文字を翻訳する必要があります。

ところで、私は多言語のページ翻訳に興味がありません。すべて は、アメリカまたはイギリスの英語で翻訳されています。

+1

米国または英国英語にはハイフン以外の文字(ダッシュ記号、 ""、アポストロフィなど)が含まれている可能性があります。一部のテキストでは脚注に†を使用しています。あなたがそれを避けることができれば、たとえそれが英語であってもテキストをASCIIに縮小しようとしないでください。 – roeland

+0

あなたが言ったように私はそれを避けるように強制されるかもしれません。 http://stackoverflow.com/a/38178064/257924は適切な使い方について私を真っ直ぐにしてくれたので、私はフォローアップ、別々の質問で何を求めているのか分かります。 – bgoodr

答えて

1

Pythonには、適切なエンコードを宣言していれば、非ASCII文字をきれいに処理するために必要なものがすべてあります。 r'\xe2\x80\x93'は、EN DASH文字またはユニコードU+2013のUTF8エンコードであるため、入力ファイルはISO-8859-1ではなく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マップがバイト文字列とユニコード文字列で異なるため、これで動作します。バイト文字列の場合、変換テーブルは長さ256の文字列でなければなりませんが、Unicode文字列では、Unicode文字列、Unicode文字列、またはNone(ref: Python Standard Library Reference Manual)のマッピングでなければなりません。

  • あなたは安全のASCIIバイト列にデータをエンコードすることができます

    tdata = data.encode('ascii') 
    

    いくつかの非翻訳非ASCII文字がdata Unicode文字列に残っている場合は、上記のコマンドは、例外がスローされます。あなたは、すべてが成功裏に変換されたことを確認する助けとしてそれを見ることができます。

+0

それはかなり役に立ちました。 charmapを自分のコードにハードコーディングすることを完全に避けることを主目的とするために、新しいPythonのpythonライブラリを使用してcharmapを提供するという新たな質問が必要です。したがって、これを回答としてマークする。 – bgoodr

+0

新しい個別の質問としてhttp://stackoverflow.com/questions/38249708/python-library-to-translate-multi-byte-characters-into-7-bit-ascii-in-python – bgoodr

関連する問題