Другого подхода это намного быстрее, чем вышеприведенный ответ - использовать регулярные выражения, например:
re.sub(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+', '', text)
По сравнению с выше ответ, он выходит более чем в 10 раз быстрее, в ходе тестирования:
import timeit
func_test = """
def valid_xml_char_ordinal(c):
codepoint = ord(c)
# conditions ordered by presumed frequency
return (
0x20 <= codepoint <= 0xD7FF or
codepoint in (0x9, 0xA, 0xD) or
0xE000 <= codepoint <= 0xFFFD or
0x10000 <= codepoint <= 0x10FFFF
);
''.join(c for c in r.content if valid_xml_char_ordinal(c))
"""
func_setup = """
import requests;
r = requests.get("https://stackoverflow.com/questions/8733233/")
"""
regex_test = """re.sub(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+', '', r.content)"""
regex_setup = """
import requests, re;
r = requests.get("https://stackoverflow.com/questions/8733233/")
"""
func_test = timeit.Timer(func_test, setup=func_setup)
regex_test = timeit.Timer(regex_test, setup=regex_setup)
print func_test.timeit(100)
print regex_test.timeit(100)
Выход:
> 2.63773989677
> 0.221401929855
Итак, осмыслении того, что мы «Реализация - это загрузка этой веб-страницы один раз (страница, которую вы сейчас читаете), затем запуск функциональной техники и техники регулярных выражений по ее содержимому 100X каждый.
Использование функционального метода занимает около 2.6 секунд.
Использование метода регулярного выражения занимает около 0,2 секунд.
Update: Как указано в комментариях, регулярное выражение в этом ответе ранее удалены некоторые символы, которые должны быть разрешены в XML. Эти персонажи включают в себя все, что есть в Supplementary Multilingual Plane, в которое входят древние сценарии, такие как клинопись, иероглифы и (странно) эможи.
Правильное регулярное выражение теперь выше. Быстрый тест для этого в будущем использует re.DEBUG
, который печатает:
In [52]: re.compile(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+', re.DEBUG)
max_repeat 1 4294967295
in
negate None
range (32, 55295)
literal 9
literal 10
literal 13
range (57344, 65533)
range (65536, 1114111)
Out[52]: re.compile(ur'[^ -\ud7ff\t\n\r\ue000-\ufffd\U00010000-\U0010ffff]+', re.DEBUG)
Мои извинения за ошибки. Я могу только предложить, что нашел этот ответ в другом месте и поместил его здесь. Это была чья-то ошибка, но я ее размножал. Мои искренние извинения никому это не повлияли.
Обновление 2, 2017-12-12: Я узнал от некоторых пользователей OSX, что этот код не будет работать на так называемые узкие сборки Python, которые, по-видимому, иногда имеют OSX. Вы можете проверить это, запустив import sys; sys.maxunicode
. Если он печатает 65535, код здесь не будет работать, пока вы не установите «широкую сборку». See more about this here.
У вас также есть случайные данные на входе, как в вопросе, на который вы ссылаетесь? –