Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.
| 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 = " | url = " | ||
| 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' | # Usem una expressió xpath per a trobar els tags d' | ||
| images_src = parsed_body.xpath("// | images_src = parsed_body.xpath("// | ||
| num_images = len(images_src) | num_images = len(images_src) | ||
| print(" | print(" | ||
| + | | ||
| # Creem un directori per anar guardant les imatges | # Creem un directori per anar guardant les imatges | ||
| nom_domini = url.replace(" | nom_domini = url.replace(" | ||
| Línia 42: | Línia 45: | ||
| print(" | print(" | ||
| os.system(" | os.system(" | ||
| + | | ||
| 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. | ||
| </ | </ | ||
| Línia 84: | Línia 90: | ||
| \\ | \\ | ||
| - | ===== Títol 3 ===== | + | ===== Obtenir informació d’imatges |
| - | **Tem** és ... | + | Amb les imatges baixades, mirarem si tenen informacio |
| + | |||
| + | 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) | ||
| + | | ||
| + | Installing collected packages: pillow | ||
| + | Successfully installed pillow-9.2.0 | ||
| + | |||
| + | Script: | ||
| + | from PIL import Image | ||
| + | from PIL import ExifTags | ||
| + | |||
| + | image = Image.open(" | ||
| + | |||
| + | exif_info = image._getexif() | ||
| + | |||
| + | for tag, value in exif_info.items(): | ||
| + | decoded = ExifTags.TAGS.get(tag, | ||
| + | print(str(decoded) + ": " + str(value)) | ||
| + | |||
| + | Sortida: | ||
| + | ImageWidth: 6720 | ||
| + | ImageLength: | ||
| + | BitsPerSample: | ||
| + | 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: | ||
| + | YResolution: | ||
| + | ExifVersion: | ||
| + | ShutterSpeedValue: | ||
| + | ApertureValue: | ||
| + | DateTimeOriginal: | ||
| + | DateTimeDigitized: | ||
| + | ExposureBiasValue: | ||
| + | MaxApertureValue: | ||
| + | MeteringMode: | ||
| + | ColorSpace: 65535 | ||
| + | Flash: 16 | ||
| + | FocalLength: | ||
| + | ExifImageWidth: | ||
| + | ExifImageHeight: | ||
| + | SceneCaptureType: | ||
| + | FocalPlaneXResolution: | ||
| + | FocalPlaneYResolution: | ||
| + | OffsetTime: +02:00 | ||
| + | OffsetTimeOriginal: | ||
| + | OffsetTimeDigitized: | ||
| + | SubsecTimeOriginal: | ||
| + | SubsecTimeDigitized: | ||
| + | FocalPlaneResolutionUnit: | ||
| + | ExposureTime: | ||
| + | FNumber: 4.5 | ||
| + | ExposureProgram: | ||
| + | CustomRendered: | ||
| + | ISOSpeedRatings: | ||
| + | ExposureMode: | ||
| + | SensitivityType: | ||
| + | WhiteBalance: | ||
| + | RecommendedExposureIndex: | ||
| + | BodySerialNumber: | ||
| + | LensSpecification: | ||
| + | LensModel: EF70-200mm f/4L USM | ||
| + | LensSerialNumber: | ||
| + | |||
| + | Aquest script | ||
| + | |||
| + | <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 todo> | ||
| + | Exercici: | ||
| + | |||
| + | Adapta l’ script per a obtenir la info EXIF de totes imatges que hi hagi en un directori. | ||
| + | </ | ||
| \\ | \\ | ||
| + | |||
| + | ===== 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ó, | ||
| + | |||
| + | 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 ' | ||
| + | Installing collected packages: six, builtWith | ||
| + | Running setup.py install for builtWith ... done | ||
| + | Successfully installed builtWith-1.3.4 six-1.16.0 | ||
| + | |||
| + | Script: | ||
| + | >>> | ||
| + | >>> | ||
| + | |||
| + | Sortida: | ||
| + | {' | ||
| + | |||
| + | Provem més pàgines: | ||
| + | >>> | ||
| + | | ||
| + | {' | ||
| + | | ||
| + | >>> | ||
| + | | ||
| + | {' | ||
| + | | ||
| + | >>> | ||
| + | | ||
| + | {' | ||
| + | |||
| + | \\ | ||
| + | |||
| + | ===== 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, | ||
| + | |||
| + | Comanda: | ||
| + | $ curl -I localhost | ||
| + | | ||
| + | HTTP/1.1 200 OK | ||
| + | Date: Tue, 05 Jul 2022 16:54:48 GMT | ||
| + | Server: Apache/ | ||
| + | Last-Modified: | ||
| + | ETag: " | ||
| + | Accept-Ranges: | ||
| + | Content-Length: | ||
| + | Vary: Accept-Encoding | ||
| + | Content-Type: | ||
| + | |||
| + | 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. | ||
| + | |||
| + | {{:: | ||
| + | |||
| + | Per a configurar que no es mostri aquesta informació, | ||
| + | |||
| + | Comandes: | ||
| + | $ sudo nano / | ||
| + | |||
| + | 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: | ||
| + | ETag: " | ||
| + | Accept-Ranges: | ||
| + | Content-Length: | ||
| + | Vary: Accept-Encoding | ||
| + | Content-Type: | ||
| + | |||
| + | Mirem la informació que retorna ara amb una url d’una pàgina que no existeix: | ||
| + | |||
| + | {{:: | ||
| + | |||
| + | <WRAP todo> | ||
| + | Exercici: | ||
| + | |||
| + | Busca les diferents opcions per a la configuracio de ServerSignature i de ServerTokens. | ||
| + | </ | ||
| + | |||
| + | Solució: | ||
| + | ServerSignature – appears at the bottom of server generated pages such as error pages, | ||
| + | directory listings, etc. | ||
| + | It takes On/ | ||
| + | Admin’s email. | ||
| + | |||
| + | ServerTokens options - | ||
| + | | ||
| + | ServerTokens Full (or not specified) | ||
| + | Response to clients: Server: Apache/ | ||
| + | | ||
| + | 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/ | ||
| + | | ||
| + | ServerTokens OS | ||
| + | Response to clients: Server: Apache/ | ||
| + | |||
| + | \\ | ||
| + | |||
| + | ===== 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' | ||
| + | |||
| + | Per limitar l' | ||
| + | |||
| + | A continuació, | ||
| + | |||
| + | 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' | ||
| + | |||
| + | ===== Les API com a alternativa al web scraping ===== | ||
| + | |||
| + | Tot i la seva efectivitat, | ||
| + | |||
| + | L'ús d'una API ofereix avantatges importants: | ||
| + | |||
| + | * **El propietari de la web crea l'API precisament per permetre accedir a les dades**. D' | ||
| + | * **L' | ||
| + | |||
| + | Sempre que hi hagi una API disponible i que ofereixi dades completes, aquest serà **el millor mètode per accedir a la informació**, | ||
| + | |||
| + | ===== Eines de scraping per a Python ===== | ||
| + | |||
| + | L' | ||
| + | * Scrapy | ||
| + | * Selenium | ||
| + | * BeautifulSoup | ||
| + | |||
| + | A continuació, | ||
| + | |||
| + | **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' | ||
| + | |||
| + | 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' | ||
| + | |||
| + | **Web scraping amb Selenium** | ||
| + | |||
| + | El programari lliure Selenium és un // | ||
| + | |||
| + | A diferència de Scrapy i BeautifulSoup, | ||
| + | |||
| + | 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: | ||
| + | |||
| + | 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' | ||
| + | |||
| + | <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. | ||
| + | </ | ||