Un altro approccio è molto più veloce della risposta di cui sopra è di usare espressioni regolari, in questo modo:
re.sub(u'[^\u0020-\uD7FF\u0009\u000A\u000D\uE000-\uFFFD\U00010000-\U0010FFFF]+', '', text)
Confrontando la risposta di cui sopra, essa risulta essere più di 10 volte più veloce nel mio test:
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)
uscita:
> 2.63773989677
> 0.221401929855
Quindi, dare un senso a questo, ciò che Sta facendo sta scaricando questa pagina web una volta (la pagina che stai leggendo attualmente), quindi eseguendo la tecnica funzionale e la tecnica regex sul suo contenuto 100X ciascuno.
L'utilizzo del metodo funzionale richiede circa 2.6 secondi.
L'utilizzo del metodo regex richiede circa 0,2 secondi.
Aggiornamento: Come identificate nei commenti, la regex in questa risposta precedentemente cancellato alcuni personaggi, che avrebbero dovuto essere ammessi in XML. Questi personaggi includono qualsiasi cosa nello Supplementary Multilingual Plane, che include script antichi come cuneiforme, geroglifici e (stranamente) emoji.
La regex corretta è ora sopra. Un test rapido per questo in futuro sta usando re.DEBUG
, che stampa:
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)
mie scuse per l'errore. Posso solo offrire che ho trovato questa risposta altrove e metterla qui. Era l'errore di qualcun altro, ma l'ho propagato. Le mie sincere scuse a chiunque ne sia affetto.
Aggiornamento 2, 2017-12-12: Ho imparato da alcuni utenti OSX che questo codice non funzionerà sulle cosiddette build strette di Python, che a volte apparentemente OSX ha. Puoi verificarlo eseguendo import sys; sys.maxunicode
. Se stampa 65535, il codice qui non funzionerà finché non installerai una "versione larga". See more about this here.
Hai anche dati casuali su input come nella domanda a cui ti stai riferendo? –