bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


webscraping_apache

Diferències

Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.

Enllaç a la visualització de la comparació

Ambdós costats versió prèvia Revisió prèvia
Següent revisió
Revisió prèvia
webscraping_apache [2022/07/05 18:09]
josefina_llaberia
webscraping_apache [2022/08/01 07:05] (actual)
lidia_alos [Eines de scraping per a Python]
Línia 28: Línia 28:
   import requests   import requests
   from lxml import html   from lxml import html
 +  
   try:   try:
     url = "https://agora.xtec.cat/iesesteveterradas/general/the-ieti-show-conquereix-terrassa"     url = "https://agora.xtec.cat/iesesteveterradas/general/the-ieti-show-conquereix-terrassa"
     response = requests.get(url)     response = requests.get(url)
     parsed_body = html.fromstring(response.text)     parsed_body = html.fromstring(response.text)
 +    
     # Usem una expressió xpath per a trobar els tags d'imatges     # Usem una expressió xpath per a trobar els tags d'imatges
     images_src = parsed_body.xpath("//img/@src")     images_src = parsed_body.xpath("//img/@src")
     num_images = len(images_src)     num_images = len(images_src)
     print("Trobade(s) " + str(num_images) + " imatge(s)")     print("Trobade(s) " + str(num_images) + " imatge(s)")
 +    
     # Creem un directori per anar guardant les imatges     # Creem un directori per anar guardant les imatges
     nom_domini = url.replace("https://", "").replace("http://", "").split("/")[0]     nom_domini = url.replace("https://", "").replace("http://", "").split("/")[0]
Línia 42: Línia 45:
     print("Guardant imatges al directori " + nom_directori)     print("Guardant imatges al directori " + nom_directori)
     os.system("mkdir " + nom_directori)     os.system("mkdir " + nom_directori)
 +    
     for image in images_src:     for image in images_src:
         download = False         download = False
Línia 58: Línia 62:
             image_file.write(downloaded_image.content)             image_file.write(downloaded_image.content)
             image_file.close()             image_file.close()
 +            
   except Exception as e:   except Exception as e:
     print(e)     print(e)
Línia 79: Línia 84:
 <WRAP todo> <WRAP todo>
 Exercici: Exercici:
 +
 Adapta l’ script per a obtenir tots els enllaços / links (tag <a>) que hi ha en una plana web a partir de la seva url i els guardi en un fitxer o els imprimeixi per pantalla. Adapta l’ script per a obtenir tots els enllaços / links (tag <a>) que hi ha en una plana web a partir de la seva url i els guardi en un fitxer o els imprimeixi per pantalla.
 </WRAP> </WRAP>
Línia 84: Línia 90:
 \\ \\
  
-===== Títol 3 =====+===== Obtenir informació d’imatges =====
  
-**Tem** és ...+Amb les imatges baixades, mirarem si tenen informacio **EXIF** i l’extraurem. 
 + 
 +L’**EXIF** és un estàndard que defineix informació específica relacionada amb una imatge capturada per una càmera digital. 
 + 
 +Primer, haurem d’instal·lar la llibreria Pillow de Python pel tractament d’imatges. 
 + 
 +Comandes: 
 +  $ pip install pillow 
 +   
 +  Collecting pillow 
 +  Downloading Pillow-9.2.0-cp310-cp310-win_amd64.whl (3.3 MB) 
 +     ---------------------------------------- 3.3/3.3 MB 13.1 MB/s eta 0:00:00 
 +  Installing collected packages: pillow 
 +  Successfully installed pillow-9.2.0 
 + 
 +Script: 
 +  from PIL import Image 
 +  from PIL import ExifTags 
 +   
 +  image = Image.open("C:/imatges_agora_xtec_cat/013-Premi-03B-rc-1024x682.jpg"
 +   
 +  exif_info = image._getexif() 
 +   
 +  for tag, value in exif_info.items(): 
 +    decoded = ExifTags.TAGS.get(tag, tag) 
 +    print(str(decoded) + ": " + str(value)) 
 + 
 +Sortida: 
 +  ImageWidth: 6720 
 +  ImageLength: 4480 
 +  BitsPerSample: (8, 8, 8) 
 +  PhotometricInterpretation:
 +  ResolutionUnit:
 +  ExifOffset: 288 
 +  Make: Canon 
 +  Model: Canon EOS 5D Mark IV 
 +  Software: Adobe Photoshop CC 2018 (Macintosh) 
 +  Orientation:
 +  DateTime: 2022:06:22 11:18:01 
 +  SamplesPerPixel:
 +  XResolution: 300.0 
 +  YResolution: 300.0 
 +  ExifVersion: b'0231' 
 +  ShutterSpeedValue: 11.643856 
 +  ApertureValue: 4.33985 
 +  DateTimeOriginal: 2022:06:21 18:11:54 
 +  DateTimeDigitized: 2022:06:21 18:11:54 
 +  ExposureBiasValue: 0.3333333333333333 
 +  MaxApertureValue: 4.0 
 +  MeteringMode:
 +  ColorSpace: 65535 
 +  Flash: 16 
 +  FocalLength: 73.0 
 +  ExifImageWidth: 1772 
 +  ExifImageHeight: 1181 
 +  SceneCaptureType:
 +  FocalPlaneXResolution: 1866.6666564941406 
 +  FocalPlaneYResolution: 1866.6666564941406 
 +  OffsetTime: +02:00 
 +  OffsetTimeOriginal: +00:00 
 +  OffsetTimeDigitized: +00:00 
 +  SubsecTimeOriginal: 03 
 +  SubsecTimeDigitized: 03 
 +  FocalPlaneResolutionUnit:
 +  ExposureTime: 0.0003125 
 +  FNumber: 4.5 
 +  ExposureProgram:
 +  CustomRendered:
 +  ISOSpeedRatings: 5000 
 +  ExposureMode:
 +  SensitivityType:
 +  WhiteBalance:
 +  RecommendedExposureIndex: 5000 
 +  BodySerialNumber: 013021004861 
 +  LensSpecification: (70.0, 200.0, nan, nan) 
 +  LensModel: EF70-200mm f/4L USM 
 +  LensSerialNumber: 0000000000 
 + 
 +Aquest script és capaç d’obtenir les dades EXIF que hi ha en una foto, així, podem saber la data en que es va fer la foto, la càmara usada, i fins i tot, dades d’ubicació GPS si el dispositiu des de el qual es va fer té aquesta opció. 
 + 
 +<WRAP todo> 
 +Exercici: 
 + 
 +Investiga les dades de més interès que pot aportar la informació EXIF d’una foto penjada a una web. 
 +</WRAP> 
 + 
 +<WRAP todo> 
 +Exercici: 
 + 
 +Adapta l’ script per a obtenir la info EXIF de totes imatges que hi hagi en un directori. 
 +</WRAP>
  
 \\ \\
 +
 +===== Informació de la construcció d’una web =====
 +
 +Una altra informació d’interès que podem capturar d’una web són les capçaleres http i les respostes a errors típics per a saber quins serveis, versions i sistemes operatius hi ha corrent en un servidor.
 +
 +A continuació, mostrem un exemple de con usar la **llibreria builtWith de python** per a l’obtenció d’informació de les eines que hi ha darrera una web.
 +
 +Instal·lem la llibreria amb les comandes corresponents.
 +
 +Comandes:
 +  $ pip install builtWith
 +  
 +  Collecting builtWith
 +    Downloading builtwith-1.3.4.tar.gz (34 kB)
 +    Preparing metadata (setup.py) ... done
 +  Collecting six
 +    Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
 +  Using legacy 'setup.py install' for builtWith, since package 'wheel' is not installed.
 +  Installing collected packages: six, builtWith
 +    Running setup.py install for builtWith ... done
 +  Successfully installed builtWith-1.3.4 six-1.16.0
 +
 +Script:
 +  >>> import builtwith
 +  >>> builtwith.parse('http://bytes.cat/')
 +
 +Sortida:
 +  {'cdn': ['CloudFlare'], 'wikis': ['DokuWiki'], 'programming-languages': ['PHP']}
 +
 +Provem més pàgines:
 +  >>> builtwith.parse('https://agora.xtec.cat/iesesteveterradas/')
 +  
 +  {'web-servers': ['Apache'], 'font-scripts': ['Font Awesome', 'Google Font API'], 'widgets': ['Lockerz Share'], 'javascript-frameworks': ['Modernizr', 'Moment.js', 'Prototype', 'React', 'jQuery'], 'web-frameworks': ['Twitter Bootstrap', 'ZURB Foundation'], 'cms': ['WordPress'], 'programming-languages': ['PHP'], 'blogs': ['PHP', 'WordPress'], 'video-players': ['YouTube']}
 +  
 +  >>> builtwith.parse('https://institutpoblenou.cat/')
 +  
 +  {'web-servers': ['Nginx'], 'font-scripts': ['Google Font API'], 'tag-managers': ['Google Tag Manager'], 'analytics': ['TrackJs'], 'web-frameworks': ['Twitter Bootstrap'], 'ecommerce': ['WooCommerce'], 'cms': ['WordPress'], 'programming-languages': ['PHP'], 'blogs': ['PHP', 'WordPress'], 'marketing-automation': ['Yoast SEO'], 'video-players': ['YouTube'], 'javascript-frameworks': ['jQuery']}
 +  
 +  >>> builtwith.parse('https://virtual.ecaib.org/')
 +  
 +  {'lms': ['Moodle'], 'programming-languages': ['PHP'], 'web-servers': ['Nginx'], 'font-scripts': ['Font Awesome', 'Google Font API'], 'javascript-graphics': ['MathJax'], 'javascript-frameworks': ['RequireJS', 'jQuery'], 'video-players': ['YouTube']}
 +
 +\\
 +
 +===== Ocultar la informació de capçaleres http d’Apache web server =====
 +
 +Instal·lem una servidor apache en una màquina virtual amb Ubuntu Linux.
 +
 +Comandes:
 +  $ sudo apt install apache2
 +
 +Una vegada instal·lat, podem provar les capçaleres que envia per defecte, amb una comanda  des d’un terminal del propi servidor.
 +
 +Comanda:
 +  $ curl -I localhost
 +  
 +  HTTP/1.1 200 OK
 +  Date: Tue, 05 Jul 2022 16:54:48 GMT
 +  Server: Apache/2.4.41 (Ubuntu)
 +  Last-Modified: Tue, 05 Jul 2022 00:03:02 GMT
 +  ETag: "2aa6-5e30393856701"
 +  Accept-Ranges: bytes
 +  Content-Length: 10918
 +  Vary: Accept-Encoding
 +  Content-Type: text/html
 +
 +Veiem que dona informació de la versió d’apache instal·lada i del sistema operatiu.
 +
 +Aquesta informació també la donarà en una configuració per defecte en escriure una url del servidor que faci referència a una pàgina que no existeix.
 +
 +{{::apache_info_1.png?400|}}
 +
 +Per a configurar que no es mostri aquesta informació, hem de modificar la configuració.
 +
 +Comandes:
 +  $ sudo nano /etc/apache2/conf-available/security.conf
 +
 +Actualitzar els valors a:
 +  ServerTokens Prod
 +  ServerSignature Off
 +
 +Reiniciar el servei apache:
 +  sudo systemctl restart apache2
 +
 +I provem la informació que retorna després d’aquest canvi de configuració.
 +
 +Comanda:
 +  $ curl -I localhost
 +  
 +  HTTP/1.1 200 OK
 +  Date: Tue, 05 Jul 2022 17:05:39 GMT
 +  Server: Apache
 +  Last-Modified: Tue, 05 Jul 2022 00:03:02 GMT
 +  ETag: "2aa6-5e30393856701"
 +  Accept-Ranges: bytes
 +  Content-Length: 10918
 +  Vary: Accept-Encoding
 +  Content-Type: text/html
 +
 +Mirem la informació que retorna ara amb una url d’una pàgina que no existeix:
 +
 +{{::apache_info_2.png?400|}}
 +
 +<WRAP todo>
 +Exercici:
 +
 +Busca les diferents opcions per a la configuracio de ServerSignature i de ServerTokens.
 +</WRAP>
 +
 +Solució:
 +  ServerSignature – appears at the bottom of server generated pages such as error pages,
 +  directory listings, etc.
 +  It takes On/Off/EMail values, where EMail shows a “mailto:” reference to Site
 +  Admin’s email.
 +
 +  ServerTokens options - 
 +  
 +  ServerTokens Full (or not specified)
 +  Response to clients: Server: Apache/2.4.2 (Unix) PHP/4.2.2 MyMod/1.2
 +  
 +  ServerTokens Prod[uctOnly]
 +  Response to clients: Server: Apache
 +  
 +  ServerTokens Major
 +  Response to clients: Server: Apache/2
 +  
 +  ServerTokens Minor
 +  Response to clients: Server: Apache/2.4
 +  
 +  ServerTokens Min[imal]
 +  Response to clients: Server: Apache/2.4.2
 +  
 +  ServerTokens OS
 +  Response to clients: Server: Apache/2.4.2 (Unix)
 +
 +\\
 +
 +===== Limitacions tècniques del web scraping =====
 +
 +Per als operadors de les pàgines web sol ser **avantatjós limitar les possibilitats de scraping automàtic en el seu contingut en línia**. D'una banda, perquè l'accés massiu a la web que fan els scrapers pot perjudicar el rendiment del lloc i, de l'altra, perquè hi sol haver seccions internes de la web que no s'haurien de mostrar als resultats de cerca.
 +
 +Per limitar l'accés als scrapers, s'ha estès l'ús de [[https://www.ionos.es/digitalguide/hosting/cuestiones-tecnicas/gestiona-la-indexacion-de-tu-sitio-con-robotstxt/|robots.txt]] estàndard. Es tracta d'un fitxer de text que els operadors web ubiquen al directori principal de la pàgina web. Hi ha entrades especials que estableixen **quins scrapers o bots estan autoritzats a accedir a quines àrees de la web**. Les entrades del fitxer robots.txt sempre s'apliquen a un domini sencer.
 +
 +A continuació, mostrem un exemple del contingut d'un fitxer robots.txt que prohibeix l'scraping mitjançant qualsevol tipus de bot a tot el lloc:
 +
 +Comandes:
 +  # Qualsevol bot
 +  User-agent: *
 +  # Excloure tot el directori principal
 +  Disallow: /
 +
 +
 +El fitxer robots.txt només actua com a mesura de seguretat ja que convida a una limitació voluntària per part dels bots, que s'haurien d'adherir a les prohibicions del fitxer. A nivell tècnic, però, no suposa cap obstacle. Per això, **per controlar de manera efectiva l'accés mitjançant web scrapers, els operadors web implementen també tècniques més agressives**. Una és, per exemple, limitar-ne el rendiment; una altra és bloquejar l'adreça IP de l'scraper després de diversos intents d'accés que infringeixin les normes de la web.
 +
 +===== Les API com a alternativa al web scraping =====
 +
 +Tot i la seva efectivitat, el web scraping no és el millor mètode per obtenir dades de pàgines web. De fet, sovint hi ha una alternativa millor: molts operadors web posen publiquen les dades de forma estructurada i en un format llegible per a les màquines. Per accedir a aquest tipus de dades es fan servir interfícies de programació especials anomenades [[https://www.ionos.es/digitalguide/paginas-web/desarrollo-web/application-programming-interface-api/|Application Programming Interfaces]] (interfícies de programació d'aplicacions, API per les sigles en anglès).
 +
 +L'ús d'una API ofereix avantatges importants:
 +
 +  * **El propietari de la web crea l'API precisament per permetre accedir a les dades**. D'aquesta manera, es redueix el risc d'infraccions i l'operador web pot regular millor l'accés a les dades. Una manera de fer-ho és, per exemple, sol·licitant una clau API per accedir-hi. Aquest mètode també permet a l'operador regular de manera més precisa les limitacions del rendiment.
 +  * **L'API presenta dades directament en un format llegible per a les màquines**. Amb això, ja no cal la tasca laboriosa d'extreure les dades del text font. A més, l'estructura de les dades se separa de la representació visual, per la qual cosa es manté sense importar si canvia el disseny de la web.
 +
 +Sempre que hi hagi una API disponible i que ofereixi dades completes, aquest serà **el millor mètode per accedir a la informació**, sense oblidar que mitjançant el web scraping es poden extreure, en principi, tots els textos que una persona podria llegir en una pàgina web.
 +
 +===== Eines de scraping per a Python =====
 +
 +L'ecosistema Python inclou diverses eines consolidades per realitzar projectes de scraping:
 +  * Scrapy
 +  * Selenium
 +  * BeautifulSoup
 +
 +A continuació, us presentem els avantatges i inconvenients de cadascuna d'aquestes tecnologies.
 +
 +**Web scraping amb Scrapy**
 +
 +Scrapy, una de les eines per fer web scraping amb Python que presentem, utilitza un analitzador sintàctic o **parser HTML** per extreure dades del text font (en HTML) de la web seguint aquest esquema:
 +
 +  URL → Solicitud HTTP → HTML → Scrapy
 +  
 +El concepte clau del desenvolupament de scrapers amb Scrapy són els anomenats web spiders, programes de scraping senzills i basats en Scrapy. **Cada spider (aranya) està programat per scrapejar una web concreta** i es va despenjant de pàgina a pàgina. La programació utilitzada està orientada a objectes: cada spider és una classe de Python pròpia.
 +
 +A més del paquet de Python en si, la instal·lació de Scrapy inclou una eina de línia d'ordres, la Scrapy Shell, que permet controlar els spiders. A més, els spiders ja creats poden emmagatzemar-se a la [[https://www.scrapinghub.com/scrapy-cloud|Scrapy Cloud]]. Des d'allà s'executen amb temps establerts. D'aquesta manera **poden scrapejar-se també llocs web complexos** sense necessitat d'utilitzar el mateix ordinador ni la pròpia connexió a Internet. Una altra manera de fer-ho és crear un servidor de web scraping propi usant el programari de codi obert [[https://scrapyd.readthedocs.io/en/stable/|Scrapyd]].
 +
 +Scrapy és una plataforma consolidada per aplicar tècniques de web scraping amb Python. La seva arquitectura està **orientada a les necessitats de projectes professionals**. Scrapy compta, per exemple, amb una canonada o pipeline integrada per processar les dades extretes. L'obertura de les pàgines a Scrapy es produeix de manera asíncrona, és a dir, amb la possibilitat de descarregar diverses pàgines simultàniament. Per això, Scrapy és una bona opció per a projectes de scraping que hagin de processar grans volums de pàgines.
 +
 +**Web scraping amb Selenium**
 +
 +El programari lliure Selenium és un //framework// per realitzar tests automatitzats de programari a aplicacions web. En principi, **va ser desenvolupat per posar a prova pàgines i apps web**, però el [[https://www.ionos.es/digitalguide/paginas-web/desarrollo-web/tutorial-de-selenium-webdriver/|WebDriver]] de Selenium també es pot fer servir amb Python per realitzar //scraping//. Si bé Selenium en si no està escrit a Python, amb aquest llenguatge de programació és possible accedir a les funcions del programari.
 +
 +A diferència de Scrapy i BeautifulSoup, Selenium no treballa amb el text font en HTML de la web en qüestió, sinó que **carrega la pàgina en un navegador sense interfície d'usuari**. El navegador interpreta llavors el codi font de la pàgina i crea, a partir d'aquest document, un [[https://www.ionos.es/digitalguide/paginas-web/desarrollo-web/presentacion-de-document-object-model-dom/|Document Object Model]] (model d'objectes de document o DOM). Aquesta interfície estandarditzada permet posar a prova les interaccions dels usuaris. D'aquesta manera s'aconsegueix, per exemple, simular clics i emplenar formularis automàticament. Els canvis a la web que resulten d'aquestes accions es reflecteixen al DOM. L'estructura del procés de web scraping amb Selenium és la següent:
 +
 +  URL → Sol·licitud HTTP → HTML → Selenium → DOM
 +
 +Com que el DOM es genera de manera dinàmica, Selenium permet **scrapejar també pàgines el contingut de les quals ha estat generat mitjançant JavaScript**. L´accés a continguts dinàmics és l´avantatge més important de Selenium. En termes pràctics, Selenium també es pot fer servir en combinació amb Scrapy o amb BeautifulSoup: Selenium proporcionaria el text font, mentre que la segona eina s'encarregaria de l'anàlisi sintàctica i l'avaluació de les dades. En aquest cas, l'esquema que se seguiria tindria aquesta manera:
 +
 +  URL → Sol·licitud HTTP → HTML → Selenium → DOM → HTML → Scrapy / BeautifulSoup
 +
 +**Web scraping amb BeautifulSoup**
 +
 +De les tres eines que presentem **per fer web scraping amb Python, BeautifulSoup és la més antiga**. Igual que en el cas de Scrapy, es tracta d'un parser o analitzador sintàctic HTML. El web scraping amb BeautifulSoup té la següent estructura:
 +
 +  URL → Sol·licitud HTTP → HTML → BeautifulSoup
 +
 +Tot i això, a diferència de Scrapy, a BeautifulSoup el desenvolupament de l'scraper no requereix una programació orientada a objectes, sinó que **l'scraper es redacta com una senzilla seqüència d'ordres o script**. Amb això, BeautifulSoup ofereix el mètode més fàcil per pescar informació de la sopa de tags a què fa honor el seu nom.
 +
 +<WRAP center round important 100%>
 +===== En resum =====
 +**Quina eina hauries de triar pel teu projecte?** En resum: escull **BeautifulSoup** si necessites un desenvolupament ràpid o si vols familiaritzar-te primer amb els conceptes de Python i de web scraping. **Scrapy**, per la seva banda, et permet realitzar complexes aplicacions de web scraping a Python si disposes dels coneixements necessaris. **Selenium** serà la teva millor opció si la teva prioritat és extreure continguts dinàmics amb Python.
 +</WRAP>
  
webscraping_apache.1657044560.txt.gz · Darrera modificació: 2022/07/05 18:09 per josefina_llaberia