2017-09-30 3 views
0

Je construis un extrait de données en utilisant scrapy et je veux normaliser une chaîne brute tirée d'un document HTML. Voici un exemple de chaîne:Normaliser les espaces avec Python

Sapphire RX460 OC 2/4GB 

avis deux groupes de deux espaces précédant la chaîne littérale et entre OC et 2.

Python fournit l'assiette comme décrit dans How do I trim whitespace with Python? Mais cela ne gèrera pas les deux espaces entre OC et 2, dont j'ai besoin replié dans un seul espace.

J'ai essayé d'utiliser normalize-space() de XPath lors de l'extraction des données avec mes scrapy Selector et qui fonctionne, mais l'affectation verbeux avec une forte dérive vers la droite:

product_title = product.css('h3').xpath('normalize-space((text()))').extract_first() 

Y at-il une façon élégante de normaliser les espaces en utilisant Python? S'il n'y a pas de doublure, y a-t-il un moyen de casser la ligne ci-dessus en quelque chose de plus facile à lire sans lancer une erreur d'indentation, par ex.

product_title = product.css('h3') 
    .xpath('normalize-space((text()))') 
    .extract_first() 

Répondre

5

Vous pouvez utilisation:

" ".join(s.split()) 

s est votre chaîne.

+0

C'est élégant et fonctionne parfaitement. Merci, Tom! –

+0

Appliqué dans le [contexte de Scrapy] (https://stackoverflow.com/a/46501593/712334), le cas d'utilisation dont j'ai fini par en avoir besoin. –

0

Vous pouvez utiliser une fonction comme ci-dessous avec une expression régulière pour rechercher des espaces continus et de les remplacer par 1 espace

import re 

def clean_data(data): 
    return re.sub(" {2,}", " ", data.strip()) 

product_title = clean(product.css('h3::text').extract_first()) 

Et puis d'améliorer la fonction propre de toute façon vous l'aimez

+0

pas aussi élégant que ce que je cherchais, mais des points pour l'extensibilité. –

1

Au lieu d'utiliser des expressions régulières est pour cela, une solution plus efficace est d'utiliser l'option rejoindre/split, observer:

>>> timeit.Timer((lambda:' '.join(' Sapphire RX460 OC 2/4GB'.split()))).timeit() 
0.7263979911804199 

>>> def f(): 
     return re.sub(" +", ' ', " Sapphire RX460 OC 2/4GB").split() 

>>> timeit.Timer(f).timeit() 
4.163465976715088 
+0

Je reviendrai sur cette réponse lorsque mes extraits grossiront. Je vous remercie!! –

+0

Le plaisir est tout à moi. – hd1

+0

Comparaison imparfaite. –