2010-02-21 15 views
9

J'ai une page qui ressemble à ceci:Utilisation de BeautifulSoup pour analyser les lignes séparées par des étiquettes <br>?

Company A<br /> 
123 Main St.<br /> 
Suite 101<br /> 
Someplace, NY 1234<br /> 
<br /> 
<br /> 
<br /> 
Company B<br /> 
456 Main St.<br /> 
Someplace, NY 1234<br /> 
<br /> 
<br /> 
<br /> 

Parfois, il y a deux plutôt que trois balises « br » séparant les entrées. Comment utiliser BeautifulSoup pour analyser ce document et extraire les champs? Je suis perplexe parce que les morceaux de texte dont j'ai besoin ne sont pas contenus dans des balises de paragraphe (ou similaires) que je peux simplement parcourir.

Répondre

2

Une fois que vous avez ce fragment HTML, utilisez simplement une regex pour remplacer <br /> suivi d'un retour à la ligne optionnel par une nouvelle ligne, puis scindé sur plusieurs retours à la ligne. Cela devrait aboutir à plusieurs paragraphes individuels que vous pouvez traiter manuellement.

+0

Merci pour la réponse, mais malheureusement il est pas aussi simple que d'utiliser une expression régulière. J'ai simplifié le document ci-dessus pour mieux illustrer ma question. Le document réel a un fouillis de balises de formatage HTML et similaires. – jamieb

+1

Mais vous ne vous souciez pas du document, juste de la partie séparée par les balises '
'. Utilisez BeatifulSoup pour extraire cette partie en premier. –

+0

Je ne sais pas pourquoi quelqu'un a rejeté votre réponse; J'apprécie l'aide. Je vais essayer quelques idées en fonction de votre suggestion. J'espérais juste que BeautifulSoup aurait éliminé le besoin d'analyse manuelle. Je vous remercie. – jamieb

0

vous pouvez faire un peu de manipulation avant tout. Par exemple, remplacez toutes les nouvelles lignes par des espaces, puis remplacez 2 occurrences et plus par <br /> par un autre délimiteur comme |. après cela, vous pouvez obtenir vos champs.

html=""" 
Company A<br /> 
123 Main St.<br /> 
Suite 101<br /> 
Someplace, NY 1234<br /> 
<br /> 
<br /> 
<br /> 
Company B<br /> 
456 Main St.<br /> 
Someplace, NY 1234<br /> 
<br /> 
<br /> 
<br /> 
""" 
import re 
newhtml=html.replace("\n","") 
pat=re.compile("(<br \/>){2,}",re.DOTALL|re.M) 
print pat.sub("|",newhtml) 

sortie

$ ./python.py 
Company A<br />123 Main St.<br />Suite 101<br />Someplace, NY 1234|Company B<br />456 Main St.<br />Someplace, NY 1234| 

maintenant vos informations de l'entreprise sont séparés par des tuyaux.

0

Peut-être que vous pouvez utiliser cette fonction:

def partition_by(pred, iterable): 
    current = None 
    current_flag = None 
    chunk = [] 
    for item in iterable: 
     if current is None: 
      current = item 
      current_flag = pred(current) 
      chunk = [current] 
     elif pred(item) == current_flag: 
      chunk.append(item) 
     else: 
      yield chunk 
      current = item 
      current_flag = not current_flag 
      chunk = [current] 
    if len(chunk) > 0: 
     yield chunk 

Ajouter quelque chose à vérifier pour être une balise <br /> ou saut de ligne:

def is_br(bs): 
    try: 
     return bs.name == u'br' 
    except AttributeError: 
     return False 

def is_br_or_nl(bs): 
    return is_br(bs) or u'\n' == bs 

(ou tout autre chose est plus approprié ... Je suis pas bien avec BeautifulSoup.)

utilisez ensuite partition_by(is_br_or_nl, cs) pour obtenir (pour cs ensemble à BeautifulSoup.BeautifulSoup(your_example_html).childGenerator())

[[u'Company A'], 
[<br />], 
[u'\n123 Main St.'], 
[<br />], 
[u'\nSuite 101'], 
[<br />], 
[u'\nSomeplace, NY 1234'], 
[<br />, u'\n', <br />, u'\n', <br />, u'\n', <br />], 
[u'\nCompany B'], 
[<br />], 
[u'\n456 Main St.'], 
[<br />], 
[u'\nSomeplace, NY 1234'], 
[<br />, u'\n', <br />, u'\n', <br />, u'\n', <br />]] 

Cela devrait être assez facile à traiter. Pour généraliser cela, vous devrez probablement écrire un prédicat pour vérifier si son argument est quelque chose qui vous intéresse ... Ensuite, vous pouvez l'utiliser avec partition_by pour que tout le reste soit regroupé. Notez que les choses qui vous intéressent sont regroupées aussi - vous devez en principe traiter chaque élément de chaque seconde liste produite par le générateur résultant, en commençant par le premier qui inclut les choses qui vous intéressent.

6

Vous devriez regarder dans l'attribut .strings trouvé dans les balises, puis utiliser "\ n" .join() sur cela.

0

J'ai slimier question .THIS comment je résolu

html=html.replace('<br>','<br />')