Edukira joan

PYTHON liburua/Aplikazioak I: Internet

Wikibookstik

10. Aplikazioak I: Internet

[aldatu]

Kapitulu honetan Interneteko baliabideak lantzen ikasiko dugu. Alde batetik hiru ariketa proposatzen ditugu HTML orriekin lan egiten ikasteko, hiruretan BeautifulSoup liburutegia erabiliz. Estekak bilatuko ditugu, orrien artean ibiliko gara eta web orri berri bat sortuko dugu. Horrez gain, azken ariketan Twitterrekin lan egingo dugu. Kasu horretan, txioen zuzeneko jarraipena nola egiten den ikasiko dugu tweepy liburutegiaz. Ikusten denez, eta aurreko kapituluetan egindakoaren ildotik, atazetarako egokiak diren moduluak berrerabiltzea da gaur egungo programazioaren gakoetako bat.

10.1. ARIKETA: WIKINEWS-ETIK BERRIEN IZENBURUAK ERAUZTEA

[aldatu]

Ariketa honetan Wikinews-eko Europako portadan (https://en.wikinews.org/wiki/Portal:Europe) agertzen diren berriak eta haien titularrak jasoko ditugu. Hasi baino lehen, web orriaren HTML kodea aztertzea ezinbestekoa da, informazioa non eta nola gordetzen den aztertzeko. Horretarako, web orriaren iturburu-kodea atzi daiteke nabigatzailetik (Mozilla-Firefox nabigatzailearekin, adibidez, Ctrl-u tekla-konbinazioarekin ikus daiteke). Kontuan izan behar da web orri horren iturburu-kodea etengabe aldatzen doala, eta hortaz, baliteke behin ondo funtzionatzen duen kodeak, hortik eta denbora batera funtzionatzeari uztea.

Ariketa honen kasuan, Wikinews-en iturburu-kodea aztertuko dugu, berrien estekak eta izenburuak non aurkitzen diren aztertzeko, gero izenburuak pantailaratzeko.

Web orriari gainetik begiratuta (ikus beheko kode-zatia), titularrak buletekin ( < li > elementuak) agertzen direla ikus dezakegu erraz asko.

Gehiago sakonduz, estekaren elementua ( < a > elementua), buleta-elementu baten azpitik agertzen dela baiezta dezakegu. Gainera, esteka-elementuek title atributua definituta dute, berriaren izenburua barneratzen duena. Hori horrela izanik, script bat egingo dugu zeinak web orria atzitu eta bertatik title atributua duten esteka-elementu guztiak jasoko dituen, eta banan banan begiratuko dugu ea buleta-elementu bati lotuta ote dagoen. Baiezko kasuetan, berri baten esteka dela baieztatuko dugu eta haren izenburua pantailaratuko dugu.

Ariketa honetarako 7.3. atalean ikusitako modulua berrerabiliko dugu web orria atzitzeko: urllib.request. Modulu horrez gain, BeautifulSoup modulua (bs4 izena erabiltzen da inportazioan) erabiliko dugu HTML egituraren barruan elementuak identifikatzeko. Modulu horrek HTML orria zuhaitz bilakatzen du, informazioa erauztea asko errazten duena. BeautifulSoup oso ahaltsua da eta gaizki eratutako HTML orriekin ere lan egitea ahalbidetzen du.

Modulu hori erabiltzeko, aurrena instalatu beharra dago, ez baitator Pythonen aurre instalatuta. Horretarako, nahikoa da pip3 bidez instalatzea honako komando honen bidez.

$ sudo pip3 install bs4

10.1. programak Wikinews-eko web orritik berrietara doazen estekak bilatzen ditu, eta beraien izenburuak pantailaratzen ditu.

Horretarako, aurrena web orria irekitzen da eta zuhaitz bilakatzen du BeautifulSoup objektuan lxlm analizatzaileren bitartez analizatu ondoren.

orria = urlopen(sys.argv[1])
soup = BeautifulSoup(orria,lxml)

Ostean, esteka-elementuak diren elementu guztiak jasotzen dira findall metodoaren bidez (lotura_guztiak aldagaian), eta begizta baten bidez elementu horien gurasoa egiaztatzen da ea buleta-elementua den, baiezko kasuan pantailaratuz.

#"https://en.wikinews.org/wiki/Portal:Europe"
import sys
#weborria atzitzeko erabiliko den liburutegia inportatu 
from urllib.request import urlopen

#web orria atzitu eta html-a orria aldagaian gorde
# programa komando bidez exekutatzeko: orria = urlopen(sys.argv[1])
orria = urlopen("https://en.wikinews.org/wiki/Portal:Europe")
#informazioa parseatzeko Beautiful soup funtzioak jaso
from bs4 import BeautifulSoup
#orria aldagaiko html-a parseatu eta Beatiful Soup formatuan gorde
soup = BeautifulSoup(orria,"lxml")

#link guztiak aurkitu:
lotura_guztiak = soup.find_all("a",{'title':True})
#link bakoitzerako href aldagaiaren edukia jaso
n_erref = 10 # Aztertuko dira lehen n_erref erreferenziak bakarrik
for lotura in lotura_guztiak[:n_erref]:
    if 'li' == lotura.parent.name:
        print(lotura["title"])

Aurreko programa hori komando lerrotik egikaritu nahi bada hau litzateke komandoa:

python3 p10-1.py https://en.wikinews.org/wiki/Portal:Europe

Honelako emaitza lortuko da:

Georgian tennis player Nikoloz Basilashvili arrested on domestic violence charge
Astronomer tells Wikinews about discovery of closest black hole known so far
Neuroscientists tell Wikinews about empathy and harm aversion observed in lab rats
English mathematician John Horton Conway dies after contracting COVID-19
SARS-CoV-2 surpasses one million infections worldwide
British mathematician Richard K. Guy dies at 103

BeautifulSoup moduluaren inguruan informazio zehatza eskuratzeko https://www.crummy.com/software/BeautifulSoup/bs4/doc/ gunea kontsulta daiteke.

10.2. ARIKETA: EUSKAL HERRIKO FUTBOL-SELEKZIOKO JOKALARIEN ESTEKA WIKIPEDIAN

[aldatu]

Aurreko ariketa oinarri harturik, Euskal Herriko futbol-selekzioak Wikipedian duen artikulutik jokalariak jaso nahi ditugu oraingoan. Baina jokalarien izenak jasotzeaz gain, beraiei buruzko informazio gehiago jaso nahi dugu, beraien Wikipediako artikuluko helbidea ere bai. Informazio hori hiztegi batean jasoko dugu.

Web orri batetik informazioa erauzi nahi dugunez, aurrena web orriaren iturburu-kodea aztertu behar dugu, jaso nahi dugun informazioa non dagoen eta nola egituratzen den jakin ahal izateko. Jarraian https://eu.wikipedia.org/wiki/Euskal_Herriko_futbol_selekzioa orriaren iturburu-kodearen zati bat erakusten dugu azalduko duguna ulertzen laguntzeko.

<h2><span class="mw-headline" id="Jokalari_aipagarriak">Jokalari aipagarriak</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;veaction=edit&amp;section=13" class="mw-editsection-visualeditor" title="Aldatu atal hau: «Jokalari aipagarriak»">aldatu</a><span class="mw-editsection-divider"> | </span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;action=edit&amp;section=13" title="Aldatu atal hau: «Jokalari aipagarriak»">aldatu iturburu kodea</a><span class="mw-editsection-bracket">]</span></span></h2>
<div style="font-style: italic; padding-left: 2em; margin-bottom: 0.5em;">Sakontzeko, irakurri: «<a href="/wiki/Euskal_Herriko_gizonezko_futbol_selekzioaren_jokalarien_zerrenda" class="mw-redirect" title="Euskal Herriko gizonezko futbol selekzioaren jokalarien zerrenda">Euskal Herriko gizonezko futbol selekzioaren jokalarien zerrenda</a>»</div>
<h3><span class="mw-headline" id="Partehartze_gehien">Partehartze gehien</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;veaction=edit&amp;section=14" class="mw-editsection-visualeditor" title="Aldatu atal hau: «Partehartze gehien»">aldatu</a><span class="mw-editsection-divider"> | </span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;action=edit&amp;section=14" title="Aldatu atal hau: «Partehartze gehien»">aldatu iturburu kodea</a><span class="mw-editsection-bracket">]</span></span></h3>
<p>Hona hemen Euskal Herriko futbol selekzioan hiru bider edo gehiagotan aritutako jokalarien zerrenda, <a href="/wiki/2019" title="2019">2019ko</a> <a href="/wiki/Maiatzaren_29" title="Maiatzaren 29">maiatzaren 29an</a>:
</p>
<table class="wikitable">

<tbody><tr>
<th>Partidak</th>
<th>Jokalariak
</th></tr>
<tr>
<td align="center">14</td>
<td><a href="/wiki/Xabi_Prieto" title="Xabi Prieto">Xabi Prieto</a>
</td></tr>
<tr>
<td align="center">13</td>
<td><a href="/wiki/Aritz_Aduriz" title="Aritz Aduriz">Aritz Aduriz</a>
</td></tr>
<tr>
<td align="center">12</td>
<td><a href="/wiki/Igor_Gabilondo" title="Igor Gabilondo">Igor Gabilondo</a>, <a href="/wiki/Gorka_Iraizoz" title="Gorka Iraizoz">Gorka Iraizoz</a>
</td></tr>
<tr>
<td align="center">11</td>
<td><a href="/wiki/Julen_Guerrero" title="Julen Guerrero">Julen Guerrero</a>, <a href="/wiki/Joseba_Etxeberria" title="Joseba Etxeberria">Joseba Etxeberria</a>, <a href="/wiki/Asier_Riesgo" title="Asier Riesgo">Asier Riesgo</a>
</td></tr>

Kasu honetan, “jokalari aipagarriak” ataleko jokalariak jaso nahi ditugu. Iturburu-kodea aztertzen badugu, Wikipediako orrien atalak < span > elementuaren klase batetik bereizten direla kontura gaitezke, mw-headline klasearekin hain zuzen ere, eta elementu horren bitartez interesatzen zaigun atala identifika dezakegu (“Jokalari_aipagarriak”).

Kodea aztertzen jarraituta, interesatzen zaizkigun esteka-elementu guztiak taula beraren barruan daudela ohar gaitezke, atalaren elementuaren jarraian dagoen taula alegia. Kontuan izan, ez dagoela < span > elementuaren ume batean, hortaz dagokion maila egokia bilatu behar da. Dena dela, esteka guztiak taula berean daudela ikusteak asko erraztuko dizkigu gauzak.

“Jokalari_aipagarriak” identifikadorea duen < span > elementua bilatuko dugu aurrena, find metodoaren bidez, eta haren gurasoa den < h2 > elementua jasoko dugu gero parent metodoaren bidez:

jokalari_atala = soup.find(span,{id:Jokalari_aipagarriak})
gurasoa = jokalari_atala.parent
# h2 elementua

Azken horren maila berean dago < table > elementua, hortaz, begizta baten bidez banan-banan < table > elementua bilatuko dugu, eta behin aurkituta, haren azpian dauden esteka-elementu guztiak erauziko ditugu nextSibling metodoaren bidez.

while hurrengoa and hurrengoa.name != table:
  hurrengoa = hurrengoa.nextSibling
if hurrengoa:
  taula = hurrengoa

Estekaren helbidea href atributuaren baitan gordetzen da HTML kodean, baina Wikipediaren kasuan, esteka partzialak dira (ez dute URL osoa aipatzen), eta euskarazko esteken kasuan https://eu.wikipedia.org helbidea atxikitu behar zaie hasieran.

for jokalari_esteka in taula.find_all(a):
  esteka = https://eu.wikipedia.org+jokalari_esteka[href]

Horrez gain, kontuan izan beharra dugu jokalari batzuen Wikipedia orria sortu gabe dagoela. Hori esteka-elementuaren atributu berezi baten bidez adierazten da, class=“new” atributu-balioaren bidez. Ondoko kodean ezaugarri hori duten jokalariekin ondoren ezer ez egitea (continue bidez begizta batean iterazio baten bukaera adierazten da, ikus 4. kapitulua) adierazten da.

if class in jokalari_esteka:
  continue

Jokalari batzuek, web orria izan arren, informazio-kutxarik ez daukate edota “Futbolariaren informazioa” atala hutsik daukate. Informazio falta duten web orriak baztertzeko, salbuespen bat kudeatzeko kodea sartuko dugu (try/except bidez) errorerik gerta ez dadin, eta salbuespenen kasuan hutsa (None) itzuliko dugu.

10.2. programan orain arte azalduko guztia bildu dugu.

10.2. programa. Euskal Herriko futbol-selekzioko jokalarien ibilbidea erauztea Wikipediatik.

import sys
from urllib.request import urlopen
from bs4 import BeautifulSoup

orria = urlopen("https://eu.wikipedia.org/wiki/Euskal_Herriko_futbol_selekzioa")
#orria = urlopen(sys.argv[1])
soup = BeautifulSoup(orria,"lxml")

#Jokalari aipagarriak atala aurkitu
jokalari_atala = soup.find("span",{"id":"Jokalari_aipagarriak"})
gurasoa = jokalari_atala.parent # h2 elementua
hurrengoa = gurasoa.nextSibling
while hurrengoa and hurrengoa.name != "table":
    hurrengoa = hurrengoa.nextSibling

# jokalariak banan-bana aztertu
hiztegia = {}
if hurrengoa:
    taula = hurrengoa
    for jokalari_esteka in taula.find_all("a"):
        if "class" in jokalari_esteka:
            print(jokalari_esteka["title"],"Ez")
            continue
        esteka = "https://eu.wikipedia.org"+jokalari_esteka["href"]
        hiztegia[jokalari_esteka["title"]] = esteka

print(len(hiztegia), "jokalari:")
print(hiztegia)

Emaitza hau zen 2020ko maiatzean:

94 jokalari:
{'Xabi Prieto': 'https://eu.wikipedia.org/wiki/Xabi_Prieto',
 'Aritz Aduriz': 'https://eu.wikipedia.org/wiki/Aritz_Aduriz',
 'Igor Gabilondo': 'https://eu.wikipedia.org/wiki/Igor_Gabilondo',
 'Gorka Iraizoz': 'https://eu.wikipedia.org/wiki/Gorka_Irai}zoz',
 'Julen Guerrero': 'https://eu.wikipedia.org/wiki/Julen_Guerrero'
 ...
}

10.3. ARIKETA: EUSKAL HERRIKO FUTBOL-SELEKZIOKO JOKALARIEN IBILBIDEA ERAUZTEA WIKIPEDIATIK

[aldatu]

KONTUZ, futbolariaren informazioa beste modu batera lortu behar da. Informazio hori orain ez dago infoboxean.

KONTUZ

Wikipediako aurreko ariketa oinarri harturik, Wikipediaren Euskal Herriko futbol-selekzioaren web orritik jokalariak jaso nahi ditugu oraingoan. Baina jokalarien izenak jasotzeaz gain, beraiei buruzko informazio gehiago jaso nahi dugu, beraien Wikipediako sarrerako informazio-kutxetatik (info-box).

Jaso nahi dugun informazioa futbolariaren ibilbidea izango da, hau da, futbolariak jokatutako talde guztiak aipatu nahi ditugu, bertan jokatutako urteak eta, informaziorik izanez gero, jokatutako partida kopurua eta sartutako golak. Informazio hori hiztegi batean jasoko dugu.

Web orri batetik informazioa erauzi nahi dugunez, aurrena web orriaren iturburu-kodea aztertu behar dugu, jaso nahi dugun informazioa non dagoen eta nola egituratzen den jakin ahal izateko. Jarraian https://eu.wikipedia.org/wiki/Euskal_Herriko_futbol_selekzioa orriaren iturburu-kodearen zati bat erakusten dugu azalduko duguna ulertzen laguntzeko.

<h2><span class="mw-headline" id="Jokalari_aipagarriak">Jokalari aipagarriak</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;veaction=edit&amp;section=13" class="mw-editsection-visualeditor" title="Aldatu atal hau: «Jokalari aipagarriak»">aldatu</a><span class="mw-editsection-divider"> | </span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;action=edit&amp;section=13" title="Aldatu atal hau: «Jokalari aipagarriak»">aldatu iturburu kodea</a><span class="mw-editsection-bracket">]</span></span></h2>
<div style="font-style: italic; padding-left: 2em; margin-bottom: 0.5em;">Sakontzeko, irakurri: «<a href="/wiki/Euskal_Herriko_gizonezko_futbol_selekzioaren_jokalarien_zerrenda" class="mw-redirect" title="Euskal Herriko gizonezko futbol selekzioaren jokalarien zerrenda">Euskal Herriko gizonezko futbol selekzioaren jokalarien zerrenda</a>»</div>
<h3><span class="mw-headline" id="Partehartze_gehien">Partehartze gehien</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;veaction=edit&amp;section=14" class="mw-editsection-visualeditor" title="Aldatu atal hau: «Partehartze gehien»">aldatu</a><span class="mw-editsection-divider"> | </span><a href="/w/index.php?title=Euskal_Herriko_futbol_selekzioa&amp;action=edit&amp;section=14" title="Aldatu atal hau: «Partehartze gehien»">aldatu iturburu kodea</a><span class="mw-editsection-bracket">]</span></span></h3>
<p>Hona hemen Euskal Herriko futbol selekzioan hiru bider edo gehiagotan aritutako jokalarien zerrenda, <a href="/wiki/2019" title="2019">2019ko</a> <a href="/wiki/Maiatzaren_29" title="Maiatzaren 29">maiatzaren 29an</a>:
</p>
<table class="wikitable">

<tbody><tr>
<th>Partidak</th>
<th>Jokalariak
</th></tr>
<tr>
<td align="center">14</td>
<td><a href="/wiki/Xabi_Prieto" title="Xabi Prieto">Xabi Prieto</a>
</td></tr>
<tr>
<td align="center">13</td>
<td><a href="/wiki/Aritz_Aduriz" title="Aritz Aduriz">Aritz Aduriz</a>
</td></tr>
<tr>
<td align="center">12</td>
<td><a href="/wiki/Igor_Gabilondo" title="Igor Gabilondo">Igor Gabilondo</a>, <a href="/wiki/Gorka_Iraizoz" title="Gorka Iraizoz">Gorka Iraizoz</a>
</td></tr>
<tr>
<td align="center">11</td>
<td><a href="/wiki/Julen_Guerrero" title="Julen Guerrero">Julen Guerrero</a>, <a href="/wiki/Joseba_Etxeberria" title="Joseba Etxeberria">Joseba Etxeberria</a>, <a href="/wiki/Asier_Riesgo" title="Asier Riesgo">Asier Riesgo</a>
</td></tr>

Kasu honetan, “jokalari aipagarriak” ataleko jokalariak jaso nahi ditugu. Iturburu-kodea aztertzen badugu, Wikipediako orrien atalak < span > elementuaren klase batetik bereizten direla kontura gaitezke, mw-headline klasearekin hain zuzen ere, eta elementu horren bitartez interesatzen zaigun atala identifika dezakegu (“Jokalari_aipagarriak”).

Kodea aztertzen jarraituta, interesatzen zaizkigun esteka-elementu guztiak taula beraren barruan daudela ohar gaitezke, atalaren elementuaren jarraian dagoen taula alegia. Kontuan izan, ez dagoela < span > elementuaren ume batean, hortaz dagokion maila egokia bilatu behar da. Dena dela, esteka guztiak taula berean daudela ikusteak asko erraztuko dizkigu gauzak.

“Jokalari_aipagarriak” identifikadorea duen < span > elementua bilatuko dugu aurrena, find metodoaren bidez, eta haren gurasoa den < h2 > elementua jasoko dugu gero parent metodoaren bidez:

jokalari_atala = soup.find(span,{id:Jokalari_aipagarriak})
gurasoa = jokalari_atala.parent
# h2 elementua

Azken horren maila berean dago < table > elementua, hortaz, begizta baten bidez banan-banan < table > elementua bilatuko dugu, eta behin aurkituta, haren azpian dauden esteka-elementu guztiak erauziko ditugu nextSibling metodoaren bidez.

while hurrengoa and hurrengoa.name != table:
  hurrengoa = hurrengoa.nextSibling
if hurrengoa:
  taula = hurrengoa

Estekaren helbidea href atributuaren baitan gordetzen da HTML kodean, baina Wikipediaren kasuan, esteka partzialak dira (ez dute URL osoa aipatzen), eta euskarazko esteken kasuan https://eu.wikipedia.org helbidea atxikitu behar zaie hasieran.

for jokalari_esteka in taula.find_all(a):
  esteka = https://eu.wikipedia.org+jokalari_esteka[href]

Horrez gain, kontuan izan beharra dugu jokalari batzuen Wikipedia orria sortu gabe dagoela. Hori esteka-elementuaren atributu berezi baten bidez adierazten da, class=“new” atributu-balioaren bidez. Ondoko kodean ezaugarri hori duten jokalariekin ondoren ezer ez egitea (continue bidez begizta batean iterazio baten bukaera adierazten da, ikus 4. kapitulua) adierazten da.

if class in jokalari_esteka:
  continue

Aurreko guztia kontuan izanik, eta kodea ulergarriagoa eta egituratuagoa izan dadin, funtzio berri bat definituko dugu esteka batetik beharrezko informazioa erauziko duena. Funtzio horri futbolariaren_informazioa_erauzi deituko diogu. Funtzioak beste web orri batetik informazioa erauziko duenez, aurreko kodea idazterakoan bezala, web orria ondo aztertu behar dugu. Ondoren interesgarria den zati bat azaltzen da:

<div id=mw-content-text lang=eu dir=ltr class=mw-content-ltr>
<table class=toccolours ...>
<caption><big><b>Julen Guerrero</b></big></caption>
...
<tr>
<th ...>Futbolari ibilbidea</th>
</tr> <tr>
<td><b>Urteak</b></td>
<td><b>Taldea</b></td>
<td><b>Part. (golak)</b></td>
</tr> <tr>
<td>1991-1992<br /> 1992-2006</td>
<td><a href=/wiki/Bilbao_Athletic title=Bilbao Athletic>Bilbao Athletic</a><br
/> <a href=/wiki/Bilboko_Athletic_Kluba title=Bilboko Athletic Kluba>Athletic</
a></td>
<td>? (?)<br /> 372 (101)</td>
</tr> </table>

Kasu honetan, < div > elementu baten barruan mw-content-text identifikadorea duen elementuaren lehen taulan informazio-kutxako (info-box) informazioa agertzen da. Ariketa honetarako, informazio hori atzituko dugu find metodoaren bidez (bi urratsetan):

div = soup_jokalari.find(div,{id:mw-content-text})
info_box = div.find(table)

Ondoren kutxa egituraren baitan dagoen “Futbolari ibilbidea” hiztegiratuko dugu. Horretarako, taulan bertan dauden zutabe-goiburukoetan (elementua) bilatu beharko dugu “Futbolari ibilbidea”, jarraian horren atzetik datorren errenkada jasotzeko.

jokalari_ibilbidea = info_box.find(th,text = Futbolari ibilbidea)
gurasoa = jokalari_ibilbidea.parent
#Lau elementu aurrera egin behar ditugu egituraren arabera
taldeak = gurasoa.nextSibling.nextSibling.nextSibling.nextSibling

Jokalari batzuen kasuan ez da partida eta gol kopuruaren errenkada aurkitzen, eta, ondorioz, hutsa dagoen kasuan, beste datuen elementu kopuru bera duen zerrenda huts bat sortuko dugu prozesaketa automatikoa errazteko:

kopurua = len(urteak)
if len(eremuak) == 2:
    
partiduak = [""]*kopurua
else:
    
partiduak = eremuak[2].text.split("\n")

Informazio hori guztia zerrenden zerrenda batean sartuko dugu, eta hori izango da funtzioak itzuliko duen balioa:

futbolariaren_informazioa = []
for i in range(0,kopurua):  
  urtea = [urteak[i],klubak[i],partiduak[i]]
    futbolariaren_informazioa.append(urtea)

Jokalari batzuek, web orria izan arren, informazio-kutxarik ez daukate edota “Futbolariaren informazioa” atala hutsik daukate. Informazio falta duten web orriak baztertzeko, salbuespen bat kudeatzeko kodea sartuko dugu (try/except bidez) errorerik gerta ez dadin, eta salbuespenen kasuan hutsa (None) itzuliko dugu.

10.2. programan orain arte azalduko guztia bildu dugu.

10.2. programa. Euskal Herriko futbol-selekzioko jokalarien ibilbidea erauztea Wikipediatik.

import sys
from urllib.request import urlopen
from bs4 import BeautifulSoup

#jokalari baten orritik fulbolari ibilbidea erauzteko
def informazioa_erauzi(esteka):
    jokalari_orria = urlopen(esteka)
    soup_jokalari = BeautifulSoup(jokalari_orria,"lxml")
    try:
        div = soup_jokalari.find("div",{"class":"mw-content-ltr"})
        info_box = div.find("table")
        jokalari_ibilbidea = info_box.find("th",text = "Futbolari ibilbidea")
        gurasoa = jokalari_ibilbidea.parent
        #Lau elementu aurrera egin behar ditugu egituraren arabera
        taldeak = gurasoa.nextSibling.nextSibling.nextSibling.nextSibling
        eremuak = taldeak.find_all("td")
        urteak = eremuak[0].text.split("\n")
        klubak = eremuak[1].text.split("\n")
        kopurua = len(urteak)
        if len(eremuak) == 2:
            partiduak = [""]*kopurua
            print(esteka)
        else:
            partiduak = eremuak[2].text.split("\n")
        futbolariaren_informazioa = []            
        for i in range(0,kopurua):
            urtea = [urteak[i],klubak[i],partiduak[i]]
            futbolariaren_informazioa.append(urtea)
        return futbolariaren_informazioa
    except AttributeError:
        return None


orria = urlopen("https://eu.wikipedia.org/wiki/Euskal_Herriko_futbol_selekzioa")
#orria = urlopen(sys.argv[1])
soup = BeautifulSoup(orria,"lxml")
#Jokalari aipagarriak atala aurkitu
jokalari_atala = soup.find("span",{"id":"Jokalari_aipagarriak"})
gurasoa = jokalari_atala.parent # h2 elementua
hurrengoa = gurasoa.nextSibling

while hurrengoa and hurrengoa.name != "table":
    hurrengoa = hurrengoa.nextSibling
hiztegia = {}
if hurrengoa:
    taula = hurrengoa
    for jokalari_esteka in taula.find_all("a"):
        if "class" in jokalari_esteka:
            print(jokalari_esteka["title"],"Ez")
            continue
        esteka = "https://eu.wikipedia.org"+jokalari_esteka["href"]
        hiztegia[jokalari_esteka["title"]] = informazioa_erauzi(esteka)

print(hiztegia)
{'Xabi Prieto': None, 'Aritz Aduriz': None, 'Igor Gabilondo': None, 'Gorka Iraizoz': None, 'Julen Guerrero': None, 'Joseba Etxeberria': None, 'Asier Riesgo': None, 'Bittor Alkiza': None, 'Aitor Lopez Rekarte': None, 'Mikel Aranburu': None, 'Andoni Iraola': None, 'Agustin Aranzabal': None, 'Ismael Urzaiz': None, 'Mikel Labaka': None, 'Iñigo Martinez': None, 'Jose Antonio Pikabea': None, 'Javier de Pedro': None, 'Mikel Gonzalez': None, 'Markel Susaeta': None, 'Gaizka Toquero': None, 'Mikel San José': None, 'Aitor Karanka': None, 'Gaizka Mendieta': None, 'Carlos Gurpegi': None, 'Ion Ansotegi': None, 'Ander Iturraspe': None, 'Mikel Balenziaga': None, 'Rafael Alkorta': None, 'Josu Urrutia': None, 'Jose Angel Ziganda': None, 'Xabier Eskurza': None, 'Jon Pérez Bolo': None, 'Iñigo Idiakez': None, 'Antonio Karmona': None, 'Xabier Alonso': None, 'Gaizka Garitano Agirre': None, 'Francisco Javier Yeste': None, 'Mikel Alonso': None, 'Fernando Llorente': None, 'Javier Garrido': None, 'David Zurutuza': None, 'Imanol Agirretxe': None, 'Markel Bergara': None, 'Yuri Berchiche': None, 'Patxi Ferreira': None, 'Ion Andoni Goikoetxea': None, 'Andoni Imaz': None, 'Andoni Zubizarreta': None, 'Iñigo Larrainzar': None, 'Alberto López Fernández': None, 'Imanol Etxeberria': None, 'Óscar de Paula': None, 'Cesar Krutxaga': None, 'Asier del Horno': None, 'Fernando Amorebieta': None, 'Oier Sanjurjo': None, 'Jon Aurtenetxe': None, 'Beñat Etxebarria': None, 'Mikel Rico': None, 'Ibai Gomez': None, 'Asier Illarramendi': None, 'Daniel García Carrillo': None, 'Ander Capa': None, 'Javier Eraso': None, 'Luis Miguel Arconada': None, 'Aitor Begiristain': None, 'Andoni Goikoetxea': None, 'Luis Maria Lopez Rekarte': None, 'Julio Salinas': None, 'Ángel María Villar': None, 'Daniel Ruiz-Bazán': None, 'Ander Garitano': None, 'Julen Lopetegi': None, 'Genar Andrinua': None, 'Mikel Lasa': None, 'Andoni Cedrun': None, 'Imanol Alguacil': None, 'Javier Olaizola': None, 'Patxi Puñal': None, 'Roberto Martínez': None, 'Luis Prieto': None, 'Joseba Llorente': None, 'Gari Uranga': None, 'Pablo Orbaiz': None, 'Pantxi Sirieix': None, 'Josu Sarriegi': None, 'Iñaki Lafuente': None, 'Iñaki Muñoz': None, 'Iker Muniain': None, 'Carlos Martinez': None, 'Roberto Torres Morales': None, 'Eneko Bóveda': None, 'Xabier Etxeita': None, 'Manuel Alejandro García': None}

10.4. ARIKETA: JOKALARIEN IBILBIDEAREN WEB ORRIA SORTZEA

[aldatu]

!!! ERNE futbolarien datuak Wikidatatik hartu behar dira.

Aurreko ariketan Euskal Herriko futbol-selekzioko jokalarien ibilbidea hiztegi batean jaso dugu. Oraingoan hiztegi horretatik erauzitako informazioarekin web orri sinple bat egingo dugu.

Ataza erraza da oraingoan, HTML orri bat sortuko dugu BeautifulSoap liburutegia erabilita, eta horretarako hiztegian gordeta ditugun jokalariekin eta beraien ibilbidearen informazioarekin taula bat sortuko dugu.

Kontuan hartzeko lehen zehaztasuna: Wikipediak UTF-8 kodeketari jarraitzen dio bere web orrietan, eta, horrela, gure web orri berria ondo ikusarazteko web orriaren burukoan (< head > elementuaren baitan) < meta > elementuan UTF- 8 kodeketa zehaztu beharko dugu. Hori egingo ez bagenu, web orria karaktere arraroekin ikusiko genuke, tilet eta ñ letretan.

Bestalde, BeautifulSoup bidez HTML orri bat sortzeko, elementuak banan- banan sortu behar ditugu new_tag metodoaren bitartez. Metodo horretan elementu berriaren izena zehaztuko dugu, eta atributurik jarri nahiko bagenu, atributuaren izenari bere balioa esleituko genioke.

Adibidez, UTF kodeketarako honako lerro hau idatzi dugu:

meta = soup_irteera.new_tag("meta", charset="UTF-8")

HTML kodean ez dugu sakonduko, baina kodea ondo ulertzeko gogora dezagun taulen inguruko zenbait zehaztasun: errenkadak "tr" etiketaren bidez adierazten dira eta zutabeak "td" etiketaren bidez, "th" etiketa berezia dago taulen goiburuak adierazteko.

Beraz, aurrena errenkada batean ("tr") goiburukoak idatziko ditugu ("th"): "Jokalaria", "Urteak", "Kluba" eta "Part. (Gol)". Ostean, jokalarien ibilbideko errenkada bakoitzerako "tr" elementu bat sortuko dugu, eta ostean "td" elementu bana jokalariaren izenerako, urteetarako, kluberako eta partida kopuruetarako.

10.3. programan objektu horiek sortuz web orria osatu dugu, aurretik lortutako hiztegiko edukia sartuz taula batean. Programak ondo funtzionatu ahal izateko, 10.2. programari bukaeran gehitu behar diogu kodea.

10.4. programa. HTML taula bat sortzea hiztegi batetik:

import sys
from urllib.request import urlopen
from bs4 import BeautifulSoup,Tag

# probatzeko
# python3 p10-3_wiki.py https://eu.wikipedia.org/wiki/Euskal_Herriko_futbol_selekzioa jokalariak.html
# eta nabigatzailearekin jokalariak.html irekin

##### 10.2 ARIKETA:
#jokalari baten orritik fulbolari ibilbidea erauzteko
def informazioa_erauzi(esteka):
    jokalari_orria = urlopen(esteka)
    soup_jokalari = BeautifulSoup(jokalari_orria,"lxml")
    try:
        div = soup_jokalari.find("div",{"class":"mw-content-ltr"})
        info_box = div.find("table")
        jokalari_ibilbidea = info_box.find("th",text = "Futbolari ibilbidea")
        gurasoa = jokalari_ibilbidea.parent
        #Lau elementu aurrera egin behar ditugu egituraren arabera
        taldeak = gurasoa.nextSibling.nextSibling.nextSibling.nextSibling
        eremuak = taldeak.find_all("td")
        urteak = eremuak[0].text.split("\n")
        klubak = eremuak[1].text.split("\n")
        kopurua = len(urteak)
        if len(eremuak) == 2:
            partiduak = [""]*kopurua
        else:
            partiduak = eremuak[2].text.split("\n")
        futbolariaren_informazioa = []            
        for i in range(0,kopurua):
            urtea = [urteak[i],klubak[i],partiduak[i]]
            futbolariaren_informazioa.append(urtea)
        return futbolariaren_informazioa
    except AttributeError:
        return None

orria = urlopen(sys.argv[1])
soup = BeautifulSoup(orria,"lxml")
#Jokalari aipagarriak atala aurkitu
jokalari_atala = soup.find("span",{"id":"Jokalari_aipagarriak"})
gurasoa = jokalari_atala.parent # h2 elementua
hurrengoa = gurasoa.nextSibling

while hurrengoa and hurrengoa.name != "table":
    hurrengoa = hurrengoa.nextSibling
hiztegia = {}
if hurrengoa:
    taula = hurrengoa
    for jokalari_esteka in taula.find_all("a"):
        if "class" in jokalari_esteka:
            print(jokalari_esteka["title"],"Ez")
            continue
        esteka = "https://eu.wikipedia.org"+jokalari_esteka["href"]
        hiztegia[jokalari_esteka["title"]] = informazioa_erauzi(esteka)

####### 10.4. ARIKETA HEMENDIK AURRERA:

soup_irteera = BeautifulSoup("","lxml")
html = soup_irteera.new_tag("html")
head = soup_irteera.new_tag("head")
meta = soup_irteera.new_tag("meta", charset="UTF-8")
table = soup_irteera.new_tag("table")
tr = soup_irteera.new_tag("tr")
soup_irteera.append(html)
html.append(head)
html.append(table)
table.append(tr)
head.append(meta)
for izenburu in ["Jokalaria","Urteak","Kluba","Part. (Gol)"]:
    th = soup_irteera.new_tag("th")
    tr.append(th)
    th.append(izenburu)
for jokalari, ibilbidea in hiztegia.items():
    if not ibilbidea:
        continue
    for errenkada in ibilbidea:
        tr = soup_irteera.new_tag("tr")
        th.append(tr)
        td_j = soup_irteera.new_tag("td")
        tr.append(td_j)
        td_j.append(jokalari)
        td_u = soup_irteera.new_tag("td")
        tr.append(td_u)
        td_u.append(errenkada[0])
        td_k = soup_irteera.new_tag("td")
        tr.append(td_k)
        td_k.append(errenkada[1])
        td_p = soup_irteera.new_tag("td")
        tr.append(td_p)
        td_p.append(errenkada[2])
with open(sys.argv[2],'w') as fout:
    fout.write(soup_irteera.prettify())

10.3. programa exekutatuz gero, HTML orri batean idatziko da HTML kodea prettify metodoaren bidez. Horrela, lerro-jauziak eta indentazioa gehituko dizkiogu HTML kodeari, irakurterrazagoa izan dadin, baina horrek ez du eraginik izango nabigatzailean ikusiko den web orrian. Azkenean HTML orri hori fitxategi batean idazten da (2. parametroak zehazten duen izenarekin).

Probatzeko honako komando hau erabiliko dugu:

python3 p10-3.py https://eu.wikipedia.org/wiki/Euskal_Herriko_futbolselekzioa jokalariak.html

Programa horren exekuzioan agertuko dena halako zerbait izango da:

Bertan bigarren parametro gisa sortuko den fitxategiaren izena agertzen da.

jokalariak.html fitxategia nabigatzaile batekin irekiz gero, 10.1. irudikoa ikus dezakegu. Kontuan izan, hiztegi baten ordena ez dela finkoa, eta programaren exekuziotik exekuziora ordena alda daitekeela.

!!! 10.1 irudia

10.3. programa. HTML taula bat sortzea hiztegi batetik.

10.5. ARIKETA: TWITTERREKO TRAOLA BATEN JARRAIPENA EGITEA

[aldatu]
KONTUZ! Atal honetako programak ez dabiltza gaur egun. 2023ko uztailean X.com bihurtu zen Twitter, eta APIa ere aldatu zen. Gainera, 2024ko x.com sare sozialaren APIarekin ezin baita ia ezer egin.


Pythonen bidez Twitterrekin lan egiteko liburutegi asko daude garatuta (https://dev.twitter.com/overview/api/twitter-libraries). Liburu honetan tweepy (http://www.tweepy.org/) liburutegia erabiliko dugu, oso ahaltsua izateaz gain, oso komunitate aktiboa duelako eta kode irekia delako. Jarraian azaltzen dugun ariketa pythoncentral webguneko honako tutorial honetan dago oinarrituta: http://pythoncentral.io/introduction-to-tweepy-twitter-for-python/.

BeautifulSoup-ekin bezala, tweepy erabiltzeko aurrena instalatu beharko dugu. Norberaren konputagailuan erabiltzeko modu errazena pip3 erabiltzea da:

$ sudo pip3 install tweepy
!pip3 install tweepy

Kodearekin hasi baino lehen, konexioa ezarri beharko dugu Twitterrekin. Twitterrek OAuth metodoa (https://dev.twitter.com/oauth) erabiltzea eskatzen du konexioa ezarri eta kautotu ahal izateko. Metodo horrek kautotzeko bi modu eskaintzen ditu, aplikazio-erabiltzaile ohiko kautotzea, eta “aplikazioa bakarrik” (application-only) kautotzea.

Adibide honetarako, azkeneko kautotze modua erabiliko dugu: “aplikazioa bakarrik”. Modu horretan, aplikazioa bere izenean kautotzen da, erabiltzaile zehatz baten beharrik izan gabe. Horrek, baina, murriztapen batzuk ekartzen ditu, ezin izango baitugu txiorik idatzi, erabiltzaileak bilatu, etab.

Beraz, kodearekin hasi baino lehen aplikazio bat sortu behar dugu Twitterren, aplikazioen kudeatzailearen web orria erabiliz: https://apps.twitter.com/.

!!!10.2 irudia twtter apia sortzen

Behin aplikazioa sortu dugula, “Keys and Access Tokens” fitxan kautotzerako beharrezkoak diren kodeak lortuko ditugu. Segurtasunaren izenean, Consumer Secret kodea ez da publiko egin behar, baina hemen aurkezten ditugun programak probatzea errazteko asmoz, beharrezko kode guztiak eskainiko ditugu programaren kodean bertan.

Aurretik esan bezala, tweepy-k Twitterren APIra sarbidea eskaintzen du. API horren inguruan dokumentazio zabala dago, oso ondo azaldua dagoena (adibidez hemen: https://dev.twitter.com/overview/api). Oinarrian lau objektu ditu: Tweets (txioak), Users (erabiltzaileak), Entities (entitateak) eta Places (tokiak). Horietako objekturen bat atzituta, horren informazioa JSON formatuan jasotzen da, eta 8. kapituluan ikusi dugun bezala, JSON formatuarekin lan egitea oso erraza da Pythonen, eta are errazagoa tweepy erabilita.

Ariketa honetan, parametro gisa jasotzen den traola (hashtag ingelesez) baten jarraipena egiteko programatxoa idatziko dugu.

Txioak zuzenean (streaming) jarraitzeko tweepyn StreamListener objektuaren instantzia bat sortu behar da, eta bereziki on_status metodoa birdefinitu beharra dago objektuei orientatutako programazioa erabiliz, interesatzen zaigun jokabidea izan dezan. Kasu honetan, txioaren testua eta bertan aipatutako traola guztiak inprimatu nahi ditugu.

Erroreen aurrean inprimatuko duen mezua birdefinitzea ere komenigarria da, exekuzioan gertatzen diren akatsen berri jaso eta konponbidea bilatzen lagunduko digulako. 10.4. programan islatzen da kodea.

OHARRA: Kontuz! Hutsik utzi ditugu tokenak eta bakoitzak bere tokenak lortu beharko ditu.

import tweepy
from tweepy import StreamListener,Stream
import sys

class KorronteEntzulea(StreamListener):
    ''' Handles data received from the stream. '''
 
    def on_status(self, status):
        # Txioaren testua inprimatzen du
        print('Txioaren testua: ' + status.text)

        # Txioan aipatzen diren traola guztiak inprimatzen ditu
        for hashtag in status.entities['hashtags']:
            print('\t#', hashtag['text'])

        print()
        return True
 
    def on_error(self, status_code):
        print('Erroreren bat. Kodea: ' + str(status_code))
        return True # entzuten jarraitzeko
 
    def on_timeout(self):
        print('Denbora gehiegi...')
        return True # entzuten jarraitzeko
 
entzulea = KorronteEntzulea()
consumer_key = ""
consumer_secret = ""
access_token = ""
access_token_secret = ""

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

korrontea = Stream(auth, entzulea)
korrontea.filter(track=['#Python'])

Kodean ikus dezakegunez, KorronteEntzulea klasea definitzen dugu StreamListener objektuaren instantzia gisa.

Ondoren programa exekutatzeko komandoa eta bi txiori dagokien irteera ikus daiteke. Adibidean jarraitzen den traola python da, baina beste bat zehatz dezakezu. Gogoratu txio bakoitzeko testua eta traolen zerrenda inprimatzen direla eta zuzenean ari garela entzuten, beraz tarte batez itxoin beharko duzu irteeran zerbait lortzeko. Programaren bukaera eragiteko Ctrl-c erabili behar da.

Txioaren testua: RT @PythonWeekly: Building a QA System with BERT on Wikipedia via @FastForwardLabs https:// t.co/D91AzmEiTe #Python #PyTorch #Wikipedia http…

   # Python
   # PyTorch
   # Wikipedia

Txioaren testua: #programming #programmer #DevOps #webdevelopment #appdevelopment #100DaysOfCode #Java #Python #javascript #NodeJS… https:// t.co/Ue0qny8zA3

   # programming
   # programmer
   # DevOps
   # webdevelopment
   # appdevelopment
   # 100DaysOfCode
   # Java
   # Python
   # javascript
   # NodeJS

...

10.6. PROPOSATUTAKO ARIKETAK

[aldatu]

1) 10.1. programaren kodea findu behar duzu, buletaren barruan dauden baina berrietara estekarik ez duten izenburuak kentzeko (hizkuntzak, adibidez). Horretaz gain, “Europe headlines” izenburupean dauden titularrak gehi ditzakezu.

2) 10.3. ariketa sinpleagoa litzateke beste liburutegiren batekin egin izan bagenu. Proba itzazu HTML.py (http://www.decalage.info/en/python/html) eta prettytable (https://code.google.com/archive/p/prettytable/) moduluak ariketa bera egiteko.

3) 10.4. ariketan informazio gehiago gehitu behar duzu, status objektuaren entities atribututik jasoz, hala nola aipatzen diren erabiltzaileak edota estekak. Horrez gain, eman begirada bat status elementuari zenbateko informazioa duen ikusteko eta erabili informazio horietako bat.