


Résolvez le problème de la structure HTML incohérente dans le grattage Web: IBM Document Site Web Analysis
Défis de la structure HTML incohérente dans le grattage Web
Lors de la grattage Web, les développeurs rencontrent souvent un problème difficile: la structure HTML renvoyée par la même URL à différents moments ou dans des conditions de demande différentes peut être différente. Cela peut être causé par diverses raisons, telles que:
- Chargement de contenu dynamique: les sites Web modernes utilisent généralement JavaScript pour charger le contenu dynamiquement. Si le Crawler ne parvient pas à exécuter correctement JavaScript, il peut être possible d'obtenir le squelette HTML incomplet initial.
- Test A / B ou contenu personnalisé: le site Web peut afficher différentes versions de pages à différents utilisateurs, ou fournir du contenu personnalisé en fonction de l'emplacement géographique des utilisateurs, de l'équipement et d'autres informations.
- Détection d'agent utilisateur: le site Web peut déterminer si la demande est un navigateur ou un robot en fonction de l'agent utilisateur dans l'en-tête de demande, renvoyant ainsi un contenu HTML différents, et même renvoyant directement une page d'erreur ou une page simplifiée.
- Rendu côté serveur (SSR) et rendu côté client (RSE): certaines pages peuvent être partiellement rendues par le serveur et partiellement rendues par le client, ce qui entraîne des différences dans la structure DOM de la première demande et de la première demande.
- Erreur ou redirection: lorsque l'URL d'origine échoue ou est redirigea, une page HTML contenant le message d'erreur peut être renvoyée au lieu du contenu attendu.
Dans le cas du site Web du document IBM mentionné ci-dessus, deux structures HTML complètement différentes ont été observées: l'une est la structure attendue contenant les données tabulaires complètes, et l'autre contient un grand nombre de variables JavaScript telles que Error.Sorrytext, qui est évidemment une erreur ou une page alternative. Cela indique que le site Web peut renvoyer une réponse différente en fonction de certaines caractéristiques de la demande, ou lorsque un contenu spécifique ne peut être trouvé.
Identifier et utiliser les sources de données API
Une stratégie plus fiable face à des structures HTML instables est d'essayer d'identifier les API sous-jacentes que le site Web utilise pour charger des données. De nombreux sites Web modernes, en particulier ceux qui chargent le contenu dynamiquement, obtiennent généralement des données via des API internes, puis rendent ces données sur le client à l'aide de JavaScript. Les demandes directes à ces points de terminaison API conduisent souvent à des données JSON ou XML plus stables et structurées, ou même des fragments HTML qui contiennent les données cibles.
Pour trouver ces points de terminaison API, vous devez généralement utiliser l'onglet réseau des outils de développeur de navigateur tels que Chrome Devtools ou Firefox Developer Tools. Lors du chargement de la page cible, toutes les demandes XHR / Fetch émises sont surveillées et un appel API qui renvoie les données requis peut généralement être trouvé.
Dans le cas du site Web de documentation IBM, en analysant son processus de demande, il peut être constaté qu'il a d'abord accédé à une URL régulière, et la page fournira alors un indice de "OldUrl": "(. *?)". Cette OldUrl pointe en fait un point de terminaison API interne qui peut renvoyer directement les extraits HTML contenant des données tabulaires.
Solution: demandes asynchrones et appels API
Pour résoudre le problème de la structure HTML incohérente, nous pouvons prendre les mesures suivantes:
- Simuler le comportement du navigateur: utilisez autant que possible un en-tête de demande utilisateur réel pour simuler le comportement du navigateur, en évitant le site Web reconnue comme un robot et un contenu d'exception.
- Première demande pour obtenir un indice API: lancez une demande de GET à l'URL d'origine, analysez son contenu pour extraire l'OldUrl pointant vers l'API de données réelle.
- Construisez les demandes de l'API: utilisez l'OldUrl extrait pour construire l'URL de demande d'API correcte et ajoutez les paramètres nécessaires (tels que parsebody = true et lang = en), qui sont généralement nécessaires pour que l'API fonctionne correctement.
- Initier les données de la demande d'API et d'analyse: lancez une demande au point de terminaison de l'API et obtenez sa réponse. Étant donné que l'API renvoie généralement des données plus propres et plus structurées (ou contient des extraits HTML cibles), nous pouvons utiliser directement des outils tels que pandas.read_html () pour l'analyse efficace.
- Traitement asynchrone: pour des scénarios où un grand nombre de pages sont nécessaires, en utilisant un client HTTP asynchrone (comme HTTPX) avec un temps d'exécution asynchrone (comme Trio ou Asyncio) peut améliorer considérablement l'efficacité de la rampe.
Voici un exemple de code Python qui met en œuvre cette stratégie:
Importer httpx # asynchrone http client Import trio # asynchrone runtime importer re # module d'expression régulière Importer des pandas en tant que pd # bibliothèque de traitement de données # définir les en-têtes de demande, simulez les en-têtes de navigateur = {{ «User-Agent»: «Mozilla / 5.0 (Windows NT 10.0; Win64; x64; RV: 109.0) Gecko / 20100101 Firefox / 113,0» } async def fetch_table_data (identifiant: str): "" " Fonction asynchrone: obtenir des données de table basées sur l'identifiant "" " Async avec httpx.asyncclient (en-têtes = en-têtes, base_url = 'https: //www.ibm.com/docs') en tant que client: # 1. Construisez les paramètres de l'URL d'origine initial_params = { 'Topic': f'tables- {identifiant} '# Utilisez l'identifiant entrant} # 2. Faites la première demande à l'URL d'origine pour obtenir le HTML contenant les indices API # Remarque: Ici, on suppose que l'identifiant finira par mapper sur un sujet comme T-AccessDateval # Si la structure URL de la question d'origine est fixée, telle que "EN / IMDM / 12.0? Topic = T-ACCESSDATEVAL" # Alors initial_params ['topic'] devrait être directement «t-accessDateval» ou une valeur fixe similaire # ici, pour démontrer l'universalité, nous utilisons f'tables- {identifier} ' # L'URL de la question initiale est "https://www.ibm.com/docs/en/imdm/12.0?topic=t-accessDateval" # Le chemin correspondant est «EN / IMDM / 12.0», et le sujet est «t-AccessDateval» # Ainsi, le chemin et les paramètres ici doivent être ajustés en fonction de la situation réelle # Supposons que l'identificateur est déjà 'T-ACCESSDATEVAL', initial_response = attendre client.get ('en / imdm / 12.0', params = {'topic': identifier}) # 3. Extraire «OldUrl» du texte de réponse en utilisant des expressions régulières # 'OldUrl' pointe généralement vers un point de terminaison de l'API interne Match = re.search (r '"oldUrl": "(. *?)"', initial_response.text) Sinon correspondant: print (f "OldUrl de {identifiant} ne peut pas être trouvé.") return pd.dataframe () # return vide dataframe old_url_path = match.group (1) # 4. Construisez le chemin URL de la demande d'API # Le chemin API est généralement 'API / V1 / Content /' plus l'ancien OldUrl extrait api_url_path = "api / v1 / contenu /" old_url_path # 5. Définissez les paramètres de la demande d'API API_PARAMS = { 'PARSEBOBY': 'true', # Assurez-vous que l'API renvoie le contenu analysé 'Lang': 'en' # Spécifiez la langue} # 6. Initiez une demande GET au point de terminaison API api_response = attendre client.get (API_URL_PATH, params = API_PARAMS) # 7. Utilisez pandas.read_html pour analyser directement les données de la table dans la réponse de l'API # attrs = {'class': 'defaultStyle'} pour correspondre avec précision à la table cible essai: # API_RESPONSE.Content contient des fragments HTML, Pandas peut directement analyser DataFrames = Pd.read_html (API_RESPONSE.Content, attrs = {'class': 'defaultStyle'}) Si dataframes: df = dataframes [0] # Vous pouvez ajouter des informations supplémentaires au besoin, comme l'identifiant d'origine df.insert (0, "source_identifier", identifiant) retourner df autre: print (f "Impossible de trouver le tableau de la réponse de l'API de {identifiant}.") return pd.dataframe () sauf Value Enerror comme e: print (f "Erreur analysant le tableau HTML de {identifiant}: {e}") return pd.dataframe () asynchrone def main (): # Supposons 'identificateurs.csv' contient une colonne de données nommées 'identificateur' # par exemple: identifiant # T-AccessDateval # t-another table df_identifiers = pd.read_csv ('identificateurs.csv') all_dfs = [] # Traverse tous les identifiants et obtenez des données en même temps asynchrones avec trio.taskgroup () en tant que TG: Pour index, ligne dans df_identifiers.ITERROWS (): identifier = row ['identificateur'] tg.start_soon (Lambda id = identificateur: all_dfs.append (trio.run (fetch_table_data, id))) # enveloppé comme un appel synchrone pour ajouter à la liste # en fait, trio.run (fetch_table_data, id) est un appel de blocage, ce qui doit être ajusté à Asynchrun Suit: # task_result = attendre fetch_table_data (identifiant) # all_dfs.append (task_result) # Ou mieux, utilisez tg.start_soon pour exécuter des tâches en parallèle et collecter les résultats # puisque trio.run ne peut pas être appelé en interne dans un autre trio.run, nous devons ajuster la façon de collecter les résultats # pour simplifier, nous démontrerons d'abord la sérialisation. Si un parallèle est requis, nous pouvons construire une liste attendue. # Ou laissez fetch_table_data renvoyez un futur / différé, puis attendez dans le groupe de tâches # pour ce didacticiel, nous adoptons d'abord une méthode hybride parallèle / série simplifiée, ou l'appelons dans le principal moyen de collecte parallèle en série # plus directe: # tasks = [tg.start_soon (fetch_table_data, identifiant) pour l'identifiant dans df_identifiers ['identificateur']]] # Ensuite, un mécanisme est nécessaire pour collecter les résultats de ces tâches. # Pour la simplicité du tutoriel, nous afficherons d'abord une structure série / pseudo-parallèle qui peut être exécutée. # True Parallel Collection nécessite des modèles de groupes de tâches plus complexes, tels que l'utilisation de verrous Trio.Queue ou de liste partagée. # Pour éviter la complexité, nous appelons directement en série ici, ou utilisons une liste asynchrone simple pour collecter df = attendre fetch_table_data (identifiant) Si ce n'est pas df.empty: all_dfs.append (df) Si all_dfs: combinée_df = pd.concat (all_dfs, ignore_index = true) Imprimer (combiné_df) combinée_df.to_csv ('combinée_table_data_api.csv', index = false) autre: imprimer ("Aucune donnée n'a été obtenue.") Si __name__ == "__main__": trio.run (main)
Analyse de code:
- HTTPX et TRIO: HTTPX est un client HTTP moderne qui prend en charge les demandes synchrones et asynchrones. Le trio est une bibliothèque d'E / S asynchrone qui fournit une méthode de programmation simultanée structurée.
- En-têtes: Définissez l'utilisateur-agent pour simuler les demandes de navigateur, qui est très importante pour éviter d'être reconnu par le mécanisme anti-rédaction du site Web.
- Fonction fetch_table_data:
- Recevoir l'identifiant comme paramètre pour construire l'URL.
- Tout d'abord, envoyez une demande au chemin EN / IMDM / 12.0 et passez dans le paramètre du sujet.
- Utilisez Re.Search pour trouver le modèle "OldUrl": "(. *?)" Le texte de réponse et extraire le chemin API réel.
- Éplice le OldUrl_Path extrait avec API / V1 / Content / pour former un chemin de demande API complet.
- Envoyez une demande à ce chemin API, avec PARSEBOBY = true et Lang = en paramètres, qui indiquent à l'API de renvoyer le contenu HTML pasable.
- pd.read_html (api_response.content, attrs = {'class': 'defaultstyle'}): c'est l'étape de base. La fonction read_html de la bibliothèque Pandas peut identifier et extraire directement les tables du contenu HTML et renvoyer une liste de données de données. attrs = {'class': 'defaultStyle'} est utilisé pour spécifier que seules les tables avec la classe defaultStyle se révèlent améliorer la précision.
- Ajoutez une colonne Source_Identifier à la DataFrame récupérée pour suivre la source de données.
- Fonction principale:
- Lit un fichier CSV contenant l'identifiant.
- Itérez dans chaque identifiant et appelez la fonction fetch_table_data pour obtenir les données. Pour le bien de la brièveté du tutoriel, ce qui est montré ici, ce sont les appels en série. Dans un rampage réel à grande échelle, une véritable concurrence devrait être obtenue en utilisant des mécanismes tels que TRIO.Taskgroup.
- Fusionnez toutes les données de données récupérées en une seule.
- Imprimez et enregistrez les données fusionnées finales dans le fichier CSV.
Résumé et meilleures pratiques
- Analyse approfondie du comportement du site Web: lorsque la structure HTML est instable, ne vous concentrez pas seulement sur le HTML lui-même, mais utilisez l'outil de développeur de navigateur (onglet réseau) pour observer la méthode de chargement des données réelle du site Web, en particulier les demandes XHR / Fetch.
- Priorité à l'API: Si le site Web dispose d'une API claire pour fournir des données, appelez l'API directement possible. Les API fournissent généralement des formats de données plus stables, structurés et faciles à analyser (tels que JSON, XML) et ne sont pas facilement affectés par les modifications de l'interface utilisateur frontale.
- Simuler les utilisateurs réels: utilisez un agent utilisateur approprié et d'autres en-têtes de demande HTTP (tels que référentiel, acceptation, etc.) pour simuler le comportement réel du navigateur, qui peut éviter efficacement d'être intercepté par le mécanisme anti-rampe du site Web ou le contenu d'exception de retour.
- Programmation asynchrone: Pour les tâches de grattage Web qui doivent gérer un grand nombre de demandes, HTTPX peut améliorer considérablement les performances et l'efficacité avec des bibliothèques asynchrones telles que Asyncio ou Trio.
- Robustesse et gestion des erreurs: ajoutez des mécanismes de gestion des erreurs appropriés (tels que les blocs d'essai à l'exception) au code pour gérer les erreurs de réseau, les exceptions de réponse API ou les défaillances d'analyse, etc., pour assurer le fonctionnement stable du robot.
- Conformez-vous à l'accord de robots et aux conditions d'utilisation du site Web: lors de l'exécution du grattage Web, assurez-vous de consulter le fichier robots.txt du site Web et respectez les conditions d'utilisation du site Web pour effectuer des rampes responsables.
Grâce aux méthodes ci-dessus, nous pouvons relever plus efficacement le défi de la structure HTML incohérente dans le grattage Web et créer un système de données de données plus stable, efficace et robuste.
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!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Stock Market GPT
Recherche d'investissement basée sur l'IA pour des décisions plus intelligentes

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Cet article présentera comment utiliser JavaScript pour réaliser l'effet de cliquer sur les images. L'idée principale est d'utiliser l'attribut Data- * de HTML5 pour stocker le chemin d'image alternatif et écouter des événements de clic via JavaScript, changez dynamiquement les attributs SRC, réalisant ainsi la commutation d'image. Cet article fournira des exemples de code et des explications détaillés pour vous aider à comprendre et à maîtriser cet effet interactif couramment utilisé.

Tout d'abord, vérifiez si le navigateur prend en charge GeolocationAPI. Si vous êtes pris en charge, appelez getCurrentPosition () pour obtenir les coordonnées de l'emplacement actuelles de l'utilisateur et obtenir les valeurs de latitude et de longitude grâce à des rappels réussis. Dans le même temps, fournissez des exceptions de traitement des rappels d'erreur tels que l'autorisation de déni, l'indisponibilité de l'emplacement ou du délai d'attente. Vous pouvez également transmettre des options de configuration pour activer une précision élevée, définir le délai d'expiration et la période de validité du cache. L'ensemble du processus nécessite l'autorisation de l'utilisateur et la gestion des erreurs correspondante.

Cet article vise à résoudre le problème du retour null lors de l'obtention d'éléments DOM via document.getElementById () dans JavaScript. Le noyau consiste à comprendre le synchronisation d'exécution du script et l'état de l'analyse DOM. En plaçant correctement la balise ou en utilisant l'événement téléchargé DomContent, vous pouvez vous assurer que l'élément est à nouveau tenté lorsqu'il est disponible, en évitant efficacement de telles erreurs.

L'utilisation du noyau de l'API de composition de Nuxt3 comprend: 1. DefinePageMeta est utilisée pour définir les méta-informations de la page, telles que le titre, la mise en page et le middleware, qui doivent être appelées directement et ne peuvent pas être placées dans des déclarations conditionnelles; 2. Usyhead est utilisé pour gérer les balises d'en-tête de page, prend en charge les mises à jour statiques et réactives et doit coopérer avec DefinePageMeta pour obtenir l'optimisation du référencement; 3. USEASYNCDATA est utilisé pour obtenir en toute sécurité des données asynchrones, gérer automatiquement l'état de chargement et d'erreur et prend en charge le contrôle d'acquisition de données du serveur et du client; 4. UseFetch est une encapsulation de usEasyncdata et $ fetch, qui dépente automatiquement la clé de demande pour éviter les demandes en double

Pour créer un intervalle de répétition dans JavaScript, vous devez utiliser la fonction setInterval (), qui exécutera à plusieurs reprises des fonctions ou des blocs de code à des intervalles de millisecondes spécifiés. Par exemple, setInterval (() => {Console.log ("Exécuter toutes les 2 secondes");}, 2000) publiera un message toutes les 2 secondes jusqu'à ce qu'il soit effacé par ClearInterval (Interpalid). Il peut être utilisé dans les applications réelles pour mettre à jour les horloges, les serveurs de sondage, etc., mais faire attention à la limite de retard minimum et à l'impact du temps d'exécution de la fonction, et effacez l'intervalle dans le temps lorsqu'il n'est plus nécessaire pour éviter les fuites de mémoire. Surtout avant la désinstallation des composants ou la fermeture des pages, assurez-vous que

ThebestatorreatEAmulti-linestringinjavascriptsisingstingTemplatalalswithbackticks, qui sepresereBreakenexactlyAswritten.

Ce tutoriel explique en détail comment formater les numéros en chaînes avec deux décimales fixes en JavaScript, même les entiers peuvent être affichés sous la forme de "# .00". Nous nous concentrerons sur l'utilisation de la méthode numéro.prototype.tofixed (), y compris sa syntaxe, sa fonctionnalité, son exemple de code et des points clés à noter, comme son type de retour étant toujours une chaîne.

Utilisez la méthode WriteText de ClipboardAPI pour copier du texte dans le presse-papiers, il doit être appelé dans le contexte de sécurité et l'interaction utilisateur, prend en charge les navigateurs modernes et l'ancienne version peut être dégradée avec EXECCOMAND.
