Salutations ! Je m'appelle Max, un développeur Python d'Ukraine, un développeur possédant une expertise en matière de web scraping, d'analyse et de traitement de données.
Mon parcours dans le web scraping a commencé en 2016 lorsque je résolvais des défis de génération de leads pour une petite entreprise. Au départ, j'utilisais des solutions prêtes à l'emploi telles que Import.io et Kimono Labs. Cependant, j’ai rapidement rencontré des limitations telles que des blocages, une extraction de données inexacte et des problèmes de performances. Cela m'a amené à apprendre Python. C’était l’époque glorieuse où les requêtes et lxml/beautifulsoup suffisaient pour extraire les données de la plupart des sites Web. Et si tu savais travailler avec les fils, tu étais déjà un expert respecté :)
Un des membres de notre communauté a écrit ce blog en guise de contribution au blog Crawlee. Si vous souhaitez contribuer à des blogs comme ceux-ci sur Crawlee Blog, veuillez nous contacter sur notre chaîne Discord.
En tant qu'indépendant, j'ai construit de petites solutions et de grands systèmes d'exploration de données complexes pour des produits au fil des ans.
Aujourd'hui, je souhaite discuter des réalités du web scraping avec Python en 2024. Nous examinerons les erreurs que je vois parfois et les problèmes que vous rencontrerez et proposerons des solutions à certains d'entre eux.
Commençons.
Prenez simplement les demandes et la belle soupe et commencez à gagner beaucoup d'argent...
Non, ce n'est pas ce genre d'article.
Oui, cela peut surprendre. Mais j'ai vu ce message de clients et de développeurs il y a six ans, il y a quatre ans et en 2024. J'ai lu un article sur Reddit il y a quelques mois à peine sur ce problème.
Regardons un exemple de code simple. Cela fonctionnera pour les requêtes, httpx et aiohttp avec une installation propre et sans extensions.
import httpx url = 'https://www.wayfair.com/' headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br, zstd", "Connection": "keep-alive", } response = httpx.get(url, headers=headers) print(response.content[:10])
Le résultat de l'impression sera similaire à :
b'\x83\x0c\x00\x00\xc4\r\x8e4\x82\x8a'
Ce n'est pas une erreur - c'est une réponse du serveur parfaitement valide. C'est codé d'une manière ou d'une autre.
La réponse réside dans l'en-tête Accept-Encoding. Dans l'exemple ci-dessus, je viens de le copier depuis mon navigateur, il répertorie donc toutes les méthodes de compression prises en charge par mon navigateur : "gzip, deflate, br, zstd". Le backend Wayfair prend en charge la compression avec "br", qui est Brotli, et l'utilise comme méthode la plus efficace.
Cela peut se produire si aucune des bibliothèques répertoriées ci-dessus n'a de dépendance Brotli parmi ses dépendances standard. Cependant, ils prennent tous en charge la décompression à partir de ce format si Brotli est déjà installé.
Il suffit donc d'installer la bibliothèque appropriée :
pip install Brotli
Cela vous permettra d'obtenir le résultat de l'impression :
b'<!DOCTYPE '
Vous pouvez obtenir le même résultat pour aiohttp et httpx en faisant l'installation avec les extensions :
pip install aiohttp[speedups] pip install httpx[brotli]
Au fait, l'ajout de la dépendance brotli a été ma première contribution à crawlee-python. Ils utilisent httpx comme client HTTP de base.
Vous avez peut-être également remarqué qu'un nouveau format de compression de données pris en charge, zstd, est apparu il y a quelque temps. Je n'ai pas encore vu de backends qui l'utilisent, mais httpx prendra en charge la décompression dans les versions supérieures à 0.28.0. Je l'utilise déjà pour compresser les dumps de réponses du serveur dans mes projets ; il fait preuve d'une efficacité incroyable dans les solutions asynchrones avec des fichiers aio.
La solution la plus courante à cette situation que j'ai vue consiste pour les développeurs à cesser simplement d'utiliser l'en-tête Accept-Encoding, obtenant ainsi une réponse non compressée du serveur. Pourquoi est-ce mauvais ? La page principale de Wayfair prend environ 1 mégaoctet non compressé et environ 0,165 mégaoctet compressé.
Par conséquent, en l'absence de cet en-tête :
Mais je pense que le problème est un peu plus profond que cela. De nombreux développeurs de web scraping ne comprennent tout simplement pas à quoi servent les en-têtes qu'ils utilisent. Donc, si cela s'applique à vous, lorsque vous travaillez sur votre prochain projet, lisez ces éléments ; ils pourraient vous surprendre.
Oui, c'est vrai. 2023 nous a apporté non seulement des modèles de langage étendus comme ChatGPT, mais également une protection Cloudflare améliorée.
Ceux qui parcourent le Web depuis longtemps pourraient dire : « Eh bien, nous avons déjà traité avec DataDome, PerimeterX, InCapsula, etc. »
Mais Cloudflare a changé les règles du jeu. Il s'agit de l'un des plus grands fournisseurs de CDN au monde, desservant un grand nombre de sites. Ses services sont donc accessibles à de nombreux sites avec une barrière à l’entrée assez faible. Cela le rend radicalement différent des technologies mentionnées précédemment, qui ont été mises en œuvre à dessein lorsqu'ils voulaient protéger le site du scraping.
Cloudflare est la raison pour laquelle, lorsque vous commencez à lire un autre cours sur "Comment faire du web scraping à l'aide de requêtes et de beautifulsoup", vous pouvez le fermer immédiatement. Parce qu'il y a de grandes chances que ce que vous apprenez ne fonctionnera tout simplement sur aucun site Web « décent ».
Regardons un autre exemple de code simple :
from httpx import Client client = Client(http2=True) url = 'https://www.g2.com/' headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br, zstd", "Connection": "keep-alive", } response = client.get(url, headers=headers) print(response)
Bien sûr, la réponse serait 403.
Et si on utilisait curl ?
curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' -s -o /dev/null -w "%{http_code}\n"
Aussi 403.
Pourquoi cela se produit-il ?
Étant donné que Cloudflare utilise les empreintes digitales TLS de nombreux clients HTTP populaires parmi les développeurs, les administrateurs de site peuvent également personnaliser la manière dont Cloudflare bloque les clients de manière agressive en fonction de ces empreintes digitales.
Pour curl, nous pouvons le résoudre comme ceci :
curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' --tlsv1.3 -s -o /dev/null -w "%{http_code}\n"
You might expect me to write here an equally elegant solution for httpx, but no. About six months ago, you could do the "dirty trick" and change the basic httpcore parameters that it passes to h2, which are responsible for the HTTP2 handshake. But now, as I'm writing this article, that doesn't work anymore.
There are different approaches to getting around this. But let's solve it by manipulating TLS.
The bad news is that all the Python clients I know of use the ssl library to handle TLS. And it doesn't give you the ability to manipulate TLS subtly.
The good news is that the Python community is great and implements solutions that exist in other programming languages.
This Python wrapper around the Golang library provides an API similar to requests.
pip install tls-client
from tls_client import Session client = Session(client_identifier="firefox_120") url = 'https://www.g2.com/' headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br, zstd", "Connection": "keep-alive", } response = client.get(url, headers=headers) print(response)
The tls_client supports TLS presets for popular browsers, the relevance of which is maintained by developers. To use this, you must pass the necessary client_identifier. However, the library also allows for subtle manual manipulation of TLS.
This wrapper around the C library patches curl and provides an API similar to requests.
pip install curl_cffi
from curl_cffi import requests url = 'https://www.g2.com/' headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br, zstd", "Connection": "keep-alive", } response = requests.get(url, headers=headers, impersonate="chrome124") print(response)
curl_cffi also provides TLS presets for some browsers, which are specified via the impersonate parameter. It also provides options for subtle manual manipulation of TLS.
I think someone just said, "They're literally doing the same thing." That's right, and they're both still very raw.
Let's do some simple comparisons:
Feature | tls_client | curl_cffi |
---|---|---|
TLS preset | + | + |
TLS manual | + | + |
async support | - | + |
big company support | - | + |
number of contributors | - | + |
Évidemment, curl_cffi gagne dans cette comparaison. Mais en tant qu'utilisateur actif, je dois dire qu'il y a parfois des erreurs assez étranges que je ne sais tout simplement pas comment gérer. Et soyons honnêtes, jusqu’à présent, ils sont tous les deux plutôt crus.
Je pense que nous verrons bientôt d'autres bibliothèques qui résoudront ce problème.
On pourrait se demander : qu’en est-il de Scrapy ? Je vais être honnête : je ne suis pas vraiment au courant de leurs mises à jour. Mais je n’ai pas entendu parler de Zyte faisant quoi que ce soit pour contourner les empreintes digitales TLS. Ainsi, Scrapy sera également bloqué dès la sortie de la boîte, mais rien ne vous empêche d'utiliser curl_cffi dans votre Scrapy Spider.
Oui, nous devons parfois utiliser des navigateurs sans tête. Même si je vais être honnête, de mon point de vue, ils sont utilisés trop souvent même lorsqu'ils ne sont clairement pas nécessaires.
Même dans une situation sans tête, les gens de Cloudflare ont réussi à rendre la vie difficile au web scraper moyen en créant un monstre appelé Cloudflare Turnstile.
Pour tester différents outils, vous pouvez utiliser cette page de démonstration.
Pour tester rapidement si une bibliothèque fonctionne avec le navigateur, vous devez commencer par vérifier le mode non-headless habituel. Vous n'avez même pas besoin d'utiliser l'automatisation ; ouvrez simplement le site en utilisant la bibliothèque souhaitée et agissez manuellement.
Quelles bibliothèques valent la peine d'être consultées pour cela ?
Il sera bloqué et ne vous permettra pas de résoudre le captcha.
Playwright est une excellente bibliothèque pour l'automatisation du navigateur. Cependant, les développeurs déclarent explicitement qu'ils n'envisagent pas de le développer en tant qu'outil de web scraping.
Et je n'ai entendu parler d'aucun projet Python qui résolve efficacement ce problème.
Il sera bloqué et ne vous permettra pas de résoudre le captcha.
Il s'agit d'une bibliothèque assez courante pour travailler avec des navigateurs sans tête en Python, et dans certains cas, elle permet de contourner Cloudflare Turnstile. Mais sur le site cible, il est bloqué. De plus, dans mes projets, j'ai rencontré au moins deux autres cas où Cloudflare bloquait undetected_chromedriver.
En général, undetected_chromedriver est une bonne bibliothèque pour vos projets, d'autant plus qu'elle utilise du bon vieux Selenium sous le capot.
Il permet de dépasser le captcha après avoir cliqué.
Je ne sais pas comment ses développeurs ont réussi cela, mais ça marche. Sa principale caractéristique est qu’il a été développé spécifiquement pour le web scraping. Il dispose également d'une bibliothèque de niveau supérieur avec laquelle travailler - botasaurus.
En revanche, jusqu'à présent, c'est assez brut, et botasaurus-driver n'a pas de documentation et a une API plutôt difficile avec laquelle travailler.
Pour résumer, il est fort probable que votre bibliothèque principale pour la navigation sans tête soit undetected_chromedriver. Mais dans certains cas particulièrement difficiles, vous devrez peut-être utiliser le botasaurus.
Les frameworks de haut niveau sont conçus pour accélérer et faciliter le développement en nous permettant de nous concentrer sur la logique métier, même si nous en payons souvent le prix en termes de flexibilité et de contrôle.
Alors, quels sont les frameworks du web scraping en 2024 ?
Il est impossible de parler des frameworks de web scraping Python sans mentionner Scrapy. Scrapinghub (maintenant Zyte) l'a publié pour la première fois en 2008. Depuis 16 ans, il a été développé comme une bibliothèque open source sur laquelle les sociétés de développement ont construit leurs solutions commerciales.
En parlant des avantages de Scrapy, vous pourriez écrire un article séparé. Mais je soulignerai les deux :
Mais quels sont les inconvénients ?
Ces dernières années, Zyte s'est davantage concentré sur le développement de sa propre plateforme. Scrapy n'obtient principalement que des correctifs.
Ainsi, Scrapy est une solution efficace et éprouvée pour les sites qui ne sont pas protégés contre le web scraping. Vous devrez développer et ajouter les solutions nécessaires au cadre afin de contourner les mesures anti-grattage.
Un nouveau framework pour le web scraping utilisant l'automatisation du navigateur, construit sur le pilote botasaurus. L'engagement initial a été effectué le 9 mai 2023.
Commençons par ses avantages :
Les inconvénients incluent :
Il s'agit d'un bon framework pour créer rapidement un scraper Web basé sur l'automatisation du navigateur. Il manque de flexibilité et de prise en charge des clients HTTP, ce qui est crucial pour les utilisateurs comme moi.
Un nouveau framework pour le web scraping dans l'écosystème Python. L'engagement initial a été pris le 10 janvier 2024, avec une sortie dans l'espace médiatique le 5 juillet 2024.
Crawlee couvre votre exploration et votre grattage de bout en bout et vous aide à construire des grattoirs fiables. Rapide.
? Crawlee pour Python est ouvert aux premiers utilisateurs !
Vos robots apparaîtront presque comme des humains et passeront sous le radar des protections modernes contre les robots, même avec la configuration par défaut. Crawlee vous offre les outils nécessaires pour explorer le Web à la recherche de liens, récupérer des données et les stocker de manière persistante dans des formats lisibles par machine, sans avoir à vous soucier des détails techniques. Et grâce aux riches options de configuration, vous pouvez modifier presque tous les aspects de Crawlee pour l'adapter aux besoins de votre projet si les paramètres par défaut ne suffisent pas.
? Voir la documentation complète, les guides et les exemples sur le site Web du projet Crawlee ?
Nous avons également une implémentation TypeScript de Crawlee, que vous pouvez explorer et utiliser pour vos projets. Visitez notre référentiel GitHub pour plus d'informations Crawlee pour JS/TS sur GitHub.
Nous…
Développé par Apify, il s'agit d'une adaptation Python de leur célèbre framework JS crawlee, publié pour la première fois le 9 juillet 2019.
Comme il s'agit d'une solution totalement nouvelle sur le marché, elle est désormais en phase active de conception et de développement. La communauté participe également activement à son développement. On voit donc que l’utilisation de curl_cffi est déjà en discussion. La possibilité de créer leur propre client basé sur Rust a déjà été évoquée. J'espère que l'entreprise n'abandonnera pas l'idée.
De l'équipe Crawlee :
"Oui, c'est sûr que nous continuerons à améliorer Crawlee pour Python dans les années à venir."
Comme personnellement, j'aimerais voir un client HTTP pour Python développé et maintenu par une grande entreprise. Et Rust se présente très bien comme langage de bibliothèque pour Python. Souvenons-nous au moins de Ruff et Pydantic v2.
Avantages :
Le framework a été développé par une entreprise établie sur le marché du web scraping, qui possède une expertise bien développée dans ce domaine.
Par ailleurs, il a une assez bonne architecture modulaire. Si les développeurs introduisent la possibilité de basculer entre plusieurs clients HTTP, nous obtiendrons un framework assez flexible qui nous permettra de changer facilement les technologies utilisées, avec une simple implémentation de la part de l'équipe de développement.
Déficiences :
Je crois que le succès de crawlee-python dépend principalement de la communauté. En raison du petit nombre de tutoriels, il ne convient pas aux débutants. Cependant, les développeurs expérimentés peuvent décider de l'essayer à la place de Scrapy.
À long terme, cela pourrait s'avérer être une meilleure solution que Scrapy et Botasaurus. Il fournit déjà des outils flexibles pour travailler avec des clients HTTP, automatiser les navigateurs dès le départ et basculer rapidement entre eux. Cependant, il manque d'outils pour contourner les protections contre le scraping, et leur mise en œuvre à l'avenir pourrait être le facteur décisif dans le choix d'un framework pour vous.
Si vous avez lu jusqu'ici, je suppose que vous l'avez trouvé intéressant et peut-être même utile :)
Le secteur évolue et offre de nouveaux défis, et si vous êtes professionnellement impliqué dans le web scraping, vous devrez garder un œil attentif sur la situation. Dans un autre domaine, vous resteriez un développeur qui fabrique des produits en utilisant des technologies obsolètes. Mais dans le web scraping moderne, vous devenez un développeur qui crée des web scrapers qui ne fonctionnent tout simplement pas.
N'oubliez pas non plus que vous faites partie de la communauté Python plus large et que vos connaissances peuvent être utiles pour développer des outils qui font bouger les choses pour nous tous. Comme vous pouvez le constater, la plupart des outils dont vous avez besoin sont en train d'être construits littéralement.
Je serai ravie de lire vos commentaires. Aussi, si vous avez besoin d'un expert en web scraping ou si vous souhaitez simplement discuter de l'article, vous pouvez me trouver sur les plateformes suivantes : Github, Linkedin, Apify, Upwork, Contra.
Merci de votre attention :)
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!