Как заставить интерпретатор python правильно обрабатывать символы, отличные от ASCII, в строковых операциях?
У меня есть строка, которая выглядит так:
6Â 918Â 417Â 712
Четкий способ обрезать эту строку (как я понимаю, Python) просто сказать, что строка находится в переменной с именем s
, мы получаем:
s.replace('Â ', '')
Это должно сделать трюк. Но, конечно, он жалуется, что символ не-ASCII '\xc2'
в файле blabla.py не закодирован.
Я никогда не мог понять, как переключаться между разными кодировками.
Вот код, он действительно такой же, как и выше, но теперь он в контексте. Файл сохраняется как UTF-8 в блокноте и имеет следующий заголовок:
#!/usr/bin/python2.4
# -*- coding: utf-8 -*-
Код:
f = urllib.urlopen(url)
soup = BeautifulSoup(f)
s = soup.find('div', {'id':'main_count'})
#making a print 's' here goes well. it shows 6Â 918Â 417Â 712
s.replace('Â ','')
save_main_count(s)
Он не превышает s.replace
...
Ответы
Ответ 1
Python 2 использует ascii
как кодировку по умолчанию для исходных файлов, а это означает, что вы должны указать другую кодировку в верхней части файла, чтобы использовать символы un-ascii unicode в литералах. Python 3 использует utf-8
как кодировку по умолчанию для исходных файлов, поэтому это не проблема.
См:
http://docs.python.org/tutorial/interpreter.html#source-code-encoding
Чтобы включить кодировку исходного кода utf-8, это будет проходить в одной из двух верхних строк:
# -*- coding: utf-8 -*-
Вышеупомянутое находится в документах, но это также работает:
# coding: utf-8
Дополнительные соображения:
-
Исходный файл должен быть сохранен с использованием правильной кодировки в текстовом редакторе.
-
В Python 2 литерал unicode должен иметь перед ним u
, как в s.replace(u"Â ", u"")
Но в Python 3 просто используйте кавычки. В Python 2 вы можете from __future__ import unicode_literals
получить поведение Python 3, но помните, что это влияет на весь текущий модуль.
-
s.replace(u"Â ", u"")
также будет терпеть неудачу, если s
не является строкой unicode.
-
string.replace
возвращает новую строку и не редактируется на месте, поэтому убедитесь, что вы также используете возвращаемое значение
Ответ 2
def removeNonAscii(s): return "".join(filter(lambda x: ord(x)<128, s))
edit: мой первый импульс всегда использует фильтр, но выражение генератора более эффективно (и короче) памяти...
def removeNonAscii(s): return "".join(i for i in s if ord(i)<128)
Имейте в виду, что это гарантировано для работы с кодировкой UTF-8 (поскольку все байты в многобайтовых символах имеют самый старший бит, установленный в 1).
Ответ 3
>>> unicode_string = u"hello aåbäcö"
>>> unicode_string.encode("ascii", "ignore")
'hello abc'
Ответ 4
Следующий код заменит все символы без символов ASCII вопросительными знаками.
"".join([x if ord(x) < 128 else '?' for x in s])
Ответ 5
Использование Regex:
import re
strip_unicode = re.compile("([^[email protected]#%&=,/'\";:~`\$\^\*\(\)\+\[\]\.\{\}\|\?\<\>\\]+|[^\s]+)")
print strip_unicode.sub('', u'6Â 918Â 417Â 712')
Ответ 6
Слишком поздно для ответа, но исходная строка была в UTF-8, а '\ xc2\xa0' - это UTF-8 для NO-BREAK SPACE. Просто декодируйте исходную строку как s.decode('utf-8')
(\ xa0 отображается как пространство при некорректном декодировании как Windows-1252 или latin-1:
Пример (Python 3)
s = b'6\xc2\xa0918\xc2\xa0417\xc2\xa0712'
print(s.decode('latin-1')) # incorrectly decoded
u = s.decode('utf8') # correctly decoded
print(u)
print(u.replace('\N{NO-BREAK SPACE}','_'))
print(u.replace('\xa0','-')) # \xa0 is Unicode for NO-BREAK SPACE
Выход
6Â 918Â 417Â 712
6 918 417 712
6_918_417_712
6-918-417-712
Ответ 7
#!/usr/bin/env python
# -*- coding: utf-8 -*-
s = u"6Â 918Â 417Â 712"
s = s.replace(u"Â", "")
print s
Откроется 6 918 417 712
Ответ 8
Я знаю, что это старый поток, но я был вынужден упомянуть о методе перевода, который всегда является хорошим способом заменить все коды символов выше 128 (или, если необходимо, на другие).
Использование: str. translate (таблица [, deletechars])
>>> trans_table = ''.join( [chr(i) for i in range(128)] + [' '] * 128 )
>>> 'Résultat'.translate(trans_table)
'R sultat'
>>> '6Â 918Â 417Â 712'.translate(trans_table)
'6 918 417 712'
Начиная с Python 2.6, вы также можете установить таблицу в None и использовать deletechars для удаления символов, которые вы не хотите, как в примерах, показанных в стандартных документах, в http://docs.python.org/library/stdtypes.html.
С строками unicode таблица переводов не является строкой из 256 символов, а dict с символом ord() соответствующих символов в качестве ключей. Но в любом случае получение правильной строки ascii из строки unicode достаточно просто, используя метод, упомянутый truppo выше, а именно: unicode_string.encode( "ascii", "ignore" )
В качестве сводки, если по какой-то причине вам абсолютно необходимо получить строку ascii (например, когда вы поднимаете стандартное исключение с помощью raise Exception, ascii_message
), вы можете использовать следующую функцию:
trans_table = ''.join( [chr(i) for i in range(128)] + ['?'] * 128 )
def ascii(s):
if isinstance(s, unicode):
return s.encode('ascii', 'replace')
else:
return s.translate(trans_table)
Хорошая вещь в переводе состоит в том, что вы можете фактически преобразовать символы с акцентом в соответствующие символы без акцента ascii вместо простого удаления или замены их на??. Это часто полезно, например, для целей индексирования.
Ответ 9
s.replace(u'Â ', '') # u before string is important
и сделайте ваш unicode файл .py
.
Ответ 10
Это грязный взлом, но он может работать.
s2 = ""
for i in s:
if ord(i) < 128:
s2 += i
Ответ 11
Для чего это стоило, мой набор символов был utf-8
, и я включил классическую строку # -*- coding: utf-8 -*-
.
Тем не менее, я обнаружил, что у меня не было Universal Newlines при чтении этих данных с веб-страницы.
В моем тексте было два слова, разделенных "\r\n
". Я только разбился на \n
и заменил "\n"
.
Как только я зациклился и увидел набор символов, я понял ошибку.
Таким образом, он также может быть в наборе символов ASCII, но символа, которого вы не ожидали.