Saltar al contenido principal

Una publicación etiquetados con "scraping"

Ver Todas las Etiquetas

· 9 min de lectura
Darvin Cotrina

En esta sección vamos a ver cómo podemos extraer información de páginas web usando la librería BeautifulSoup de Python, veremos el poder de esta librería y cómo podemos usarla para extraer información de páginas web.

1. Requerimientos

Antes de empezar, debemos instalar las siguientes librerías:

pip install requests
pip install beautifulsoup4

2. Importar librerías

Como en todo codigo de Python, lo primero que debemos hacer es importar las librerías que vamos a usar, en este caso

from bs4 import BeautifulSoup
import requests

3. Obtener el contenido de una página web

BeautifulSoup no puede optener el contenido directamente desde una url, por lo que nos vamos ayudar en el módulo requests

url = 'https://peps.python.org/pep-0020/'
r = requests.get(url)
html = r.text

4. Ver el contenido de la página

BeautifulSoup nos permite ver el contenido de la página de una forma más amigable, para ello usamos el método prettify()

soup = BeautifulSoup(html, 'html')
print(soup.prettify())
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<meta content="light dark" name="color-scheme"/>
<title>
PEP 20 – The Zen of Python | peps.python.org
</title>
<link href="../_static/py.png" rel="shortcut icon"/>
<link href="https://peps.python.org/pep-0020/" rel="canonical"/>
<link href="../_static/style.css" rel="stylesheet" type="text/css"/>
<link href="../_static/mq.css" rel="stylesheet" type="text/css"/>
<link href="../_static/pygments.css" id="pyg-light" media="(prefers-color-scheme: light)" rel="stylesheet" type="text/css"/>
<link href="../_static/pygments_dark.css" id="pyg-dark" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css"/>
<link href="https://peps.python.org/peps.rss" rel="alternate" title="Latest PEPs" type="application/rss+xml"/>
<meta content="Python Enhancement Proposals (PEPs)" name="description"/>
</head>
<body>
<svg style="display: none;" xmlns="http://www.w3.org/2000/svg">
<symbol id="svg-sun-half" pointer-events="all" viewbox="0 0 24 24">
<title>
Following system colour scheme
</title>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="9">
</circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85">
</path>
</svg>
</symbol>
<symbol id="svg-moon" pointer-events="all" viewbox="0 0 24 24">
<title>
Selected dark colour scheme
</title>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none" stroke="none">
</path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z">
</path>
</svg>
</symbol>
<symbol id="svg-sun" pointer-events="all" viewbox="0 0 24 24">
<title>
Selected light colour scheme
</title>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="5">
</circle>
<line x1="12" x2="12" y1="1" y2="3">
</line>
<line x1="12" x2="12" y1="21" y2="23">
</line>
<line x1="4.22" x2="5.64" y1="4.22" y2="5.64">
</line>
<line x1="18.36" x2="19.78" y1="18.36" y2="19.78">
</line>
<line x1="1" x2="3" y1="12" y2="12">
</line>
<line x1="21" x2="23" y1="12" y2="12">
</line>
<line x1="4.22" x2="5.64" y1="19.78" y2="18.36">
</line>
<line x1="18.36" x2="19.78" y1="5.64" y2="4.22">
</line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>
Python Enhancement Proposals
</h1>
<ul class="breadcrumbs">
<li>
<a href="https://www.python.org/" title="The Python Programming Language">
Python
</a>
»
</li>
<li>
<a href="../pep-0000/">
PEP Index
</a>
»
</li>
<li>
PEP 20
</li>
</ul>
<button id="colour-scheme-cycler" onclick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto">
<use href="#svg-sun-half">
</use>
</svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark">
<use href="#svg-moon">
</use>
</svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light">
<use href="#svg-sun">
</use>
</svg>
<span class="visually-hidden">
Toggle light / dark / auto colour theme
</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">
PEP 20 – The Zen of Python
</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">
Author
<span class="colon">
:
</span>
</dt>
<dd class="field-odd">
Tim Peters &lt;tim.peters at gmail.com&gt;
</dd>
<dt class="field-even">
Status
<span class="colon">
:
</span>
</dt>
<dd class="field-even">
<abbr title="Currently valid informational guidance, or an in-use process">
Active
</abbr>
</dd>
<dt class="field-odd">
Type
<span class="colon">
:
</span>
</dt>
<dd class="field-odd">
<abbr title="Non-normative PEP containing background, guidelines or other information relevant to the Python ecosystem">
Informational
</abbr>
</dd>
<dt class="field-even">
Created
<span class="colon">
:
</span>
</dt>
<dd class="field-even">
19-Aug-2004
</dd>
<dt class="field-odd">
Post-History
<span class="colon">
:
</span>
</dt>
<dd class="field-odd">
22-Aug-2004
</dd>
</dl>
<hr class="docutils"/>
<section id="contents">
<details>
<summary>
Table of Contents
</summary>
<ul class="simple">
<li>
<a class="reference internal" href="#abstract">
Abstract
</a>
</li>
<li>
<a class="reference internal" href="#the-zen-of-python">
The Zen of Python
</a>
</li>
<li>
<a class="reference internal" href="#easter-egg">
Easter Egg
</a>
</li>
<li>
<a class="reference internal" href="#references">
References
</a>
</li>
<li>
<a class="reference internal" href="#copyright">
Copyright
</a>
</li>
</ul>
</details>
</section>
<section id="abstract">
<h2>
<a class="toc-backref" href="#abstract" role="doc-backlink">
Abstract
</a>
</h2>
<p>
Long time Pythoneer Tim Peters succinctly channels the BDFL’s guiding
principles for Python’s design into 20 aphorisms, only 19 of which
have been written down.
</p>
</section>
<section id="the-zen-of-python">
<h2>
<a class="toc-backref" href="#the-zen-of-python" role="doc-backlink">
The Zen of Python
</a>
</h2>
<div class="highlight-text notranslate">
<div class="highlight">
<pre><span></span>Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
</pre>
</div>
</div>
</section>
<section id="easter-egg">
<h2>
<a class="toc-backref" href="#easter-egg" role="doc-backlink">
Easter Egg
</a>
</h2>
<div class="highlight-pycon notranslate">
<div class="highlight">
<pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">this</span>
</pre>
</div>
</div>
</section>
<section id="references">
<h2>
<a class="toc-backref" href="#references" role="doc-backlink">
References
</a>
</h2>
<p>
Originally posted to
<a class="reference external" href="mailto:comp.lang.python/python-list%40python.org">
comp
<span>
.
</span>
lang
<span>
.
</span>
python/python-list
<span>
@
</span>
python
<span>
.
</span>
org
</a>
under a
thread called
<a class="reference external" href="https://groups.google.com/d/msg/comp.lang.python/B_VxeTBClM0/L8W9KlsiriUJ">
“The Way of Python”
</a>
</p>
</section>
<section id="copyright">
<h2>
<a class="toc-backref" href="#copyright" role="doc-backlink">
Copyright
</a>
</h2>
<p>
This document has been placed in the public domain.
</p>
</section>
</section>
<hr class="docutils"/>
<p>
Source:
<a class="reference external" href="https://github.com/python/peps/blob/main/pep-0020.txt">
https://github.com/python/peps/blob/main/pep-0020.txt
</a>
</p>
<p>
Last modified:
<a class="reference external" href="https://github.com/python/peps/commits/main/pep-0020.txt">
2022-03-15 17:40:34+00:00 GMT
</a>
</p>
</article>
<nav id="pep-sidebar">
<h2>
Contents
</h2>
<ul>
<li>
<a class="reference internal" href="#abstract">
Abstract
</a>
</li>
<li>
<a class="reference internal" href="#the-zen-of-python">
The Zen of Python
</a>
</li>
<li>
<a class="reference internal" href="#easter-egg">
Easter Egg
</a>
</li>
<li>
<a class="reference internal" href="#references">
References
</a>
</li>
<li>
<a class="reference internal" href="#copyright">
Copyright
</a>
</li>
</ul>
<br/>
<a href="https://github.com/python/peps/blob/main/pep-0020.txt" id="source">
Page Source (GitHub)
</a>
</nav>
</section>
<script src="../_static/colour_scheme.js">
</script>
<script src="../_static/wrap_tables.js">
</script>
<script src="../_static/sticky_banner.js">
</script>
</body>
</html>

Una vez que tenemos el contenido de la página, podemos navegar por el contenido usando los métodos find() y find_all().

a = soup.find_all('a')
for link in a:
print(link.get('href'))
https://www.python.org/
../pep-0000/
#abstract
#the-zen-of-python
#easter-egg
#references
#copyright
#abstract
#the-zen-of-python
#easter-egg
#references
mailto:comp.lang.python/python-list%40python.org
https://groups.google.com/d/msg/comp.lang.python/B_VxeTBClM0/L8W9KlsiriUJ
#copyright
https://github.com/python/peps/blob/main/pep-0020.txt
https://github.com/python/peps/commits/main/pep-0020.txt
#abstract
#the-zen-of-python
#easter-egg
#references
#copyright
https://github.com/python/peps/blob/main/pep-0020.txt

Para navegar por el contenido del documento, BeautifulSoup tiene varios métodos que nos permiten navegar por el contenido del documento, los más usados son:

  • find(): Nos permite encontrar el primer elemento que cumpla con las condiciones especificadas.
  • find_all(): Nos permite encontrar todos los elementos que cumplan con las condiciones especificadas.
  • select(): Nos permite encontrar todos los elementos que cumplan con las condiciones especificadas usando selectores CSS.
  • select_one(): Nos permite encontrar el primer elemento que cumpla con las condiciones especificadas usando selectores CSS.
  • find_parent(): Nos permite encontrar el elemento padre que cumpla con las condiciones especificadas.
  • find_parents(): Nos permite encontrar todos los elementos padres que cumplan con las condiciones especificadas.

Entre otros, para mas información ir a la documentación

# buscar elementos a por class
elements = soup.find_all('a', {'class': 'reference internal'})
for element in elements:
print(element.get('href'))
#abstract
#the-zen-of-python
#easter-egg
#references
#copyright
#abstract
#the-zen-of-python
#easter-egg
#references
#copyright
# buscar elementos por id
elements = soup.find_all(id = 'copyright')
print(elements)
[<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>]
# buscar elementos por texto
elements = soup.find_all(string='PEP 20')
elements
[]
# buscar elementos por texto con expresiones regulares
import re
elements = soup.find_all(re.compile('^sy'))
elements
[<symbol id="svg-sun-half" pointer-events="all" viewbox="0 0 24 24">
<title>Following system colour scheme</title>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>,
<symbol id="svg-moon" pointer-events="all" viewbox="0 0 24 24">
<title>Selected dark colour scheme</title>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none" stroke="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>,
<symbol id="svg-sun" pointer-events="all" viewbox="0 0 24 24">
<title>Selected light colour scheme</title>
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" x2="12" y1="1" y2="3"></line>
<line x1="12" x2="12" y1="21" y2="23"></line>
<line x1="4.22" x2="5.64" y1="4.22" y2="5.64"></line>
<line x1="18.36" x2="19.78" y1="18.36" y2="19.78"></line>
<line x1="1" x2="3" y1="12" y2="12"></line>
<line x1="21" x2="23" y1="12" y2="12"></line>
<line x1="4.22" x2="5.64" y1="19.78" y2="18.36"></line>
<line x1="18.36" x2="19.78" y1="5.64" y2="4.22"></line>
</svg>
</symbol>]

6. Conclusiones

Como hemos visto, BeautifulSoup es una librería muy poderosa que nos permite extraer información de páginas web de una forma rapida y sencilla, pero tiene sus limitaciones y no es la mejor opción para extraer información de páginas web complejas, para ello existen otras librerías como Scrapy que nos permiten extraer información de páginas web de una forma más eficiente.

Cuando hagamos scraping de páginas web, debes de tener en cuenta que tienes que respetar las políticas de privacidad de la página web, para ello debes de leer los términos y condiciones de la página web, asi como el acceso a los robots de búsqueda, del archivo robots.txt de la página web.