2010-12-02 19 views
3

J'utilise BeautifulSoup pour extraire les balises TableData d'une table. Les TD ont une classe de 'a', 'u', 'e', ​​'disponible-indisponible' ou 'indisponible-disponible'. (Oui, je sais que les noms de classes originales mais bon ...)modèle Regex avec des exceptions Python (toujours manipuler)

Voici un exemple:

<tr> 
    <td class="u">4</td> 
    <td class="unavailable-available">5</td> 
    <td class="a'>6</td> 
    <td class="available-unavailable">7</td> 
    <td class="u">8</td> 
    ... 

Je travaille avec une ligne qui intègre un re.compile():

tab = [int(tag.string) for tag in soup.find('table',{'summary':tableSummary}).findAll("td", attrs = {"class": re.compile('\Aa')})] 

je besoin d'extraire tout le td est avec un nom de classe « a » et «indisponible-disponible. J'ai essayé quelques assertions négatives-lookahead mais sans beaucoup de chance. Je les légendes valeur regex qui peut produire la regex correcte ...

+0

Ha ha! Fait cela je pense. – timbo

+0

Avez-vous vraiment html avec des guillemets dépareillées comme '" a'' entrée montre? – PaulMcG

Répondre

2
table.findAll('td', attrs = {"class":re.compile(r'(^|\s)(a|unavailable-available)($|\s)')}) 

Cela correspond début de la chaîne ou des espaces suivis par « un » ou « indisponible-disponible » suivi d'un espace ou fin de chaîne. Donc, ça va correspondre à toutes ces sortes de choses

class="a" 
class="a ui-xxx" 
class="ui-xxx a" 
class="ui-xxx a ui-yyy" 
class="unavailable-available" 
class="unavailable-available foo" 
+0

+1 pour la robustesse et d'être explicite sur ce qui est recherché. –

+0

Vous devez utiliser une chaîne brute ou '\ s' sera . mal interprété, je pris la liberté d'éditer votre message –

+0

@ Tim: normalement je me souviens, mais cette fois j'ai oublié Merci pour le mettre à jour, il est plus précis de cette façon - bien que ce n'est pas plus précis (' « d \ » ==.. '\\ s' == r '\ s'', essayez-le.) J'aurais remarqué si ça n'avait pas marché,' car je l'ai essayé –

0

HA!

re.compile('^a(?!vail)|^un') 
  • matchs tout en commençant un ça ne procédait par « vail » et tout démarrage « un de. Bon un!
0

Je m'incline devant les prouesses RE des autres. Mais comme une alternative point de données BS + RE, voici une interprétation de pyparsing (en supposant que ces citations ne correspondent pas méchants se fixe):

html = """ 
<tr> 
    <td class="u">4</td> 
    <td class="unavailable-available">5</td> 
    <td class="a">6</td> 
    <td class="available-unavailable">7</td> 
    <td class="u">8</td> 
""" 

from pyparsing import makeHTMLTags, withAttribute, oneOf, SkipTo 

# define opening and closing tag expressions 
td,tdEnd = makeHTMLTags("TD") 

# only want opening TD's with certain classes 
td.setParseAction(withAttribute(**{'class':oneOf("a unavailable-available")})) 

# define overall pattern 
patt = td + SkipTo(tdEnd)("contents") + tdEnd 

# search for matches 
for t in patt.searchString(html): 
    print t.dump() 

Prints:

['TD', ['class', 'unavailable-available'], False, '5', '</TD>'] 
- class: unavailable-available 
- contents: 5 
- empty: False 
- endTd: </TD> 
- startTd: ['TD', ['class', 'unavailable-available'], False] 
    - class: unavailable-available 
    - empty: False 
['TD', ['class', 'a'], False, '6', '</TD>'] 
- class: a 
- contents: 6 
- empty: False 
- endTd: </TD> 
- startTd: ['TD', ['class', 'a'], False] 
    - class: a 
    - empty: False 

Pour chaque match, vous pouvez également accéder t.contents et t['class'] (doit utiliser la syntaxe dict car class est un mot-clé Python) directement.