2017-09-21 1 views
3

vient de démarrer le web scraping en python et je suis confronté à quelques problèmes.BeautifulSoup et lxml ne peuvent pas trouver l'élément div

je commencé à utiliser Sélénium pour télécharger la source et l'enregistrement d'une page Web, il:

from selenium import webdriver 
driver= webdriver.Firefox() 
driver.get("https://www.website.com") 
f=open('output.txt','w') 
f.write(driver.page_source.encode('utf-8')) 
f.close() 
driver.quit() 

Tout fonctionnait bien, mais Sélénium prend trop de temps, donc je suis tourné vers mécaniser, pour obtenir la source de la page:

import mechanize 
browser = mechanize.Browser() 
browser.set_handle_robots(False) 
cookies = mechanize.CookieJar() 
browser.set_cookiejar(cookies) 
browser.addheaders = [('User-agent', 'Mozilla/5.0')] 
browser.set_handle_refresh(False) 
browser.open("https://www.website.com") 

vient ici le problème: si je tente de trouver un div particulier par son ID, il me retourne pas:

from bs4 import BeautifulSoup as BS 
soup= BS(browser.response().read(),'lxml') 
print(soup.find(id="div_id")) 

Bien que si j'inspecte le code source obtenu avec mechanize avec un éditeur de texte régulier, je peux le trouver. Il est quelque chose comme:

<div id="div_id" data referrer="div_id"> 

Ce div a beaucoup d'autres éléments de l'enfant, il est situé à environ 1/5 « dans » le code et le code source complet est sur le 500kb.If J'essaie plutôt à la recherche d'autres div près, pas de chance non plus. Alors que si je cherche quelque div proche du début du code source, il le trouve.Et quoi de plus intéressant, si j'essaie de chercher la même div (avec BS), dans le code source obtenu avec Selenium, au lieu de celui obtenu Avec Mechanize, il est capable de le trouver, bien que le div semble complètement identique par inspection avec un éditeur de texte.

J'ai essayé avec tous les parseurs supportés par BS, sans chance. Donc, je pensais qu'il avait peut-être quelque chose à voir avec BS, et j'essayé de faire la même chose avec lxml:

from lxml import etree 
parser= etree.HTMLParser() 
tree= etree.parse(open('source.txt'),parser) 
results= tree.xpath('//div[@id="div_id"]') 
print(etree.tostring(results[0])) 

Comme BS, il a pu trouver le div dans le code source obtenu avec Sélénium, mais pas avec Mechanize. Donc, je pensais que cela pourrait avoir quelque chose à voir avec Mechanize et transformé à utiliser Demandes:

import requests 
from fake_useragent import UserAgent 
ua=UserAgent() 
url= 'https://www.website.com' 
headers= {'User-agent': str(ua.chrome)} 
page = requests.get(url, headers=headers) 

Lorsque regardé dans page.content pour la div, soit avec BS ou lxml, encore une fois ne luck.It arrive si j'analyse directement la réponse ou si je l'enregistre dans un fichier, puis analyser le fichier.

Et je pense que c'est à ce sujet ... J'ai également essayé d'encoder les réponses Mechanize et Requests, comme je l'avais vu avec Selenium, mais pas de changement. J'ai également essayé d'utiliser d'autres BS version (3.x), pas de changement.

Pour résumer: - Si je cherche le div avec BS ou lxml dans le code source obtenu via Selenium, il le trouve. Avec les autres, non. - Si je cherche d'autres divs au début du code source, BS et lxml le trouvent, indépendamment de la méthode utilisée pour obtenir le code. - Lors de l'inspection, le div est là dans tous les cas.

Versions utilisées: -python: 2.7.9 -BeautifulSoup: 4.6.0 -Mechanize: 0.3.5 -les demandes: 2.18.4 -Selenium: 3.5.0 -lxml: 4.0.0 -OS: linux debian

Merci.

+0

Il serait utile si vous nous avez donné l'URL réelle. –

+0

url: https://www.facebook.com/groups/1584160618524185/ div id: pagelet_forsale_island Merci – Bleracas

Répondre

0

La div que vous cherchez est cachée dans un commentaire HTML qui est probablement traité via le Javascript.Vous pouvez toujours utiliser requests d'abord extraire le code HTML caché comme suit:

from bs4 import BeautifulSoup, Comment 
import requests 

id = "pagelet_forsale_island" 

r = requests.get("https://www.facebook.com/groups/1584160618524185/") 
soup = BeautifulSoup(r.content, "html.parser") 

for comment in soup.find_all(string=lambda text:isinstance(text, Comment)): 
    if id in comment: 
     hidden_soup = BeautifulSoup(comment, "html.parser") 

     for div in hidden_soup.find_all('div', id=id): 
      print div 

Cela devient BeautifulSoup pour trouver tous les commentaires dans le code HTML et de déterminer ensuite le cas échéant contenir votre id. Si une correspondance est trouvée, le commentaire lui-même est à nouveau transmis à BeautifulSoup pour un traitement ultérieur. Cela affichera votre <div> comme:

<div data-referrer="pagelet_forsale_island" id="pagelet_forsale_island"></div> 
+0

C'est tout! Pourriez-vous expliquer comment "pour commenter dans soup.find_all (string = lambda text: isinstance (texte, commentaire)):" fonctionne? Je ne suis pas très sûr. Et pensez-vous que BS est le plus apte pour cette tâche ou peut-être un autre outil me conviendrait mieux? Je vous remercie! – Bleracas

+0

'comments' sont juste des types de texte spéciaux. C'est une astuce pour l'obtenir pour retourner tous les commentaires trouvés dans un document. Il y a d'autres outils, j'ai tendance à utiliser BS cependant. –