Další pokračování regulérních výrazů. Dnes se naučíme získávat z textu údaje.
re.compile
Tato funkce zkompiluje regulární výraz do řeči regulárních výrazů:
>>> r=re.compile(r"\d+")
>>> r
<_sre.SRE_Pattern object at 0x00BBEA70>
>>> dir(r)
['__copy__', '__deepcopy__', 'findall', 'finditer', 'match', 'scanner', 'search', 'split', 'sub', 'subn']
Jak vidíte, tento objekt má více metod. Některé jsou pro nás známe, jako třeba findall
, ale ten zbytek si budeme muset vysvětlit. Avšak než se tak stane, vysvětlíme si metaznak (...)
. Pomocí tohoto metaznaku můžete definovat skupiny znaků, ke kterým budete moci později přistupovat číselnými indexy podle pořadí závorek v textu. Více snad pochopíte z příkladu:
r=re.compile(r"(\d+) (\w+)")
#Pokud necháme "55 aa" procházet tímto regulárním výrazem, tak na indexu 1 budou čísla (55) a na indexu 2 písmena (aa)
My začneme metodou search
. Tato metoda, podobně jako re.compile
, vrací objekt re
.
>>> r=re.compile(r"(\d+) (\w+)")
>>> hledani=r.search("55 aa")
>>> hledani
<_sre.SRE_Match object at 0x01E3D9F8>
>>> dir(hledani)
['__copy__', '__deepcopy__', 'end', 'expand', 'group', 'groupdict', 'groups', 'span', 'start']
My jako první použijeme metodu group
. Ta přijímá jako parametr index (my umíme používat zatím pouze číselné indexy) a vrací shodný objekt z regulárního výrazu:
>>> hledani.group(1)
'55'
>>> hledani.group(2)
'aa'
Metaznak (?P<jmeno>...)
Pomocí tohoto metaznaku můžeme definovat skupiny znaků jinak než nám již známým číselným indexem. Pokud tedy budeme chtít přistoupit k výrazu vráceném metodou search
zavoláme metodu group("jmeno")
:
>>> r=re.compile(r"(?P<slovo_a>\W?[aA]\w+)")#Definujeme skupinu "slovo_a"
re.finditer
Tato metoda přijímá jako parametry regulární výraz a prohledávaný řetězec. My ji použijeme pro získání dat z řetězce.
>>> r=re.compile(r"(?P<slovo_a>\W?[aA]\w+)")
>>> re.finditer(r,"auto")
<callable-iterator object at 0x00C9AC90>
Vrací iterátor
, tudíž můžeme prohnat výstup cyklem for
:
>>> r=re.compile(r"(?P<slovo_a>\W?[aA]\w+)")
>>> for prvek in re.finditer(r,"auto"):
print prvek.group("slovo_a")
auto
Proměnná prvek poskytuje mimo jiné i metodu groupdict
. Ta vrací slovník všech definovaných skupin:
>>> for prvek in re.finditer(r,"auto"):
print prvek.groupdict()
{'slovo_a': 'auto'}
Další metaznaky
Pro jednodušší práci s regulárními výrazy by to chtělo trochu rozšířit naši znalost metaznaků:
.
– reprezentuje jakýkoliv znak kromě nového řádku.\
&dnash; tento znak známe jako označení speciální posloupnosti, ale to není jeho jediná funkce. Pomocí toho znaku můžeme vyhledávat znaky, které jsou za normálních okolností metaznaky:5\*2
. Tento výraz odpovídá "5*2".*
– regulární výraz před*
se může opakovat libovolněkrát (0×,1×,100×…)
Praktické příklady
Na závěr si ukážeme pár praktických příkladů:
Najdi všechny odkazy v textu
Máme zdrojový kód nějaké stránky a chceme z něj získat všechny odkazy.
# -*- coding: cp1250 -*-
import re
import urllib
fp = urllib.urlopen('http://www.programujte.com')#Načteme nějakou stránku
data = fp.read()#Získáme zdrojový kód stránky
fp.close()
for prvek in re.findall(r'href="(.*?)"',data):
print prvek
Najdi všechny e-mailové adresy:
# -*- coding: cp1250 -*-
import re
r=re.compile(r"(?P<email>[\w\d]*@[\w\d]*\.[\w\d]*)",re.U)
#Nejprve definujeme skupinu 'email'
#[\w\d]* - v názvu e-mailu mohou být čísla a písmena
#@ - potom následuje zavináč
#[\w\d]* - číslice nebo písmena se mohou vícekrát opakovat
#\. - tyto dva znaky reprezentují tečku
#[\w\d]* - číslice nebo písmena se mohou vícekrát opakovat
data="jakub_vojacek@programujte.com, curo@programujte.com"
for prvek in r.finditer(data):
print prvek.group("email")