Belle soupe - Guide rapide
Dans le monde d'aujourd'hui, nous avons des tonnes de données / informations non structurées (principalement des données Web) disponibles gratuitement. Parfois, les données disponibles gratuitement sont faciles à lire et parfois non. Peu importe la façon dont vos données sont disponibles, le web scraping est un outil très utile pour transformer des données non structurées en données structurées plus faciles à lire et à analyser. En d'autres termes, un moyen de collecter, d'organiser et d'analyser cette énorme quantité de données consiste à utiliser le web scraping. Voyons donc d'abord ce qu'est le web-scraping.
Qu'est-ce que le web-scraping?
Le grattage est simplement un processus d'extraction (à partir de divers moyens), de copie et de filtrage des données.
Lorsque nous grattons ou extrayons des données ou des flux à partir du Web (comme des pages Web ou des sites Web), cela s'appelle du Web-scraping.
Ainsi, le scraping Web, également connu sous le nom d'extraction de données Web ou de récolte Web, est l'extraction de données à partir du Web. En bref, le web scraping permet aux développeurs de collecter et d'analyser des données sur Internet.
Pourquoi le Web-scraping?
Le web-scraping est l'un des outils les plus efficaces pour automatiser la plupart des actions d'un humain lors de la navigation. Le web-scraping est utilisé dans une entreprise de différentes manières -
Données pour la recherche
Un analyste intelligent (comme un chercheur ou un journaliste) utilise Web Scrapper au lieu de collecter et de nettoyer manuellement les données des sites Web.
Comparaison des prix et de la popularité des produits
Actuellement, il existe quelques services qui utilisent des scrappers Web pour collecter des données à partir de nombreux sites en ligne et les utiliser pour comparer la popularité et les prix des produits.
Suivi SEO
Il existe de nombreux outils de référencement tels que Ahrefs, Seobility, SEMrush, etc., qui sont utilisés pour l'analyse concurrentielle et pour extraire des données des sites Web de vos clients.
Moteurs de recherche
Il existe de grandes entreprises informatiques dont l'activité dépend uniquement du scraping Web.
Ventes et marketing
Les données collectées via le web scraping peuvent être utilisées par les spécialistes du marketing pour analyser différentes niches et concurrents ou par le spécialiste de la vente pour vendre des services de marketing de contenu ou de promotion sur les réseaux sociaux.
Pourquoi Python pour le Web Scraping?
Python est l'un des langages les plus populaires pour le scraping Web car il peut gérer très facilement la plupart des tâches liées à l'exploration Web.
Vous trouverez ci-dessous quelques points expliquant pourquoi choisir python pour le scraping Web:
Facilité d'utilisation
Comme la plupart des développeurs conviennent que Python est très facile à coder. Nous n'avons pas besoin d'utiliser d'accolades "{}" ou de points-virgules ";" n'importe où, ce qui le rend plus lisible et facile à utiliser lors du développement de web scrapers.
Support de bibliothèque énorme
Python fournit un vaste ensemble de bibliothèques pour différentes exigences, il est donc approprié pour le scraping Web ainsi que pour la visualisation de données, l'apprentissage automatique, etc.
Syntaxe facilement explicable
Python est un langage de programmation très lisible car la syntaxe python est facile à comprendre. Python est très expressif et l'indentation du code aide les utilisateurs à différencier différents blocs ou étendues dans le code.
Langue à typage dynamique
Python est un langage typé dynamiquement, ce qui signifie que les données affectées à une variable indiquent de quel type de variable il s'agit. Cela fait gagner beaucoup de temps et accélère le travail.
Immense communauté
La communauté Python est énorme, ce qui vous aide où que vous soyez lors de l'écriture de code.
Introduction à la belle soupe
The Beautiful Soup est une bibliothèque de python qui porte le nom d'un poème de Lewis Carroll du même nom dans «Alice's Adventures in the Wonderland». Beautiful Soup est un package python et, comme son nom l'indique, analyse les données indésirables et aide à organiser et à formater les données Web désordonnées en corrigeant le mauvais HTML et en nous les présentant dans des structures XML facilement traversables.
En bref, Beautiful Soup est un package python qui nous permet d'extraire des données de documents HTML et XML.
Comme BeautifulSoup n'est pas une bibliothèque Python standard, nous devons d'abord l'installer. Nous allons installer la bibliothèque BeautifulSoup 4 (également connue sous le nom de BS4), qui est la dernière.
Pour isoler notre environnement de travail afin de ne pas perturber la configuration existante, créons d'abord un environnement virtuel.
Créer un environnement virtuel (facultatif)
Un environnement virtuel nous permet de créer une copie de travail isolée de python pour un projet spécifique sans affecter la configuration extérieure.
La meilleure façon d'installer n'importe quelle machine de package python est d'utiliser pip, cependant, si pip n'est pas déjà installé (vous pouvez le vérifier en utilisant - «pip –version» dans votre commande ou l'invite du shell), vous pouvez installer en donnant la commande ci-dessous -
Environnement Linux
$sudo apt-get install python-pip
Environnement Windows
Pour installer pip dans Windows, procédez comme suit -
Téléchargez le get-pip.py depuis https://bootstrap.pypa.io/get-pip.py ou du github à votre ordinateur.
Ouvrez l'invite de commande et accédez au dossier contenant le fichier get-pip.py.
Exécutez la commande suivante -
>python get-pip.py
Voilà, pip est maintenant installé sur votre machine Windows.
Vous pouvez vérifier votre pip installé en exécutant la commande ci-dessous -
>pip --version
pip 19.2.3 from c:\users\yadur\appdata\local\programs\python\python37\lib\site-packages\pip (python 3.7)
Installation de l'environnement virtuel
Exécutez la commande ci-dessous dans votre invite de commande -
>pip install virtualenv
Après l'exécution, vous verrez la capture d'écran ci-dessous -
La commande ci-dessous créera un environnement virtuel («myEnv») dans votre répertoire actuel -
>virtualenv myEnv
Capture d'écran
Pour activer votre environnement virtuel, exécutez la commande suivante -
>myEnv\Scripts\activate
Dans la capture d'écran ci-dessus, vous pouvez voir que nous avons «myEnv» comme préfixe qui nous indique que nous sommes sous l'environnement virtuel «myEnv».
Pour sortir de l'environnement virtuel, exécutez disable.
(myEnv) C:\Users\yadur>deactivate
C:\Users\yadur>
Comme notre environnement virtuel est prêt, installons maintenant beautifulsoup.
Installation de BeautifulSoup
Comme BeautifulSoup n'est pas une bibliothèque standard, nous devons l'installer. Nous allons utiliser le package BeautifulSoup 4 (connu sous le nom de bs4).
Machine Linux
Pour installer bs4 sur Debian ou Ubuntu Linux à l'aide du gestionnaire de paquets système, exécutez la commande ci-dessous -
$sudo apt-get install python-bs4 (for python 2.x)
$sudo apt-get install python3-bs4 (for python 3.x)
Vous pouvez installer bs4 en utilisant easy_install ou pip (au cas où vous rencontriez un problème lors de l'installation à l'aide de System Packager).
$easy_install beautifulsoup4
$pip install beautifulsoup4
(Vous devrez peut-être utiliser respectivement easy_install3 ou pip3 si vous utilisez python3)
Machine Windows
Installer beautifulsoup4 dans Windows est très simple, surtout si vous avez déjà installé pip.
>pip install beautifulsoup4
Alors maintenant, beautifulsoup4 est installé dans notre machine. Parlons de quelques problèmes rencontrés après l'installation.
Problèmes après l'installation
Sur la machine Windows que vous pouvez rencontrer, une erreur d'installation d'une mauvaise version est principalement due à -
Erreur: ImportError “No module named HTMLParser”, alors vous devez exécuter la version python 2 du code sous Python 3.
Erreur: ImportError “No module named html.parser” erreur, alors vous devez exécuter la version Python 3 du code sous Python 2.
Le meilleur moyen de sortir des deux situations ci-dessus est de réinstaller à nouveau BeautifulSoup, en supprimant complètement l'installation existante.
Si vous obtenez le SyntaxError “Invalid syntax” sur la ligne ROOT_TAG_NAME = u '[document]', alors vous devez convertir le code python 2 en python 3, soit en installant le package -
$ python3 setup.py install
ou en exécutant manuellement le script de conversion 2 à 3 de python sur le répertoire bs4 -
$ 2to3-3.2 -w bs4
Installer un analyseur
Par défaut, Beautiful Soup prend en charge l'analyseur HTML inclus dans la bibliothèque standard de Python, mais il prend également en charge de nombreux analyseurs python tiers externes tels que l'analyseur lxml ou l'analyseur html5lib.
Pour installer l'analyseur lxml ou html5lib, utilisez la commande -
Machine Linux
$apt-get install python-lxml
$apt-get insall python-html5lib
Machine Windows
$pip install lxml
$pip install html5lib
Généralement, les utilisateurs utilisent lxml pour la vitesse et il est recommandé d'utiliser l'analyseur lxml ou html5lib si vous utilisez une ancienne version de python 2 (avant la version 2.7.3) ou python 3 (avant 3.2.2) comme l'analyseur HTML intégré de python est pas très bon pour gérer les anciennes versions.
Courir une belle soupe
Il est temps de tester notre package Beautiful Soup dans l'une des pages html (en prenant la page web - https://www.tutorialspoint.com/index.htm, vous pouvez choisir n'importe quelle autre page Web de votre choix) et en extraire des informations.
Dans le code ci-dessous, nous essayons d'extraire le titre de la page Web -
from bs4 import BeautifulSoup
import requests
url = "https://www.tutorialspoint.com/index.htm"
req = requests.get(url)
soup = BeautifulSoup(req.text, "html.parser")
print(soup.title)
Production
<title>H2O, Colab, Theano, Flutter, KNime, Mean.js, Weka, Solidity, Org.Json, AWS QuickSight, JSON.Simple, Jackson Annotations, Passay, Boon, MuleSoft, Nagios, Matplotlib, Java NIO, PyTorch, SLF4J, Parallax Scrolling, Java Cryptography</title>
Une tâche courante consiste à extraire toutes les URL d'une page Web. Pour cela, il suffit d'ajouter la ligne de code ci-dessous -
for link in soup.find_all('a'):
print(link.get('href'))
Production
https://www.tutorialspoint.com/index.htm
https://www.tutorialspoint.com/about/about_careers.htm
https://www.tutorialspoint.com/questions/index.php
https://www.tutorialspoint.com/online_dev_tools.htm
https://www.tutorialspoint.com/codingground.htm
https://www.tutorialspoint.com/current_affairs.htm
https://www.tutorialspoint.com/upsc_ias_exams.htm
https://www.tutorialspoint.com/tutor_connect/index.php
https://www.tutorialspoint.com/whiteboard.htm
https://www.tutorialspoint.com/netmeeting.php
https://www.tutorialspoint.com/index.htm
https://www.tutorialspoint.com/tutorialslibrary.htm
https://www.tutorialspoint.com/videotutorials/index.php
https://store.tutorialspoint.com
https://www.tutorialspoint.com/gate_exams_tutorials.htm
https://www.tutorialspoint.com/html_online_training/index.asp
https://www.tutorialspoint.com/css_online_training/index.asp
https://www.tutorialspoint.com/3d_animation_online_training/index.asp
https://www.tutorialspoint.com/swift_4_online_training/index.asp
https://www.tutorialspoint.com/blockchain_online_training/index.asp
https://www.tutorialspoint.com/reactjs_online_training/index.asp
https://www.tutorix.com
https://www.tutorialspoint.com/videotutorials/top-courses.php
https://www.tutorialspoint.com/the_full_stack_web_development/index.asp
….
….
https://www.tutorialspoint.com/online_dev_tools.htm
https://www.tutorialspoint.com/free_web_graphics.htm
https://www.tutorialspoint.com/online_file_conversion.htm
https://www.tutorialspoint.com/netmeeting.php
https://www.tutorialspoint.com/free_online_whiteboard.htm
http://www.tutorialspoint.com
https://www.facebook.com/tutorialspointindia
https://plus.google.com/u/0/+tutorialspoint
http://www.twitter.com/tutorialspoint
http://www.linkedin.com/company/tutorialspoint
https://www.youtube.com/channel/UCVLbzhxVTiTLiVKeGV7WEBg
https://www.tutorialspoint.com/index.htm
/about/about_privacy.htm#cookies
/about/faq.htm
/about/about_helping.htm
/about/contact_us.htm
De même, nous pouvons extraire des informations utiles en utilisant beautifulsoup4.
Maintenant, comprenons plus à propos de la «soupe» dans l'exemple ci-dessus.
Dans l'exemple de code précédent, nous analysons le document via un beau constructeur à l'aide d'une méthode de chaîne. Une autre méthode consiste à faire passer le document via un descripteur de fichier ouvert.
from bs4 import BeautifulSoup
with open("example.html") as fp:
soup = BeautifulSoup(fp)
soup = BeautifulSoup("<html>data</html>")
Tout d'abord, le document est converti en Unicode, et les entités HTML sont converties en caractères Unicode: </p>
import bs4
html = '''<b>tutorialspoint</b>, <i>&web scraping &data science;</i>'''
soup = bs4.BeautifulSoup(html, 'lxml')
print(soup)
Production
<html><body><b>tutorialspoint</b>, <i>&web scraping &data science;</i></body></html>
BeautifulSoup analyse ensuite les données à l'aide d'un analyseur HTML ou vous lui dites explicitement d'analyser à l'aide d'un analyseur XML.
Structure de l'arborescence HTML
Avant d'examiner les différents composants d'une page HTML, commençons par comprendre l'arborescence HTML.
L'élément racine dans l'arborescence du document est le html, qui peut avoir des parents, des enfants et des frères et sœurs et cela dépend de sa position dans l'arborescence. Pour vous déplacer parmi les éléments HTML, les attributs et le texte, vous devez vous déplacer entre les nœuds de votre arborescence.
Supposons que la page Web soit comme indiqué ci-dessous -
Ce qui se traduit par un document html comme suit -
<html><head><title>TutorialsPoint</title></head><h1>Tutorialspoint Online Library</h1><p<<b>It's all Free</b></p></body></html>
Ce qui signifie simplement que pour le document html ci-dessus, nous avons une arborescence html comme suit -
Lorsque nous avons passé un document ou une chaîne html à un constructeur beautifulsoup, beautifulsoup convertit essentiellement une page html complexe en différents objets python. Ci-dessous, nous allons discuter de quatre grands types d'objets:
Tag
NavigableString
BeautifulSoup
Comments
Objets de balise
Une balise HTML est utilisée pour définir différents types de contenu. Un objet de balise dans BeautifulSoup correspond à une balise HTML ou XML dans la page ou le document réel.
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup('<b class="boldest">TutorialsPoint</b>')
>>> tag = soup.html
>>> type(tag)
<class 'bs4.element.Tag'>
Les balises contiennent de nombreux attributs et méthodes et deux caractéristiques importantes d'une balise sont son nom et ses attributs.
Nom (tag.name)
Chaque balise contient un nom et est accessible via «.name» comme suffixe. tag.name renverra le type de tag dont il s'agit.
>>> tag.name
'html'
Cependant, si nous changeons le nom de la balise, la même chose se reflétera dans le balisage HTML généré par BeautifulSoup.
>>> tag.name = "Strong"
>>> tag
<Strong><body><b class="boldest">TutorialsPoint</b></body></Strong>
>>> tag.name
'Strong'
Attributs (tag.attrs)
Un objet balise peut avoir n'importe quel nombre d'attributs. La balise <b class = ”boldest”> a un attribut 'class' dont la valeur est “boldest”. Tout ce qui n'est PAS une balise est essentiellement un attribut et doit contenir une valeur. Vous pouvez accéder aux attributs en accédant aux clés (comme en accédant à «class» dans l'exemple ci-dessus) ou en accédant directement via «.attrs»
>>> tutorialsP = BeautifulSoup("<div class='tutorialsP'></div>",'lxml')
>>> tag2 = tutorialsP.div
>>> tag2['class']
['tutorialsP']
Nous pouvons faire toutes sortes de modifications aux attributs de notre balise (ajouter / supprimer / modifier).
>>> tag2['class'] = 'Online-Learning'
>>> tag2['style'] = '2007'
>>>
>>> tag2
<div class="Online-Learning" style="2007"></div>
>>> del tag2['style']
>>> tag2
<div class="Online-Learning"></div>
>>> del tag['class']
>>> tag
<b SecondAttribute="2">TutorialsPoint</b>
>>>
>>> del tag['SecondAttribute']
>>> tag
</b>
>>> tag2['class']
'Online-Learning'
>>> tag2['style']
KeyError: 'style'
Attributs à valeurs multiples
Certains des attributs HTML5 peuvent avoir plusieurs valeurs. Le plus couramment utilisé est l'attribut de classe qui peut avoir plusieurs valeurs CSS. D'autres incluent «rel», «rev», «headers», «accesskey» et «accept-charset». Les attributs à valeurs multiples dans une belle soupe sont affichés sous forme de liste.
>>> from bs4 import BeautifulSoup
>>>
>>> css_soup = BeautifulSoup('<p class="body"></p>')
>>> css_soup.p['class']
['body']
>>>
>>> css_soup = BeautifulSoup('<p class="body bold"></p>')
>>> css_soup.p['class']
['body', 'bold']
Cependant, si un attribut contient plus d'une valeur mais qu'il ne s'agit pas d'attributs à valeurs multiples par n'importe quelle version de la norme HTML, belle soupe laissera l'attribut seul -
>>> id_soup = BeautifulSoup('<p id="body bold"></p>')
>>> id_soup.p['id']
'body bold'
>>> type(id_soup.p['id'])
<class 'str'>
Vous pouvez consolider plusieurs valeurs d'attribut si vous transformez une balise en chaîne.
>>> rel_soup = BeautifulSoup("<p> tutorialspoint Main <a rel='Index'> Page</a></p>")
>>> rel_soup.a['rel']
['Index']
>>> rel_soup.a['rel'] = ['Index', ' Online Library, Its all Free']
>>> print(rel_soup.p)
<p> tutorialspoint Main <a rel="Index Online Library, Its all Free"> Page</a></p>
En utilisant 'get_attribute_list', vous obtenez une valeur qui est toujours une liste, une chaîne, indépendamment du fait qu'il s'agisse d'une multi-valeur ou non.
id_soup.p.get_attribute_list(‘id’)
Cependant, si vous analysez le document en tant que 'xml', il n'y a pas d'attributs à valeurs multiples -
>>> xml_soup = BeautifulSoup('<p class="body bold"></p>', 'xml')
>>> xml_soup.p['class']
'body bold'
NavigableString
L'objet navigablestring est utilisé pour représenter le contenu d'une balise. Pour accéder au contenu, utilisez «.string» avec balise.
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>>
>>> soup.string
'Hello, Tutorialspoint!'
>>> type(soup.string)
>
Vous pouvez remplacer la chaîne par une autre chaîne, mais vous ne pouvez pas modifier la chaîne existante.
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>> soup.string.replace_with("Online Learning!")
'Hello, Tutorialspoint!'
>>> soup.string
'Online Learning!'
>>> soup
<html><body><h2 id="message">Online Learning!</h2></body></html>
BeautifulSoup
BeautifulSoup est l'objet créé lorsque nous essayons de gratter une ressource Web. C'est donc le document complet que nous essayons de gratter. La plupart du temps, il est traité comme objet tag.
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup("<h2 id='message'>Hello, Tutorialspoint!</h2>")
>>> type(soup)
<class 'bs4.BeautifulSoup'>
>>> soup.name
'[document]'
commentaires
L'objet comment illustre la partie commentaire du document Web. C'est juste un type spécial de NavigableString.
>>> soup = BeautifulSoup('<p><!-- Everything inside it is COMMENTS --></p>')
>>> comment = soup.p.string
>>> type(comment)
<class 'bs4.element.Comment'>
>>> type(comment)
<class 'bs4.element.Comment'>
>>> print(soup.p.prettify())
<p>
<!-- Everything inside it is COMMENTS -->
</p>
Objets NavigableString
Les objets navigablestring sont utilisés pour représenter le texte dans les balises, plutôt que les balises elles-mêmes.
Dans ce chapitre, nous discuterons de la navigation par balises.
Voici notre document html -
>>> html_doc = """
<html><head><title>Tutorials Point</title></head>
<body>
<p class="title"><b>The Biggest Online Tutorials Library, It's all Free</b></p>
<p class="prog">Top 5 most used Programming Languages are:
<a href="https://www.tutorialspoint.com/java/java_overview.htm" class="prog" id="link1">Java</a>,
<a href="https://www.tutorialspoint.com/cprogramming/index.htm" class="prog" id="link2">C</a>,
<a href="https://www.tutorialspoint.com/python/index.htm" class="prog" id="link3">Python</a>,
<a href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" class="prog" id="link4">JavaScript</a> and
<a href="https://www.tutorialspoint.com/ruby/index.htm" class="prog" id="link5">C</a>;
as per online survey.</p>
<p class="prog">Programming Languages</p>
"""
>>>
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html_doc, 'html.parser')
>>>
Sur la base du document ci-dessus, nous essaierons de passer d'une partie du document à une autre.
Descente
Les balises, qui peuvent contenir d'autres balises / chaînes (enfants de balises), sont l'un des éléments importants de tout élément de document HTML. Beautiful Soup propose différentes façons de naviguer et de parcourir les enfants de l'étiquette.
Navigation à l'aide des noms de balises
Le moyen le plus simple de rechercher une arborescence d'analyse est de rechercher la balise par son nom. Si vous voulez la balise <head>, utilisez soup.head -
>>> soup.head
<head>&t;title>Tutorials Point</title></head>
>>> soup.title
<title>Tutorials Point</title>
Pour obtenir une balise spécifique (comme la première balise <b>) dans la balise <body>.
>>> soup.body.b
<b>The Biggest Online Tutorials Library, It's all Free</b>
L'utilisation d'un nom de balise comme attribut ne vous donnera que la première balise portant ce nom -
>>> soup.a
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
Pour obtenir tous les attributs de la balise, vous pouvez utiliser la méthode find_all () -
>>> soup.find_all("a")
[<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>, <a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>, <a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>, <a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>, <a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>]>>> soup.find_all("a")
[<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>, <a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>, <a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>, <a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>, <a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>]
.contenu et .enfants
Nous pouvons rechercher les enfants de la balise dans une liste par son .contents -
>>> head_tag = soup.head
>>> head_tag
<head><title>Tutorials Point</title></head>
>>> Htag = soup.head
>>> Htag
<head><title>Tutorials Point</title></head>
>>>
>>> Htag.contents
[<title>Tutorials Point</title>
>>>
>>> Ttag = head_tag.contents[0]
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.contents
['Tutorials Point']
L'objet BeautifulSoup lui-même a des enfants. Dans ce cas, la balise <html> est l'enfant de l'objet BeautifulSoup -
>>> len(soup.contents)
2
>>> soup.contents[1].name
'html'
Une chaîne n'a pas de .contents, car elle ne peut rien contenir -
>>> text = Ttag.contents[0]
>>> text.contents
self.__class__.__name__, attr))
AttributeError: 'NavigableString' object has no attribute 'contents'
Au lieu de les obtenir sous forme de liste, utilisez le générateur .children pour accéder aux enfants de la balise -
>>> for child in Ttag.children:
print(child)
Tutorials Point
.descendance
L'attribut .descendants vous permet d'itérer sur tous les enfants d'une balise, de manière récursive -
ses enfants directs et les enfants de ses enfants directs et ainsi de suite -
>>> for child in Htag.descendants:
print(child)
<title>Tutorials Point</title>
Tutorials Point
La balise <head> n'a qu'un seul enfant, mais elle a deux descendants: la balise <title> et l'enfant de la balise <title>. L'objet beautifulsoup n'a qu'un seul enfant direct (la balise <html>), mais il a beaucoup de descendants -
>>> len(list(soup.children))
2
>>> len(list(soup.descendants))
33
.chaîne
Si la balise n'a qu'un seul enfant et que cet enfant est une chaîne NavigableString, l'enfant est rendu disponible en tant que .string -
>>> Ttag.string
'Tutorials Point'
Si le seul enfant d'une balise est une autre balise, et que cette balise a une .string, alors la balise parent est considérée comme ayant la même .string que son enfant -
>>> Htag.contents
[<title>Tutorials Point</title>]
>>>
>>> Htag.string
'Tutorials Point'
Cependant, si une balise contient plus d'une chose, alors on ne sait pas à quoi .string doit faire référence, donc .string est défini sur None -
>>> print(soup.html.string)
None
.strings et stripped_strings
S'il y a plus d'une chose dans une balise, vous pouvez toujours regarder uniquement les chaînes. Utilisez le générateur .strings -
>>> for string in soup.strings:
print(repr(string))
'\n'
'Tutorials Point'
'\n'
'\n'
"The Biggest Online Tutorials Library, It's all Free"
'\n'
'Top 5 most used Programming Languages are: \n'
'Java'
',\n'
'C'
',\n'
'Python'
',\n'
'JavaScript'
' and\n'
'C'
';\n \nas per online survey.'
'\n'
'Programming Languages'
'\n'
Pour supprimer les espaces supplémentaires, utilisez le générateur .stripped_strings -
>>> for string in soup.stripped_strings:
print(repr(string))
'Tutorials Point'
"The Biggest Online Tutorials Library, It's all Free"
'Top 5 most used Programming Languages are:'
'Java'
','
'C'
','
'Python'
','
'JavaScript'
'and'
'C'
';\n \nas per online survey.'
'Programming Languages'
Monter
Dans une analogie avec «arbre généalogique», chaque tag et chaque chaîne a un parent: le tag qui le contient:
.parent
Pour accéder à l'élément parent de l'élément, utilisez l'attribut .parent.
>>> Ttag = soup.title
>>> Ttag
<title>Tutorials Point</title>
>>> Ttag.parent
<head>title>Tutorials Point</title></head>
Dans notre html_doc, la chaîne de titre elle-même a un parent: la balise <title> qui la contient -
>>> Ttag.string.parent
<title>Tutorials Point</title>
Le parent d'une balise de niveau supérieur comme <html> est l'objet Beautifulsoup lui-même -
>>> htmltag = soup.html
>>> type(htmltag.parent)
<class 'bs4.BeautifulSoup'>
Le .parent d'un objet Beautifulsoup est défini comme Aucun -
>>> print(soup.parent)
None
.Parents
Pour parcourir tous les éléments parents, utilisez l'attribut .parents.
>>> link = soup.a
>>> link
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
>>>
>>> for parent in link.parents:
if parent is None:
print(parent)
else:
print(parent.name)
p
body
html
[document]
Aller de côté
Vous trouverez ci-dessous un document simple -
>>> sibling_soup = BeautifulSoup("<a><b>TutorialsPoint</b><c><strong>The Biggest Online Tutorials Library, It's all Free</strong></b></a>")
>>> print(sibling_soup.prettify())
<html>
<body>
<a>
<b>
TutorialsPoint
</b>
<c>
<strong>
The Biggest Online Tutorials Library, It's all Free
</strong>
</c>
</a>
</body>
</html>
Dans le document ci-dessus, les balises <b> et <c> sont au même niveau et ils sont tous les deux enfants de la même balise. Les balises <b> et <c> sont des frères et sœurs.
.next_sibling et .previous_sibling
Utilisez .next_sibling et .previous_sibling pour naviguer entre les éléments de page qui se trouvent au même niveau de l'arborescence d'analyse:
>>> sibling_soup.b.next_sibling
<c><strong>The Biggest Online Tutorials Library, It's all Free</strong></c>
>>>
>>> sibling_soup.c.previous_sibling
<b>TutorialsPoint</b>
La balise <b> a un .next_sibling mais pas de .previous_sibling, car il n'y a rien avant la balise <b> au même niveau de l'arbre, même cas avec la balise <c>.
>>> print(sibling_soup.b.previous_sibling)
None
>>> print(sibling_soup.c.next_sibling)
None
Les deux chaînes ne sont pas des frères et sœurs, car ils n'ont pas le même parent.
>>> sibling_soup.b.string
'TutorialsPoint'
>>>
>>> print(sibling_soup.b.string.next_sibling)
None
.next_siblings et .previous_siblings
Pour parcourir les frères et sœurs d'une balise, utilisez .next_siblings et .previous_siblings.
>>> for sibling in soup.a.next_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>
',\n'
>a class="prog" href="https://www.tutorialspoint.com/python/index.htm" id="link3">Python</a>
',\n'
<a class="prog" href="https://www.tutorialspoint.com/javascript/javascript_overview.htm" id="link4">JavaScript</a>
' and\n'
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm"
id="link5">C</a>
';\n \nas per online survey.'
>>> for sibling in soup.find(id="link3").previous_siblings:
print(repr(sibling))
',\n'
<a class="prog" href="https://www.tutorialspoint.com/cprogramming/index.htm" id="link2">C</a>
',\n'
<a class="prog" href="https://www.tutorialspoint.com/java/java_overview.htm" id="link1">Java</a>
'Top 5 most used Programming Languages are: \n'
Aller et venir
Revenons maintenant aux deux premières lignes de notre précédent exemple «html_doc» -
&t;html><head><title>Tutorials Point</title></head>
<body>
<h4 class="tagLine"><b>The Biggest Online Tutorials Library, It's all Free</b></h4>
Un analyseur HTML prend ci-dessus la chaîne de caractères et la transforme en une série d'événements tels que «ouvrir une balise <html>», «ouvrir une balise <head>», «ouvrir la balise <title>», «ajouter une chaîne», «Fermez la balise </title>», «fermez la balise </head>», «ouvrez une balise <h4>» et ainsi de suite. BeautifulSoup propose différentes méthodes pour reconstruire l'analyse initiale du document.
.next_element et .previous_element
L'attribut .next_element d'une balise ou d'une chaîne pointe vers ce qui a été analysé immédiatement après. Parfois, il ressemble à .next_sibling, mais ce n'est pas entièrement le même. Vous trouverez ci-dessous la dernière balise <a> de notre exemple de document «html_doc».
>>> last_a_tag = soup.find("a", id="link5")
>>> last_a_tag
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>
>>> last_a_tag.next_sibling
';\n \nas per online survey.'
Cependant, l'élément .next_element de cette balise <a>, la chose qui a été analysée immédiatement après la balise <a>, n'est pas le reste de cette phrase: c'est le mot «C»:
>>> last_a_tag.next_element
'C'
Le comportement ci-dessus est dû au fait que dans le balisage d'origine, la lettre «C» est apparue avant ce point-virgule. L'analyseur a rencontré une balise <a>, puis la lettre «C», puis la balise de fermeture </a>, puis le point-virgule et le reste de la phrase. Le point-virgule est au même niveau que la balise <a>, mais la lettre «C» a été rencontrée en premier.
L'attribut .previous_element est l'exact opposé de .next_element. Il pointe vers n'importe quel élément analysé immédiatement avant celui-ci.
>>> last_a_tag.previous_element
' and\n'
>>>
>>> last_a_tag.previous_element.next_element
<a class="prog" href="https://www.tutorialspoint.com/ruby/index.htm" id="link5">C</a>
.next_elements et .previous_elements
Nous utilisons ces itérateurs pour avancer et reculer vers un élément.
>>> for element in last_a_tag.next_e lements:
print(repr(element))
'C'
';\n \nas per online survey.'
'\n'
<p class="prog">Programming Languages</p>
'Programming Languages'
'\n'
Il existe de nombreuses méthodes Beautifulsoup, ce qui nous permet de rechercher un arbre d'analyse. Les deux méthodes les plus courantes et les plus utilisées sont find () et find_all ().
Avant de parler de find () et find_all (), voyons quelques exemples de différents filtres que vous pouvez passer dans ces méthodes.
Types de filtres
Nous avons différents filtres que nous pouvons transmettre à ces méthodes et la compréhension de ces filtres est cruciale car ces filtres sont utilisés encore et encore, tout au long de l'API de recherche. Nous pouvons utiliser ces filtres en fonction du nom de la balise, de ses attributs, du texte d'une chaîne ou d'un mélange de ceux-ci.
Un string
L'un des types de filtre les plus simples est une chaîne. En passant une chaîne à la méthode de recherche, Beautifulsoup effectuera une correspondance avec cette chaîne exacte.
Le code ci-dessous trouvera toutes les balises <p> dans le document -
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>> markup.find_all('p')
[<p>Top Three</p>, <p></p>, <p><b>Java, Python, Cplusplus</b></p>]
Expression régulière
Vous pouvez trouver toutes les balises commençant par une chaîne / balise donnée. Avant cela, nous devons importer le module re pour utiliser une expression régulière.
>>> import re
>>> markup = BeautifulSoup('<p>Top Three</p><p><pre>Programming Languages are:</pre></p><p><b>Java, Python, Cplusplus</b></p>')
>>>
>>> markup.find_all(re.compile('^p'))
[<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>]
liste
Vous pouvez transmettre plusieurs balises à rechercher en fournissant une liste. Le code ci-dessous trouve toutes les balises <b> et <pre> -
>>> markup.find_all(['pre', 'b'])
[<pre>Programming Languages are:</pre>, <b>Java, Python, Cplusplus</b>]
Vrai
True renverra toutes les balises qu'il peut trouver, mais aucune chaîne seule -
>>> markup.find_all(True)
[<html><body><p>Top Three</p><p></p><pre>Programming Languages are:</pre>
<p><b>Java, Python, Cplusplus</b> </p> </body></html>,
<body><p>Top Three</p><p></p><pre> Programming Languages are:</pre><p><b>Java, Python, Cplusplus</b></p>
</body>,
<p>Top Three</p>, <p></p>, <pre>Programming Languages are:</pre>, <p><b>Java, Python, Cplusplus</b></p>, <b>Java, Python, Cplusplus</b>]
Pour ne renvoyer que les balises de la soupe ci-dessus -
>>> for tag in markup.find_all(True):
(tag.name)
'html'
'body'
'p'
'p'
'pre'
'p'
'b'
Trouver tout()
Vous pouvez utiliser find_all pour extraire toutes les occurrences d'une balise particulière de la réponse de la page comme -
Syntaxe
find_all(name, attrs, recursive, string, limit, **kwargs)
Extrayons quelques données intéressantes d'IMDB - «Films les mieux notés» de tous les temps.
>>> url="https://www.imdb.com/chart/top/?ref_=nv_mv_250"
>>> content = requests.get(url)
>>> soup = BeautifulSoup(content.text, 'html.parser')
#Extract title Page
>>> print(soup.find('title'))
<title>IMDb Top 250 - IMDb</title>
#Extracting main heading
>>> for heading in soup.find_all('h1'):
print(heading.text)
Top Rated Movies
#Extracting sub-heading
>>> for heading in soup.find_all('h3'):
print(heading.text)
IMDb Charts
You Have Seen
IMDb Charts
Top India Charts
Top Rated Movies by Genre
Recently Viewed
D'en haut, nous pouvons voir que find_all nous donnera tous les éléments correspondant aux critères de recherche que nous définissons. Tous les filtres que nous pouvons utiliser avec find_all () peuvent être utilisés avec find () et d'autres méthodes de recherche comme find_parents () ou find_siblings ().
trouver()
Nous l'avons vu plus haut, find_all () est utilisé pour scanner tout le document pour trouver tout le contenu mais quelque chose, la condition est de ne trouver qu'un seul résultat. Si vous savez que le document ne contient qu'une seule balise <body>, il est inutile de rechercher l'ensemble du document. Une façon est d'appeler find_all () avec limit = 1 à chaque fois ou bien nous pouvons utiliser la méthode find () pour faire de même -
Syntaxe
find(name, attrs, recursive, string, **kwargs)
Donc, en dessous de deux méthodes différentes donne le même résultat -
>>> soup.find_all('title',limit=1)
[<title>IMDb Top 250 - IMDb</title>]
>>>
>>> soup.find('title')
<title>IMDb Top 250 - IMDb</title>
Dans les sorties ci-dessus, nous pouvons voir que la méthode find_all () renvoie une liste contenant un seul élément tandis que la méthode find () renvoie un seul résultat.
Une autre différence entre les méthodes find () et find_all () est -
>>> soup.find_all('h2')
[]
>>>
>>> soup.find('h2')
Si la méthode soup.find_all () ne trouve rien, elle retourne une liste vide alors que find () renvoie None.
find_parents () et find_parent ()
Contrairement aux méthodes find_all () et find () qui traversent l'arbre, en regardant les descendants de la balise, les méthodes find_parents () et find_parents () font le contraire, elles traversent l'arbre vers le haut et regardent les parents d'une balise (ou d'une chaîne).
Syntaxe
find_parents(name, attrs, string, limit, **kwargs)
find_parent(name, attrs, string, **kwargs)
>>> a_string = soup.find(string="The Godfather")
>>> a_string
'The Godfather'
>>> a_string.find_parents('a')
[<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>]
>>> a_string.find_parent('a')
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
>>> a_string.find_parent('tr')
<tr>
<td class="posterColumn">
<span data-value="2" name="rk"></span>
<span data-value="9.149038526210072" name="ir"></span>
<span data-value="6.93792E10" name="us"></span>
<span data-value="1485540" name="nv"></span>
<span data-value="-1.850961473789928" name="ur"></span>
<a href="/title/tt0068646/"> <img alt="The Godfather" height="67" src="https://m.media-amazon.com/images/M/MV5BM2MyNjYxNmUtYTAwNi00MTYxLWJmNWYtYzZlODY3ZTk3OTFlXkEyXkFqcGdeQXVyNzkwMjQ5NzM@._V1_UY67_CR1,0,45,67_AL_.jpg" width="45"/>
</a> </td>
<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>
<td class="ratingColumn imdbRating">
<strong title="9.1 based on 1,485,540 user ratings">9.1</strong>
</td>
<td class="ratingColumn">
<div class="seen-widget seen-widget-tt0068646 pending" data-titleid="tt0068646">
<div class="boundary">
<div class="popover">
<span class="delete"> </span><ol><li>1<li>2<li>3<li>4<li>5<li>6<li>7<li>8<li>9<li>10</li>0</li></li></li></li&td;</li></li></li></li></li></ol> </div>
</div>
<div class="inline">
<div class="pending"></div>
<div class="unseeable">NOT YET RELEASED</div>
<div class="unseen"> </div>
<div class="rating"></div>
<div class="seen">Seen</div>
</div>
</div>
</td>
<td class="watchlistColumn">
<div class="wlb_ribbon" data-recordmetrics="true" data-tconst="tt0068646"></div>
</td>
</tr>
>>>
>>> a_string.find_parents('td')
[<td class="titleColumn">
2.
<a href="/title/tt0068646/" title="Francis Ford Coppola (dir.), Marlon Brando, Al Pacino">The Godfather</a>
<span class="secondaryInfo">(1972)</span>
</td>]
Il existe huit autres méthodes similaires -
find_next_siblings(name, attrs, string, limit, **kwargs)
find_next_sibling(name, attrs, string, **kwargs)
find_previous_siblings(name, attrs, string, limit, **kwargs)
find_previous_sibling(name, attrs, string, **kwargs)
find_all_next(name, attrs, string, limit, **kwargs)
find_next(name, attrs, string, **kwargs)
find_all_previous(name, attrs, string, limit, **kwargs)
find_previous(name, attrs, string, **kwargs)
Où,
find_next_siblings() et find_next_sibling() Les méthodes itéreront sur tous les frères de l'élément qui viennent après celui en cours.
find_previous_siblings() et find_previous_sibling() Les méthodes itéreront sur tous les frères qui précèdent l'élément actuel.
find_all_next() et find_next() Les méthodes itéreront sur toutes les balises et chaînes qui suivent l'élément courant.
find_all_previous et find_previous() Les méthodes itéreront sur toutes les balises et chaînes qui précèdent l'élément actuel.
Sélecteurs CSS
La bibliothèque BeautifulSoup pour prendre en charge les sélecteurs CSS les plus couramment utilisés. Vous pouvez rechercher des éléments à l'aide des sélecteurs CSS à l'aide de la méthode select ().
Voici quelques exemples -
>>> soup.select('title')
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>>
>>> soup.select("p:nth-of-type(1)")
[<p>The Top Rated Movie list only includes theatrical features.</p>, <p> class="imdb-footer__copyright _2-iNNCFskmr4l2OFN2DRsf">© 1990- by IMDb.com, Inc.</p>]
>>> len(soup.select("p:nth-of-type(1)"))
2
>>> len(soup.select("a"))
609
>>> len(soup.select("p"))
2
>>> soup.select("html head title")
[<title>IMDb Top 250 - IMDb</title>, <title>IMDb Top Rated Movies</title>]
>>> soup.select("head > title")
[<title>IMDb Top 250 - IMDb</title>]
#print HTML code of the tenth li elemnet
>>> soup.select("li:nth-of-type(10)")
[<li class="subnav_item_main">
<a href="/search/title?genres=film_noir&sort=user_rating,desc&title_type=feature&num_votes=25000,">Film-Noir
</a> </li>]
L'un des aspects importants de BeautifulSoup est la recherche dans l'arborescence d'analyse et vous permet d'apporter des modifications au document Web en fonction de vos besoins. Nous pouvons apporter des modifications aux propriétés de la balise en utilisant ses attributs, tels que la méthode .name, .string ou .append (). Il vous permet d'ajouter de nouvelles balises et chaînes à une balise existante à l'aide des méthodes .new_string () et .new_tag (). Il existe également d'autres méthodes, telles que .insert (), .insert_before () ou .insert_after () pour apporter diverses modifications à votre document HTML ou XML.
Modification des noms et des attributs des balises
Une fois que vous avez créé la soupe, il est facile de faire des modifications comme renommer la balise, apporter des modifications à ses attributs, ajouter de nouveaux attributs et supprimer des attributs.
>>> soup = BeautifulSoup('<b class="bolder">Very Bold</b>')
>>> tag = soup.b
La modification et l'ajout de nouveaux attributs sont les suivants -
>>> tag.name = 'Blockquote'
>>> tag['class'] = 'Bolder'
>>> tag['id'] = 1.1
>>> tag
<Blockquote class="Bolder" id="1.1">Very Bold</Blockquote>
La suppression des attributs est la suivante -
>>> del tag['class']
>>> tag
<Blockquote id="1.1">Very Bold</Blockquote>
>>> del tag['id']
>>> tag
<Blockquote>Very Bold</Blockquote>
Modifier .string
Vous pouvez facilement modifier l'attribut .string de la balise -
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">Must for every <i>Learner>/i<</a>'
>>> Bsoup = BeautifulSoup(markup)
>>> tag = Bsoup.a
>>> tag.string = "My Favourite spot."
>>> tag
<a href="https://www.tutorialspoint.com/index.htm">My Favourite spot.</a>
D'en haut, nous pouvons voir si la balise contient une autre balise, elle et tout son contenu seront remplacés par de nouvelles données.
ajouter()
L'ajout de nouvelles données / contenus à une balise existante se fait à l'aide de la méthode tag.append (). Elle est très similaire à la méthode append () dans la liste Python.
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">Must for every <i>Learner</i></a>'
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.a.append(" Really Liked it")
>>> Bsoup
<html><body><a href="https://www.tutorialspoint.com/index.htm">Must for every <i>Learner</i> Really Liked it</a></body></html>
>>> Bsoup.a.contents
['Must for every ', <i>Learner</i>, ' Really Liked it']
NavigableString () et .new_tag ()
Si vous souhaitez ajouter une chaîne à un document, cela peut être fait facilement en utilisant le constructeur append () ou par NavigableString () -
>>> soup = BeautifulSoup("<b></b>")
>>> tag = soup.b
>>> tag.append("Start")
>>>
>>> new_string = NavigableString(" Your")
>>> tag.append(new_string)
>>> tag
<b>Start Your</b>
>>> tag.contents
['Start', ' Your']
Note: Si vous trouvez une erreur de nom lors de l'accès à la fonction NavigableString (), comme suit -
NameError: le nom 'NavigableString' n'est pas défini
Importez simplement le répertoire NavigableString du package bs4 -
>>> from bs4 import NavigableString
Nous pouvons résoudre l'erreur ci-dessus.
Vous pouvez ajouter des commentaires à vos balises existantes ou ajouter une autre sous-classe de NavigableString, appelez simplement le constructeur.
>>> from bs4 import Comment
>>> adding_comment = Comment("Always Learn something Good!")
>>> tag.append(adding_comment)
>>> tag
<b>Start Your<!--Always Learn something Good!--></b>
>>> tag.contents
['Start', ' Your', 'Always Learn something Good!']
L'ajout d'une toute nouvelle balise (sans l'ajouter à une balise existante) peut être fait en utilisant la méthode intégrée de Beautifulsoup, BeautifulSoup.new_tag () -
>>> soup = BeautifulSoup("<b></b>")
>>> Otag = soup.b
>>>
>>> Newtag = soup.new_tag("a", href="https://www.tutorialspoint.com")
>>> Otag.append(Newtag)
>>> Otag
<b><a href="https://www.tutorialspoint.com"></a></b>
Seul le premier argument, le nom de la balise, est requis.
insérer()
Similaire à la méthode .insert () sur la liste python, tag.insert () insérera un nouvel élément cependant, contrairement à tag.append (), le nouvel élément ne va pas nécessairement à la fin du contenu de son parent. Un nouvel élément peut être ajouté à n'importe quelle position.
>>> markup = '<a href="https://www.djangoproject.com/community/">Django Official website <i>Huge Community base</i></a>'
>>> soup = BeautifulSoup(markup)
>>> tag = soup.a
>>>
>>> tag.insert(1, "Love this framework ")
>>> tag
<a href="https://www.djangoproject.com/community/">Django Official website Love this framework <i>Huge Community base</i></a>
>>> tag.contents
['Django Official website ', 'Love this framework ', <i>Huge Community base</i
>]
>>>
insert_before () et insert_after ()
Pour insérer une balise ou une chaîne juste avant quelque chose dans l'arborescence d'analyse, nous utilisons insert_before () -
>>> soup = BeautifulSoup("Brave")
>>> tag = soup.new_tag("i")
>>> tag.string = "Be"
>>>
>>> soup.b.string.insert_before(tag)
>>> soup.b
<b><i>Be</i>Brave</b>
De même pour insérer une balise ou une chaîne juste après quelque chose dans l'arborescence d'analyse, utilisez insert_after ().
>>> soup.b.i.insert_after(soup.new_string(" Always "))
>>> soup.b
<b><i>Be</i> Always Brave</b>
>>> soup.b.contents
[<i>Be</i>, ' Always ', 'Brave']
clair()
Pour supprimer le contenu d'une balise, utilisez tag.clear () -
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical&lr;/i> Contents</a>'
>>> soup = BeautifulSoup(markup)
>>> tag = soup.a
>>> tag
<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical</i> Contents</a>
>>>
>>> tag.clear()
>>> tag
<a href="https://www.tutorialspoint.com/index.htm"></a>
extrait()
Pour supprimer une balise ou des chaînes de l'arborescence, utilisez PageElement.extract ().
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">For <i&gr;technical & Non-technical</i> Contents</a>'
>>> soup = BeautifulSoup(markup)
>>> a_tag = soup.a
>>>
>>> i_tag = soup.i.extract()
>>>
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">For Contents</a>
>>>
>>> i_tag
<i>technical & Non-technical</i>
>>>
>>> print(i_tag.parent)
None
décomposer()
Le tag.decompose () supprime une balise de l'arborescence et supprime tout son contenu.
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical</i> Contents</a>'
>>> soup = BeautifulSoup(markup)
>>> a_tag = soup.a
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">For <i>technical & Non-technical</i> Contents</a>
>>>
>>> soup.i.decompose()
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">For Contents</a>
>>>
Remplacer par()
Comme son nom l'indique, la fonction pageElement.replace_with () remplacera l'ancienne balise ou chaîne par la nouvelle balise ou chaîne dans l'arborescence -
>>> markup = '<a href="https://www.tutorialspoint.com/index.htm">Complete Python <i>Material</i></a>'
>>> soup = BeautifulSoup(markup)
>>> a_tag = soup.a
>>>
>>> new_tag = soup.new_tag("Official_site")
>>> new_tag.string = "https://www.python.org/"
>>> a_tag.i.replace_with(new_tag)
<i>Material</i>
>>>
>>> a_tag
<a href="https://www.tutorialspoint.com/index.htm">Complete Python <Official_site>https://www.python.org/</Official_site></a>
Dans la sortie ci-dessus, vous avez remarqué que replace_with () renvoie la balise ou la chaîne qui a été remplacée (comme «Material» dans notre cas), vous pouvez donc l'examiner ou l'ajouter à une autre partie de l'arbre.
emballage()
La pageElement.wrap () a inclus un élément dans la balise que vous spécifiez et retourne un nouveau wrapper -
>>> soup = BeautifulSoup("<p>tutorialspoint.com</p>")
>>> soup.p.string.wrap(soup.new_tag("b"))
<b>tutorialspoint.com</b>
>>>
>>> soup.p.wrap(soup.new_tag("Div"))
<Div><p><b>tutorialspoint.com</b></p></Div>
déballer()
La balise tag.unwrap () est juste l'opposé de wrap () et remplace une balise par ce qui se trouve à l'intérieur de cette balise.
>>> soup = BeautifulSoup('<a href="https://www.tutorialspoint.com/">I liked <i>tutorialspoint</i></a>')
>>> a_tag = soup.a
>>>
>>> a_tag.i.unwrap()
<i></i>
>>> a_tag
<a href="https://www.tutorialspoint.com/">I liked tutorialspoint</a>
D'en haut, vous avez remarqué que comme replace_with (), unrap () renvoie la balise qui a été remplacée.
Voici un autre exemple de unwrap () pour mieux le comprendre -
>>> soup = BeautifulSoup("<p>I <strong>AM</strong> a <i>text</i>.</p>")
>>> soup.i.unwrap()
<i></i>
>>> soup
<html><body><p>I <strong>AM</strong> a text.</p></body></html>
unwrap () est bon pour supprimer le balisage.
Tous les documents HTML ou XML sont écrits dans un encodage spécifique comme ASCII ou UTF-8. Cependant, lorsque vous chargez ce document HTML / XML dans BeautifulSoup, il a été converti en Unicode.
>>> markup = "<p>I will display £</p>"
>>> Bsoup = BeautifulSoup(markup)
>>> Bsoup.p
<p>I will display £</p>
>>> Bsoup.p.string
'I will display £'
Le comportement ci-dessus est dû au fait que BeautifulSoup utilise en interne la sous-bibliothèque appelée Unicode, Dammit pour détecter le codage d'un document, puis le convertir en Unicode.
Cependant, pas tout le temps, l'Unicode, Dammit devine correctement. Comme le document est recherché octet par octet pour deviner le codage, cela prend beaucoup de temps. Vous pouvez gagner du temps et éviter les erreurs, si vous connaissez déjà l'encodage en le passant au constructeur BeautifulSoup comme from_encoding.
Vous trouverez ci-dessous un exemple où BeautifulSoup identifie à tort, un document ISO-8859-8 comme ISO-8859-7 -
>>> markup = b"<h1>\xed\xe5\xec\xf9</h1>"
>>> soup = BeautifulSoup(markup)
>>> soup.h1
<h1>νεμω</h1>
>>> soup.original_encoding
'ISO-8859-7'
>>>
Pour résoudre le problème ci-dessus, transmettez-le à BeautifulSoup à l'aide de from_encoding -
>>> soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
>>> soup.h1
<h1>ולש </h1>
>>> soup.original_encoding
'iso-8859-8'
>>>
Une autre nouvelle fonctionnalité ajoutée à partir de BeautifulSoup 4.4.0 est, exclude_encoding. Il peut être utilisé lorsque vous ne connaissez pas le bon encodage mais que vous êtes sûr qu'Unicode, Dammit affiche un résultat incorrect.
>>> soup = BeautifulSoup(markup, exclude_encodings=["ISO-8859-7"])
Codage de sortie
La sortie d'un BeautifulSoup est un document UTF-8, quel que soit le document entré dans BeautifulSoup. Ci-dessous un document, où se trouvent les caractères polonais au format ISO-8859-2.
html_markup = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-2">
</HEAD>
<BODY>
ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
</BODY>
</HTML>
"""
>>> soup = BeautifulSoup(html_markup)
>>> print(soup.prettify())
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
</head>
<body>
ą ć ę ł ń ó ś ź ż Ą Ć Ę Ł Ń Ó Ś Ź Ż
</body>
</html>
Dans l'exemple ci-dessus, si vous remarquez, la balise <meta> a été réécrite pour refléter le document généré par BeautifulSoup est maintenant au format UTF-8.
Si vous ne voulez pas la sortie générée en UTF-8, vous pouvez affecter l'encodage souhaité dans prettify ().
>>> print(soup.prettify("latin-1"))
b'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n <head>\n <meta content="text/html; charset=latin-1" http-equiv="content-type"/>\n </head>\n <body>\n ą ć ę ł ń \xf3 ś ź ż Ą Ć Ę Ł Ń \xd3 Ś Ź Ż\n </body>\n</html>\n'
Dans l'exemple ci-dessus, nous avons encodé le document complet, cependant vous pouvez encoder, n'importe quel élément particulier de la soupe comme s'il s'agissait d'une chaîne python -
>>> soup.p.encode("latin-1")
b'<p>0My first paragraph.</p>'
>>> soup.h1.encode("latin-1")
b'<h1>My First Heading</h1>'
Tous les caractères qui ne peuvent pas être représentés dans l'encodage choisi seront convertis en références d'entités XML numériques. Voici un exemple de ce type -
>>> markup = u"<b>\N{SNOWMAN}</b>"
>>> snowman_soup = BeautifulSoup(markup)
>>> tag = snowman_soup.b
>>> print(tag.encode("utf-8"))
b'<b>\xe2\x98\x83</b>'
Si vous essayez d'encoder ce qui précède en «latin-1» ou «ascii», cela générera «☃», indiquant qu'il n'y a pas de représentation pour cela.
>>> print (tag.encode("latin-1"))
b'<b>☃</b>'
>>> print (tag.encode("ascii"))
b'<b>☃</b>'
Unicode, bon sang
Unicode, Dammit est principalement utilisé lorsque le document entrant est dans un format inconnu (principalement une langue étrangère) et que nous voulons encoder dans un format connu (Unicode) et que nous n'avons pas besoin de Beautifulsoup pour faire tout cela.
Le point de départ de tout projet BeautifulSoup est l'objet BeautifulSoup. Un objet BeautifulSoup représente le document HTML / XML d'entrée utilisé pour sa création.
Nous pouvons passer une chaîne ou un objet de type fichier pour Beautiful Soup, où les fichiers (objets) sont stockés localement dans notre machine ou sur une page Web.
Les objets BeautifulSoup les plus courants sont -
- Tag
- NavigableString
- BeautifulSoup
- Comment
Comparaison d'objets pour l'égalité
Selon la belle soupe, deux objets de chaîne ou de balise navigables sont égaux s'ils représentent le même balisage HTML / XML.
Voyons maintenant l'exemple ci-dessous, où les deux balises <b> sont traitées comme égales, même si elles vivent dans des parties différentes de l'arborescence d'objets, car elles ressemblent toutes les deux à «<b> Java </b>».
>>> markup = "<p>Learn Python and <b>Java</b> and advanced <b>Java</b>! from Tutorialspoint</p>"
>>> soup = BeautifulSoup(markup, "html.parser")
>>> first_b, second_b = soup.find_all('b')
>>> print(first_b == second_b)
True
>>> print(first_b.previous_element == second_b.previous_element)
False
Cependant, pour vérifier si les deux variables font référence aux mêmes objets, vous pouvez utiliser ce qui suit:
>>> print(first_b is second_b)
False
Copie de beaux objets de soupe
Pour créer une copie de n'importe quelle balise ou NavigableString, utilisez la fonction copy.copy (), comme ci-dessous -
>>> import copy
>>> p_copy = copy.copy(soup.p)
>>> print(p_copy)
<p>Learn Python and <b>Java</b> and advanced <b>Java</b>! from Tutorialspoint</p>
>>>
Bien que les deux copies (originale et copiée) contiennent le même balisage, les deux ne représentent pas le même objet -
>>> print(soup.p == p_copy)
True
>>>
>>> print(soup.p is p_copy)
False
>>>
La seule vraie différence est que la copie est complètement détachée de l'arborescence d'objets originale de Beautiful Soup, comme si extract () avait été appelé dessus.
>>> print(p_copy.parent)
None
Le comportement ci-dessus est dû à deux objets de balise différents qui ne peuvent pas occuper le même espace en même temps.
Il existe plusieurs situations dans lesquelles vous souhaitez extraire des types d'informations spécifiques (uniquement les balises <a>) à l'aide de Beautifulsoup4. La classe SoupStrainer de Beautifulsoup vous permet d'analyser uniquement une partie spécifique d'un document entrant.
Une façon est de créer un SoupStrainer et de le transmettre au constructeur Beautifulsoup4 en tant qu'argument parse_only.
Soupe Passoire
Un SoupStrainer indique à BeautifulSoup quelles parties sont extraites et l'arborescence d'analyse se compose uniquement de ces éléments. Si vous limitez vos informations requises à une partie spécifique du code HTML, cela accélérera votre résultat de recherche.
product = SoupStrainer('div',{'id': 'products_list'})
soup = BeautifulSoup(html,parse_only=product)
Les lignes de code ci-dessus analyseront uniquement les titres d'un site de produit, qui peuvent se trouver à l'intérieur d'un champ de balise.
De même, comme ci-dessus, nous pouvons utiliser d'autres objets soupStrainer pour analyser des informations spécifiques à partir d'une balise HTML. Voici quelques exemples -
from bs4 import BeautifulSoup, SoupStrainer
#Only "a" tags
only_a_tags = SoupStrainer("a")
#Will parse only the below mentioned "ids".
parse_only = SoupStrainer(id=["first", "third", "my_unique_id"])
soup = BeautifulSoup(my_document, "html.parser", parse_only=parse_only)
#parse only where string length is less than 10
def is_short_string(string):
return len(string) < 10
only_short_strings =SoupStrainer(string=is_short_string)
La gestion des erreurs
Il existe deux principaux types d'erreurs qui doivent être traitées dans BeautifulSoup. Ces deux erreurs ne proviennent pas de votre script mais de la structure de l'extrait de code car l'API BeautifulSoup génère une erreur.
Les deux principales erreurs sont les suivantes -
AttributeError
Cela se produit lorsque la notation par points ne trouve pas de balise sœur dans la balise HTML actuelle. Par exemple, vous avez peut-être rencontré cette erreur, en raison de l'absence de «balise d'ancrage», cost-key générera une erreur lors de sa traversée et nécessitera une balise d'ancrage.
KeyError
Cette erreur se produit si l'attribut de balise HTML requis est manquant. Par exemple, si nous n'avons pas d'attribut data-pid dans un extrait de code, la clé pid lancera une erreur de clé.
Pour éviter les deux erreurs énumérées ci-dessus lors de l'analyse d'un résultat, ce résultat sera contourné pour s'assurer qu'un extrait de code mal formé n'est pas inséré dans les bases de données -
except(AttributeError, KeyError) as er:
pass
diagnostiquer()
Chaque fois que nous rencontrons des difficultés pour comprendre ce que fait BeautifulSoup sur notre document ou HTML, transmettez-le simplement à la fonction diagnose (). En passant le fichier de document à la fonction diagnostiquer (), nous pouvons montrer comment la liste des différents analyseurs gère le document.
Vous trouverez ci-dessous un exemple pour démontrer l'utilisation de la fonction diagnose () -
from bs4.diagnose import diagnose
with open("20 Books.html",encoding="utf8") as fp:
data = fp.read()
diagnose(data)
Production
Erreur d'analyse
Il existe deux principaux types d'erreurs d'analyse. Vous pouvez obtenir une exception comme HTMLParseError, lorsque vous transmettez votre document à BeautifulSoup. Vous pouvez également obtenir un résultat inattendu, où l'arborescence d'analyse BeautifulSoup est très différente du résultat attendu du document d'analyse.
Aucune des erreurs d'analyse n'est due à BeautifulSoup. C'est à cause de l'analyseur externe que nous utilisons (html5lib, lxml) puisque BeautifulSoup ne contient aucun code d'analyseur. Une façon de résoudre l'erreur d'analyse ci-dessus consiste à utiliser un autre analyseur.
from HTMLParser import HTMLParser
try:
from HTMLParser import HTMLParseError
except ImportError, e:
# From python 3.5, HTMLParseError is removed. Since it can never be
# thrown in 3.5, we can just define our own class as a placeholder.
class HTMLParseError(Exception):
pass
L'analyseur HTML intégré à Python provoque deux erreurs d'analyse les plus courantes, HTMLParser.HTMLParserError: balise de début malformée et HTMLParser.HTMLParserError: balise de fin incorrecte et pour résoudre cela, il faut utiliser un autre analyseur principalement: lxml ou html5lib.
Un autre type courant de comportement inattendu est que vous ne trouvez pas de balise dont vous savez qu'elle se trouve dans le document. Cependant, lorsque vous exécutez find_all () renvoie [] ou find () renvoie None.
Cela peut être dû au fait que l'analyseur HTML intégré à python ignore parfois les balises qu'il ne comprend pas.
Erreur de l'analyseur XML
Par défaut, le package BeautifulSoup analyse les documents au format HTML, cependant, il est très facile à utiliser et gère le XML mal formé de manière très élégante en utilisant beautifulsoup4.
Pour analyser le document au format XML, vous devez disposer d'un analyseur lxml et il vous suffit de passer le «xml» comme deuxième argument au constructeur Beautifulsoup -
soup = BeautifulSoup(markup, "lxml-xml")
ou
soup = BeautifulSoup(markup, "xml")
Une erreur d'analyse XML courante est -
AttributeError: 'NoneType' object has no attribute 'attrib'
Cela peut se produire dans le cas où un élément manque ou n'est pas défini lors de l'utilisation de la fonction find () ou findall ().
Autres erreurs d'analyse
Vous trouverez ci-dessous quelques-unes des autres erreurs d'analyse que nous allons discuter dans cette section -
Problème environnemental
Outre les erreurs d'analyse mentionnées ci-dessus, vous pouvez rencontrer d'autres problèmes d'analyse tels que des problèmes environnementaux où votre script peut fonctionner dans un système d'exploitation mais pas dans un autre système d'exploitation ou peut fonctionner dans un environnement virtuel mais pas dans un autre environnement virtuel ou peut ne pas fonctionner en dehors de l'environnement virtuel. Tous ces problèmes peuvent être dus au fait que les deux environnements ont des bibliothèques d'analyseurs différentes disponibles.
Il est recommandé de connaître ou de vérifier votre analyseur par défaut dans votre environnement de travail actuel. Vous pouvez vérifier l'analyseur par défaut actuel disponible pour l'environnement de travail actuel ou bien transmettre explicitement la bibliothèque d'analyseur requise en tant que seconds arguments au constructeur BeautifulSoup.
Insensible à la casse
Comme les balises et attributs HTML sont insensibles à la casse, les trois analyseurs HTML convertissent les noms de balises et d'attributs en minuscules. Cependant, si vous souhaitez conserver des balises et des attributs en majuscules ou en majuscules, il est préférable d'analyser le document au format XML.
UnicodeEncodeError
Examinons le segment de code ci-dessous -
soup = BeautifulSoup(response, "html.parser")
print (soup)
Production
UnicodeEncodeError: 'charmap' codec can't encode character '\u011f'
Le problème ci-dessus peut être dû à deux situations principales. Vous essayez peut-être d'imprimer un caractère Unicode que votre console ne sait pas afficher. Deuxièmement, vous essayez d'écrire dans un fichier et vous passez un caractère Unicode qui n'est pas pris en charge par votre encodage par défaut.
Une façon de résoudre le problème ci-dessus consiste à encoder le texte / caractère de réponse avant de faire la soupe pour obtenir le résultat souhaité, comme suit -
responseTxt = response.text.encode('UTF-8')
KeyError: [attr]
Cela est dû à l'accès à la balise ['attr'] lorsque la balise en question ne définit pas l'attribut attr. Les erreurs les plus courantes sont: «KeyError: 'href'» et «KeyError: 'class'». Utilisez tag.get ('attr') si vous n'êtes pas sûr que attr est défini.
for item in soup.fetch('a'):
try:
if (item['href'].startswith('/') or "tutorialspoint" in item['href']):
(...)
except KeyError:
pass # or some other fallback action
AttributeError
Vous pouvez rencontrer AttributeError comme suit -
AttributeError: 'list' object has no attribute 'find_all'
L'erreur ci-dessus se produit principalement parce que vous vous attendiez à ce que find_all () renvoie une seule balise ou chaîne. Cependant, soup.find_all renvoie une liste d'éléments python.
Tout ce que vous avez à faire est de parcourir la liste et de récupérer les données de ces éléments.