3. Peticions HTTP. API REST
El protocol HTPP
Hui en dia tot el núvol d'aplicacions i la web està gestionat, entre altres pel protocol HTTP i altres serveis que permeten estar interconnectats.
HTTP (Hiper Text Transfer Protocol) es basa en senzilles operacions de sol·licitud/resposta:
- Un client estableix una connexió amb un servidor i envia un missatge amb les dades de la sol·licitud. Aquesta petició s'anomena
requesti destaquen 4 tipus de peticions: - GET, per a demanar algun recurs al servidor
- POST, per a desar algun recurs al servidor
- PUT, per a modificar algun recurs ja existent al resvidor
- DELETE, per a esborrar algun recurs
- El servidor respon amb un missatge similar, que conté l'estat de l'operació i el seu possible resultat. Aquesta resposta s'anomena
response, formada, com hem dit per: - Els possibles estat son un codi que indica el resultat de la petició. Infomració més detallada a la wikipedia
- 1XX Respostes informatives
- 2XX Peticions correctes
- 3XX Redireccions
- 4XX Errors provocats pel client
- 5XX Errors provocats dins del servidor
- El recurs sol·licitad. Habitualmente serà una pàgina web (HTML més la hipermèdia), un arxiu JSON amb dades, un arxiu PDF, etc.
Serveis API REST
Anem a definir una API REST de manera molt bàsica per a poder-ho entendre ràpidament:
- S'anomena un servei tot allò que ens pot donar un servidor. Dades, pàgines, arxius, l'hora, etc.
-
API és l'acrònim de Application Programming Interfaces i indica tot allò que ens pot oferir un servidor, així com la sintaxi que hem de fer sevir per a demana-li les coses
Dins del llenguatges de programació, la API son les llibreries que disposa i com hem de invocar a les funcions de dites llibreries.
-
Una API REST (Representational State Transfer) és un conjunt de regles i convencions arquitectòniques per dissenyar serveis web basats en el protocol HTTP. Cap destacar que REST implica:
- Fer servir HTTP, i per tant identificar la seua API mitjançant:
- Les URL on es demana la petició (ruta al servidor)
- El tipus o mètode de la petició (GET, POST, etc.)
- Que siga Stateless o sense memòria. Una petició serà atesa per ella mateixa, sense recordar res de les anteriors peticions.
- Estat Representacional: es refereix a l'estat del recurs demanat en el moment de la petició, i ve expresat en XML o actualment en JSON
- Seguretat (amb JWT) i hipermèdia (HAETOAS, amb enllaços als recursos relacionats)
Consumint recursos de internet. La llibreria request
És en aquest apartat on anem a estudiar com fer peticions a recursos de internet, mitjançant les peticions vistes anteriorment amb http. Aquestes peticinos s'engloben dins de la llibreria request. Els recursos poden ser be:
- Una pàgina web
- Una imatge o arxiu ubicat en algun lloc
- Una API rest a la que demanarem/enviarem algun recurs
El fluxe de treball serà:
- Composar la URL de destí
- Afegir a la petició arguments o paràmetres
- Llançar la petició
- Arreplegar la resposta (response)
- Avaluar el codi d'estat per saber com ha anat
- Recuperar el cos de la resposta (JSON, Arxius, HTML, etc..)
Petició bàsica amb request
Com pot observar-se:
- Es crea tot a partir del objecte
requests. Aquest mètode te tants mètodes com tipus de peticions http, encara que sols veurem les 4 bàsiques. Rep com a paràmetre la url que volem fer la petició. - Ens retorna un objecte de tipus
Response, el qual encapsula la resposta del servidor: Response.status_codeamb el codi html de com ha anat la peticióResponse.headersla capçalera en la metainformació de la resposta. Per exemple:Response.contentel contingut de la resposta, directament en bytes. Si la resposta es text, s'interpreta directament.Response.textla resposta en format text.Response.json(), quan la resposta conté un json, ens permet parsejar-la directament i guarda-la dins d'un objecte:
Descarregant una imatge de la web
A l'anterior exemple:
- La petició
get()és a un recurs gràfic. - El content es passem per la classe
BytesIOque ens permet tractar-lo com un stream de bytes, el que ens permet passar-ho a: - el mètode
open()de la classeImagede la llibreriaPIL(Python Image Library), dedicada a la manipulació d'imatges. - La imatge la podem obrir e inclòs guardar-la a un fitxer al nostre sistema.
Repte
Busca a la documentació com implementaries la descarrega d'un fitxer de qualssevol tipus, un pdf o un zip, i implementa-ho
Afegint paràmetres i recursos
De vegades (i molt sovint) voldrem enviar dades al servidor que ens aten la petició, per exemple identificar-nos, penjar un arxiu, marcar una compra a la cistella, etc. Existeixen dos maneres bàsiques de enviar eixa informació, per paràmetres o amb el cos de la petició
Enviar paràmetres
Les dades dins dels paràmetres s'envien afegint al recurs que volem les dades a enviar de la forma parametre=valor darrere d'un símbol d'interrogació (?). Cas d'haver més paràmetres, es concatenen amb l'ampersand (&). Per exemple si volem fer un login, la petició seria algo com http://www.elmeuservidor.com/login?user=pepito&password=123456.
La primera solució per a fer-ho així seria composar la url de manera artesanal:
| Python | |
|---|---|
La segona solució, recomanable. és fer servir eines pròpies de la llibreria per a elaborar-ho més fàcil:
| Python | |
|---|---|
Si volem afegir dades, al cos de la petició, de la mateixa manera que es fa amb postman o similar, s'ha de fer canviant la crida:
| Python | |
|---|---|
Teniu més informació disponible a la pàgina ofical https://requests.readthedocs.io/en/latest/.
Web Scraping
El web scraping, o rascat web en català, és una tècnica utilitzada per extreure informació de llocs web de manera automatitzada. En altres paraules, es tracta de processos automatitzats que naveguen per pàgines web, descarreguen el seu contingut i extreuen dades específiques d'interès. Aquestes dades poden incloure text, imatges, enllaços, preus, puntuacions i molt més, depenent de la naturalesa del lloc web i de la informació que es vulgui obtenir.
El web scraping és una eina valuosa per recopilar dades de la web quan no es disposa d'un accés directe a una API (Interfície de Programació d'Aplicacions) o quan es necessita automatitzar la recopilació d'informació. Tot i això, és important fer servir aquesta tècnica amb responsabilitat i respectar els termes d'ús dels llocs web, ja que alguns llocs poden prohibir o limitar l'ús del web scraping per tal de protegir les seves dades i continguts.
Com que necessitem descarregar contingut web, la llibreria request estudiat anteriorment casa perfectament per a descarregar els arxius HTML.
BeautifulSoup
Beautiful Soup és una biblioteca de Python que facilita l'extracció de dades de documents HTML i XML. Aquesta biblioteca proporciona eines per analitzar i "navegar" pels elements d'un document web, facilitant la tasca d'extreure informació específica. És especialment útil en conjunció amb tècniques de web scraping, ja que permet accedir als diferents components d'una pàgina web i extraure el contingut desitjat de manera més eficient.
Per a fer servir aquiesta llibreria, hem de instal·lar-la amb pip install beautifulsoup4 o mitjançant conda.
L'estrctura bàsica d'un programa de scrapping és la següent:
Obtenir la sopa
Consideracions:
- La dificultat del Scraping és el veure en quina part de la pàgina està el contingut a extreure
- Moltes pàgines tenen mecanismes d'intentar detectar bots o programes de scraping, per això és bona idea el aplicar un user agent (navegador) distint.
Canviar navegador d'orige
Això generarà alguna cosa com:
Tot i que podem trobar tota la documentació a https://www.crummy.com/software/BeautifulSoup/bs4/doc/, anem a veure els principals elements que podem trobar per a accedir a les etiquetes d'una pàgina.
Atenció
El més important és recordar:
| Text Only | |
|---|---|
1 2 3 | |
Atenció
Hem partit d'un exemple al qual ens baixem l'HTML de la pàgina web a fer scrapping, però ara tenim que tindre en consideració el següent. El que mostra el navegador no sempre és el HTML, sinò que moltes vegades aquest HTML font s'amplia amb l'execució de JAvascript
Si descarreguem amb request la pàgina web tindrem el HTML pre-javascript. i a nosaltres ens interessa el HTML post-javascript, ja que molta informació pot ser el resultat de l'execució de javascript, amb consultes a BBDD o similar
Selenuim
Selènium https://www.selenium.dev és una potent suite d'eines per a la automatització de navegadors web. Dissenyat inicialment per a testing automatitzat de pàgines web, Selenium s'ha convertit en una eina essencial per als desenvolupadors i testers que necessiten interactuar amb navegadors web mitjançant codi.
Amb Selenium, els usuaris poden escriure scripts en diversos llenguatges de programació com Python, Java, C#, entre d'altres, per a realitzar tasques automatitzades a través de l'interfície gràfica d'un navegador web. Això inclou clicar en enllaços, emplenar formularis, navegar entre pàgines i molt més.
Selenium suporta diversos navegadors com Chrome, Firefox, Safari i Edge, el que fa que sigui una eina versàtil per a la creació de proves automatitzades o per a la realització de tasques repetitives en l'entorn web.
A més de la seva utilització en testing, Selenium també és àmpliament utilitzat en web scraping, monitoratge de pàgines web, i altres tasques d'automatització relacionades amb la interacció amb navegadors. La seva naturalesa flexible i la capacitat de controlar navegadors en temps real fan de Selenium una eina imprescindible per als desenvolupadors i professionals del control de qualitat que treballen amb aplicacions web.
Per fer la instal·lació de selenium conda install -c conda-forge selenium.
Si recordes hem arribat ací perquè volem la versió definitiva del HTML (post javascript). Llavors no ens queda altra que navegar per aquella pàgina que volem scrapejar, i Selenium ens permet emular dita navegació.
Selecció del navegador
Aquest codi ens permet seleccionar un navegador distint (o no) cada cop que el demanem. Això és adequat per a evitar mecanismes anti-scrapping. També podrien ser canviar les IP d'orige, per a semblar consexions de llocs distints.
Un cop sel·leccionat el navegador, simplement deurem d'alçar la instància del mateix, dir-li la pàgina on volem a nar i revisar-la tota (anant de dalt a baix...)
Navegació per la pàgina www.marca.com
BeautifulSoup
Anem a veure els mètodes més important que farem servir de la llibreria BeautifulSoup un cop recuperat l'HTML i parsejat. Partim una mica del següent DOM per a l'explicació
Observem que cada element conté:
| HTML | |
|---|---|
i podem buscar-los com segueix:
- Localitazar elements
soup.find_all('etiqueta'). Retorna tots els elements del tipus d'etiqueta indicat. Per exemplesoup.find_all('li')tornarà tots els elements de la llista. -
Localitazar elements d'una classe:
-
soup.find_all('etiqueta',class_='classe'). Torna els elements de les etiquetes indicades d'una certa classe soup.find_all(class_='classe'). Torna els elements indicades d'una certa classe, podent ser de distint tipus d'etiqueta- Localitzar un element identificat
soup.find_all('etiqueta',id='identificacor')
Atenció
Tenir en compte:
- Els mètodes
find_all()retornent un conjunt d'elements (buit o no) - Els mètode
findretorna:- None si no troba res (no existeix)
- Un element, quan per exemple busquem per identificador, i el troba
- El primer element en cas de trobar-ne diversos.
Espai a les búsquede
Tenir en compte que els mètodes find i find_all() efectuen la búsqueda a l'interior del element des del qual busquem:
soup.find_all('li')retornarà tots els elements que hi han al document, ja que busquem desde l'inici del DOMelement.find_all('div')buscarà sols dins de cada element.
Un cop ja tenim localitzat un element podem accedir, des d'ell a tot el següent. Suposem que el tenim referenciat amb la variable elem:
- Tipus d'element o tag →
elem.name - Accedir a característiques o atributs d'ell → Una etiqueta pot tenir un llistat d'atributs o característiques. Podem accedir a ells com si d'un diccionari es tratara
elem[atribut]:
| Python | |
|---|---|
També podem recuperar-los tots amb elem.attrs:
Accedir al contingut com a text
El contingut textual, per entendre-ho, ha de diferenciar-se que podem diferenciar entre els següents tipus d'elements:
- Elements que contenen sols una línea de text
XML -
Elements que contenen altres elements:
Tenim diverses opcions per a recuperar contingut: -
elem.text→ retorna un string amb tot el contingut textual. Apareixeran els bots de linia si els elements d'on extraguem el text estan en linies diferents, inclòs sagnats. Segons els tipus anteriors tindriem:Contingut textualo be
'\n Peu de la pàgina\n This is span 1\nThis is span 2\nThis is span 2\n' -
elem.strings→ Retorna un llistat (array) amb els elements textuals, incloses bots de linia i blancs. Segons els tipus anteriors tindriem:['Contingut textual']o be
['\n This is the footer\n ', 'This is span 1', '\n', 'This is span 2', '\n', 'This is span 2', '\n'] -
elem.stripped_strings→ Retorna un llistat (array) amb els elements textuals, sense bots de linia i blancs. Segons els tipus anteriors tindriem:['Contingut textual']o be
['This is the footer','This is span 1','This is span 2','This is span 2'] -
elem.string→ retorna sols una cadena, quan l'element conté sols un únic element textual. Cas contrari (buida o més d'una) no retorna res
Navegació a partir d'un element
Exemple de scraping
Primer que res hem d'analitzar el contingut de la pàgina web. A l'exemple anem a estudiar la web whatcar.com, que fa anàlisi de cotxes. Dins de la web, podem accedir a la pestanya de reviews, i ens trobem això:
Sembla que hi ha un enllaç per a cada marca. Per veure el tipus d'element, hem de fer una tasca d'anàlisi del codi font, mitjançant les eines de desenvolupador. Llavors ens trobem que:
- Per a cada marca que s'analitza està dins d'etiquetes
<a class="FragmentReviewsMake-makeContainer-d9f354b1" ...> - Dins de cada marka hi ha un link a la pàgina de cada marca
<a href='...'>
Arreplegant els links de les marques
el resultat és un arxiu de text amb el següent contingut:
Ara, de manera recursiva hauriem d'analitzar cadascuna de les marques, vegem primer la estructura de cada marca:
i si explorem cadascuna de les targetes de cada model:
podem trobar que dins mateix tenim un link <a href="/bmw/2-series/hatchback/review/n78" ...> </a>, del qual sols ens interessa el href..
Posteriorment hauriem de veure com accedir a la pàgina de cada model i buscar els elements amb informació interessant per veure com extreure-la.