From 09334755d84debde8d574905d5e8906e586b5e0b Mon Sep 17 00:00:00 2001 From: Carlos Romero Date: Tue, 9 Jan 2024 11:53:27 +0100 Subject: Added Spanish translation of the doc --- doc.es/Makefile | 130 ++ doc.es/source/6.1.jpg | Bin 0 -> 22619 bytes doc.es/source/conf.py | 256 ++++ doc.es/source/index.rst | 3709 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 4095 insertions(+) create mode 100644 doc.es/Makefile create mode 100644 doc.es/source/6.1.jpg create mode 100644 doc.es/source/conf.py create mode 100644 doc.es/source/index.rst diff --git a/doc.es/Makefile b/doc.es/Makefile new file mode 100644 index 0000000..8c833d2 --- /dev/null +++ b/doc.es/Makefile @@ -0,0 +1,130 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/BeautifulSoup.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/BeautifulSoup.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/BeautifulSoup" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/BeautifulSoup" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/doc.es/source/6.1.jpg b/doc.es/source/6.1.jpg new file mode 100644 index 0000000..97014f0 Binary files /dev/null and b/doc.es/source/6.1.jpg differ diff --git a/doc.es/source/conf.py b/doc.es/source/conf.py new file mode 100644 index 0000000..42fcf6d --- /dev/null +++ b/doc.es/source/conf.py @@ -0,0 +1,256 @@ +# -*- coding: utf-8 -*- +# +# Beautiful Soup documentation build configuration file, created by +# sphinx-quickstart on Thu Jan 26 11:22:55 2012. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Beautiful Soup' +copyright = u'2004-2024, Leonard Richardson' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '4' +# The full version, including alpha/beta/rc tags. +release = '4.12.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +language = "es" + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'BeautifulSoupdoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'BeautifulSoup.tex', u'Beautiful Soup Documentation', + u'Leonard Richardson', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'beautifulsoup', u'Beautiful Soup Documentation', + [u'Leonard Richardson'], 1) +] + + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'Beautiful Soup' +epub_author = u'Leonard Richardson' +epub_publisher = u'Leonard Richardson' +epub_copyright = u'2012, Leonard Richardson' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +#epub_exclude_files = [] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True diff --git a/doc.es/source/index.rst b/doc.es/source/index.rst new file mode 100644 index 0000000..53c47f5 --- /dev/null +++ b/doc.es/source/index.rst @@ -0,0 +1,3709 @@ +.. _manual: + +================================= + Documentación de Beautiful Soup +================================= + +.. py:module:: bs4 + +.. image:: 6.1.jpg + :align: right + :alt: "El lacayo-pez empezó por sacarse de debajo del brazo una gran carta, + casi tan grande como él." + +`Beautiful Soup `_ es una +librería de Python para extraer datos de archivos en formato HTML y XML. +Trabaja con tu analizador favorito para ofrecer maneras bien definidas +de navegar, buscar y modificar el árbol analizado. Puede llegar a ahorrar +horas o días de trabajo a los programadores. + +Este manual ilustra con ejemplos la funcionalidades más importantes +de Beautiful Soup 4. Te muestro las cosas para las que la librería es buena, +cómo funciona, cómo usarla, cómo hacer lo que quieres y qué hacer cuando +no se cumplen tus expectativas. + +Este documento cubre Beautiful Soup versión 4.12.1. Los ejemplos en este +documento fueron escritos para Python 3.8. + +Podrías estar buscando la documentación de `Beautiful Soup 3 +`_. +Si es así, debes saber que Beautiful Soup 3 ya no se desarrolla y +su soporte fue abandonado el 31 de diciembre de 2020. Si quieres +conocer la diferencias entre Beautiful Soup 3 y Beautiful Soup 4, +mira `Actualizar el código a BS4`_. + +Esta documentación ha sido traducida a otras lenguas por los usuarios +de Beautiful Soup: + +* `这篇文档当然还有中文版. `_ +* このページは日本語で利用できます(`外部リンク `_) +* `이 문서는 한국어 번역도 가능합니다. `_ +* `Este documento também está disponível em Português do Brasil. `_ +* `Эта документация доступна на русском языке. `_ + +Cómo conseguir ayuda +==================== +Si tienes alguna pregunta sobre BeautifulSoup, o si tienes problemas, +`envía un correo electrónico al grupo de discusión +`_. +Si tienes algún problema relacionado con el análisis de un documento HTML, +asegúrate de mencionar :ref:`lo que la función diagnose() dice ` +sobre dicho documento. + +Cuando informes de algún error en esta documentación, por favor, +indica la traducción que estás leyendo. + +=============== + Inicio rápido +=============== + +Este es un documento HTML que usaré como ejemplo a lo largo de este +documento. Es parte de una historia de `Alicia en el país de las maravillas`:: + + html_doc = """The Dormouse's story + +

The Dormouse's story

+ +

Once upon a time there were three little sisters; and their names were + Elsie, + Lacie and + Tillie; + and they lived at the bottom of a well.

+ +

...

+ """ + +Al procesar el documento de "Las tres hermanas" en Beautiful Soup, se nos +devuelve un objeto :py:class:`BeautifulSoup`, que representa el +documento como una estructura de datos anidada:: + + from bs4 import BeautifulSoup + soup = BeautifulSoup(html_doc, 'html.parser') + + print(soup.prettify()) + # + # + # + # The Dormouse's story + # + # + # + #

+ # + # The Dormouse's story + # + #

+ #

+ # Once upon a time there were three little sisters; and their names were + # + # Elsie + # + # , + # + # Lacie + # + # and + # + # Tillie + # + # ; and they lived at the bottom of a well. + #

+ #

+ # ... + #

+ # + # + +Estas son algunas de las maneras sencillas para navegar +por la estructura de datos:: + + soup.title + # The Dormouse's story + + soup.title.name + # u'title' + + soup.title.string + # u'The Dormouse's story' + + soup.title.parent.name + # u'head' + + soup.p + #

The Dormouse's story

+ + soup.p['class'] + # u'title' + + soup.a + # Elsie + + soup.find_all('a') + # [Elsie, + # Lacie, + # Tillie] + + soup.find(id="link3") + # Tillie + +Una tarea frecuente es extraer todas las URL encontradas en las etiquetas + de una página:: + + for link in soup.find_all('a'): + print(link.get('href')) + # http://example.com/elsie + # http://example.com/lacie + # http://example.com/tillie + +Otra tarea habitual es extraer todo el texto de una página:: + + print(soup.get_text()) + # The Dormouse's story + # + # The Dormouse's story + # + # Once upon a time there were three little sisters; and their names were + # Elsie, + # Lacie and + # Tillie; + # and they lived at the bottom of a well. + # + # ... + +¿Esto se parece a lo que necesitas? Si es así, sigue leyendo. + +========================= + Instalar Beautiful Soup +========================= +Si usas una versión reciente de Debian o Ubuntu Linux, puedes instalar +Beautiful Soup con el gestor de paquetes del sistema: + +:kbd:`$ apt-get install python3-bs4` + +Beautiful Soup 4 está publicado en Pypi, así que si no puedes instalarlo +con el gestor de paquetes, puedes instalarlo con ``easy_install`` o +``pip``. El nombre del paquete es ``beautifulsoup4``. Asegúrate de que +usas la versión correcta de ``pip`` o ``easy_install`` para tu versión +de Python (podrían llamarse ``pip3`` y ``easy_install3``, respectivamente): + +:kbd:`$ easy_install beautifulsoup4` + +:kbd:`$ pip install beautifulsoup4` + +(El paquete :py:class:`BeautifulSoup` ``no`` es el que quieres. Ese es +el lanzamiento anterior `Beautiful Soup 3`_. Muchos *software* utilizan +BS3, así que aún está disponible, pero si estás escribiendo nuevo código, +deberías instalar ``beautifulsoup4``). + +Si no tienes ``easy_install`` o ``pip`` instalados, puedes +`descargar el código de Beautiful Soup 4 comprimido en un tarball +`_ e +instalarlo con ``setup.py``: + +:kbd:`$ python setup.py install` + +Si aún así todo falla, la licencia de Beautiful Soup te permite +empaquetar la librería completa con tu aplicación. Puedes descargar +el *tarball*, copiar su directorio ``bs4`` en tu base de código y +usar Beautiful Soup sin instalarlo en absoluto. + +Yo empleo Python 3.10 para desarrollar Beautiful Soup, aunque debería +funcionar con otras versiones recientes. + +.. _parser-installation: + + +Instalar un analizador +====================== + +Beautiful Soup soporta el analizador de HTML incluido en la librería +estándar de Python, aunque también soporta varios analizadores de +Python de terceros. Uno de ellos es el `analizador de lxml `_. +Dependiendo de tu instalación, puedes instalar lxml con uno de los +siguientes comandos: + +:kbd:`$ apt-get install python-lxml` + +:kbd:`$ easy_install lxml` + +:kbd:`$ pip install lxml` + +Otra alternativa es usar el analizador de Python de +`html5lib `_, +el cual analiza HTML de la misma manera en la que lo haría +un navegador web. Dependiendo de tu instalación, puedes instalar +html5lib con uno de los siguientes comandos: + +:kbd:`$ apt-get install python-html5lib` + +:kbd:`$ easy_install html5lib` + +:kbd:`$ pip install html5lib` + +Esta tabla resume las ventajas e inconvenientes de cada librería de los analizadores: + ++-----------------------+--------------------------------------------+-----------------------------------+-----------------------------+ +| Analizador | Uso típico | Ventajas | Desventajas | ++-----------------------+--------------------------------------------+-----------------------------------+-----------------------------+ +| html.parser de Python | ``BeautifulSoup(markup, "html.parser")`` | * Ya incluido | * No tan rápido como lxml, | +| | | * Rapidez decente | menos tolerante que | +| | | * Tolerante (en Python 3.2) | html5lib. | ++-----------------------+--------------------------------------------+-----------------------------------+-----------------------------+ +| Analizador HTML de | ``BeautifulSoup(markup, "lxml")`` | * Muy rápido | * Dependencia externa de C | +| lxml | | * Tolerante | | ++-----------------------+--------------------------------------------+-----------------------------------+-----------------------------+ +| Analizador XML de | ``BeautifulSoup(markup, "lxml-xml")`` | * Muy rápido | * Dependencia externa de C | +| lxml | ``BeautifulSoup(markup, "xml")`` | * El único analizador XML | | +| | | actualmente soportado | | ++-----------------------+--------------------------------------------+-----------------------------------+-----------------------------+ +| html5lib | ``BeautifulSoup(markup, "html5lib")`` | * Extremadamente tolerante | * Muy lento | +| | | * Analiza las páginas de la misma | * Dependencia externa de | +| | | manera que un navegador web | Python | +| | | * Crea HTML5 válido | | ++-----------------------+--------------------------------------------+-----------------------------------+-----------------------------+ + +Si puedes, te recomiendo que instales y uses lxml para mayor velocidad. + +Ten en cuenta que si un documento es inválido, analizadores diferentes +generarán árboles de Beautiful Soup diferentes para él. Mira +`Diferencias entre analizadores`_ para más detalle. + +================== + Haciendo la sopa +================== + +Para analizar un documento pásalo al constructor de :py:class:`BeautifulSoup`. +Puedes pasar una cadena de caracteres o abrir un manejador de archivos:: + + from bs4 import BeautifulSoup + + with open("index.html") as fp: + soup = BeautifulSoup(fp, 'html.parser') + + soup = BeautifulSoup("a web page", 'html.parser') + +Primero, el documento se convierte a Unicode, y las entidades HTML se +convierten a caracteres Unicode:: + + print(BeautifulSoup("Sacré bleu!", "html.parser")) + # Sacré bleu! + +Entonces Beautiful Soup analiza el documento usando el mejor analizador +disponible. Usará un analizador HTML a no ser que se especifique que se +use un analizador XML (ver `Analizar XML`_). + +================== + Tipos de objetos +================== + +Beautiful Soup transforma un complejo documento HTML en un complejo árbol de objetos +de Python. Pero tan solo tendrás que lidiar con cuatro `tipos` de objetos: :py:class:`Tag`, +:py:class:`NavigableString`, :py:class:`BeautifulSoup` y :py:class:`Comment`. + +.. py:class:: Tag + + Un objeto :py:class:`Tag` corresponde a una etiqueta XML o HTML en el documento + original. + + :: + + soup = BeautifulSoup('Extremely bold', 'html.parser') + tag = soup.b + type(tag) + # + + Las etiquetas tienen muchos atributos y métodos, y cubriré la mayoría de ellos en + `Navegar por el árbol`_ y `Buscar en el árbol`_. Por ahora, las características + más importantes de una etiqueta son su nombre y sus atributos. + + .. py:attribute:: name + + Toda etiqueta tiene un nombre:: + + tag.name + # 'b' + + + Si cambias el nombre de una etiqueta, el cambio se verá reflejado en + cualquier especificación generada por Beautiful Soup a partir de entonces:: + + tag.name = "blockquote" + tag + #
Extremely bold
+ + .. py:attribute:: attrs + + Una etiqueta HTML o XML puede tener cualquier cantidad de atributos. + La etiqueta ```` tiene un atributo "id" cuyo valor + es "boldest". Puedes acceder a los atributos de una etiqueta + usándola como un diccionario:: + + tag = BeautifulSoup('bold', 'html.parser').b + tag['id'] + # 'boldest' + + Puedes acceder a los atributos del diccionario directamente con ``.attrs``:: + + tag.attrs + # {'id': 'boldest'} + + Puedes añadir, quitar y modificar los atributos de una etiqueta. De nuevo, esto + se realiza usando la etiqueta como un diccionario:: + + tag['id'] = 'verybold' + tag['another-attribute'] = 1 + tag + # + + del tag['id'] + del tag['another-attribute'] + tag + # bold + + tag['id'] + # KeyError: 'id' + tag.get('id') + # None + + .. _multivalue: + + Atributos multivaluados + ----------------------- + + HTML 4 define algunos atributos que pueden tomar múltiples valores. HTML 5 + elimina un par de ellos, pero define unos cuantos más. El atributo multivaluado + más común es ``class`` (esto es, una etiqueta puede tener más de una clase de CSS). + Otros incluyen ``rel``, ``rev``, ``accept-charset``, ``headers`` y ``accesskey``. + Por defecto, Beautiful Soup transforma los valores de un atributo multivaluado en + una lista:: + + css_soup = BeautifulSoup('

', 'html.parser') + css_soup.p['class'] + # ['body'] + + css_soup = BeautifulSoup('

', 'html.parser') + css_soup.p['class'] + # ['body', 'strikeout'] + + Si un atributo `parece` que tiene más de un valor, pero no es un atributo + multivaluado definido como tal por ninguna versión del estándar de HTML, + Beautiful Soup no modificará el atributo:: + + id_soup = BeautifulSoup('

', 'html.parser') + id_soup.p['id'] + # 'my id' + + Cuando transformas una etiqueta en una cadena de caracteres, muchos atributos + se combinan:: + + rel_soup = BeautifulSoup('

Back to the homepage

', 'html.parser') + rel_soup.a['rel'] + # ['index', 'first'] + rel_soup.a['rel'] = ['index', 'contents'] + print(rel_soup.p) + #

Back to the homepage

+ + Puedes forzar que todos los atributos sean analizados como cadenas + de caracteres pasando ``multi_valued_attributes=None`` como argumento + clave en el constructor de :py:class:`BeautifulSoup`:: + + no_list_soup = BeautifulSoup('

', 'html.parser', multi_valued_attributes=None) + no_list_soup.p['class'] + # 'body strikeout' + + Puedes usar ``get_attribute_list`` para obtener un valor que siempre sea una lista, + sin importar si es un atributo multivaluado:: + + id_soup.p.get_attribute_list('id') + # ["my id"] + + Si analizas un documento como XML, no hay atributos multivaluados:: + + xml_soup = BeautifulSoup('

', 'xml') + xml_soup.p['class'] + # 'body strikeout' + + Una vez más, puedes configurar esto usando el argumento ``multi_valued_attributes`` :: + + class_is_multi= { '*' : 'class'} + xml_soup = BeautifulSoup('

', 'xml', multi_valued_attributes=class_is_multi) + xml_soup.p['class'] + # ['body', 'strikeout'] + + Probablemente no tengas que hacer esto, pero si lo necesitas, usa los + parámetros por defecto como guía. Implementan las reglas descritas en la + especificación de HTML:: + + from bs4.builder import builder_registry + builder_registry.lookup('html').DEFAULT_CDATA_LIST_ATTRIBUTES + +.. py:class:: NavigableString + +----------------------------- + +Un *string* corresponde a un trozo de texto en una etiqueta. Beautiful Soup usa la clase +:py:class:`NavigableString` para contener estos trozos de texto:: + + soup = BeautifulSoup('Extremely bold', 'html.parser') + tag = soup.b + tag.string + # 'Extremely bold' + type(tag.string) + # + +Un :py:class:`NavigableString` es como una cadena de caracteres de Python Unicode, +exceptuando que también soporta algunas de las características descritas en +`Navegar por el árbol`_ y `Buscar en el árbol`_. Puedes convertir un objeto +:py:class:`NavigableString` a una cadena de caracteres Unicode usando ``str``:: + + unicode_string = str(tag.string) + unicode_string + # 'Extremely bold' + type(unicode_string) + # + +No puedes editar dicha cadena, pero puedes reemplazar una cadena por otra, usando +:ref:`replace_with()`:: + + tag.string.replace_with("No longer bold") + tag + # No longer bold + +:py:class:`NavigableString` soporta la mayoría de las características descritas en +`Navegar por el árbol`_ y `Buscar en el árbol`_, pero no todas. +En particular, como una cadena no puede contener nada (la manera en la que +una etiqueta contiene una cadena de caracteres u otra etiqueta), *strings* no +admiten los atributos `.contents`` o ``.string``, o el método ``find()``. + +Si quieres usar un :py:class:`NavigableString` fuera de Beautiful Soup, +deberías llamar ``unicode()`` sobre él para convertirlo en una cadena de caracteres +de Python Unicode. Si no, tu cadena arrastrará una referencia a todo el árbol analizado +de Beautiful Soup, incluso cuando hayas acabado de utilizar Beautiful Soup. Esto es un +gran malgasto de memoria. + +.. py:class:: BeautifulSoup + +--------------------------- + +El objeto :py:class:`BeautifulSoup` representa el documento analizado +en su conjunto. Para la mayoría de propósitos, puedes usarlo como un objeto +:py:class:`Tag`. Esto significa que soporta la mayoría de métodos descritos +en `Navegar por el árbol`_ and `Buscar en el árbol`_. + +Puedes también pasar un objeto :py:class:`BeautifulSoup` en cualquiera de +los métodos definidos en `Modificar el árbol`_, como si fuese un :py:class:`Tag`. +Esto te permite hacer cosas como combinar dos documentos analizados:: + + doc = BeautifulSoup("INSERT FOOTER HEREHere's the footer", "xml") + doc.find(text="INSERT FOOTER HERE").replace_with(footer) + # 'INSERT FOOTER HERE' + print(doc) + # + #
Here's the footer
+ +Como un objeto :py:class:`BeautifulSoup` no corresponde realmente con una +etiqueta HTML o XML, no tiene nombre ni atributos. Aún así, es útil +comprobar su ``.name``, así que se le ha dado el ``.name`` especial +"[document]":: + + soup.name + # '[document]' + +Cadenas especiales +================== + +:py:class:`Tag`, :py:class:`NavigableString` y +:py:class:`BeautifulSoup` cubren la mayoría de todo lo que verás en +un archivo HTML o XML, aunque aún quedan algunos remanentes. El principal +que probablemente encuentres es el :py:class:`Comment`. + +.. py:class:: Comment + +:: + + markup = "" + soup = BeautifulSoup(markup, 'html.parser') + comment = soup.b.string + type(comment) + # + +El objeto :py:class:`Comment` es solo un tipo especial de :py:class:`NavigableString`:: + + comment + # 'Hey, buddy. Want to buy a used parser' + +Pero cuando aparece como parte de un documento HTML, un :py:class:`Comment` +se muestra con un formato especial:: + + print(soup.b.prettify()) + # + # + # + +Para documentos HTML +-------------------- + +Beautiful Soup define algunas subclases de :py:class:`NavigableString` +para contener cadenas de caracteres encontradas dentro de etiquetas +HTML específicas. Esto hace más fácil tomar el cuerpo principal de la +página, ignorando cadenas que probablemente representen directivas de +programación encontradas dentro de la página. `(Estas clases son nuevas +en Beautiful Soup 4.9.0, y el analizador html5lib no las usa)`. + +.. py:class:: Stylesheet + +Una subclase de :py:class:`NavigableString` que representa hojas de estilo +CSS embebidas; esto es, cualquier cadena en una etiqueta +``