2017-01-17 1 views
1

Je suis en train de lire un livre sur Python en ce moment. Il y a un petit projet pour les devoirs: "Écrire un programme qui va à un site de partage de photos comme Flickr ou Imgur, recherche une catégorie de photos, puis télécharge toutes les images résultantes." Il est suggéré d'utiliser uniquement webbrowser, requests et bs4 libraries.Beautifulsoup renvoie html incomplet

Je ne peux pas le faire pour Flickr. J'ai trouvé que l'analyseur ne peut pas aller à l'intérieur de l'élément (div class = "interaction-view"). En utilisant "Inspecter l'élément" dans Chrome, je peux voir qu'il y a quelques éléments "div" à l'intérieur et un élément "a". Cependant, quand j'utilise la bibliothèque bs4, elle ne peut pas le voir.

Mon code comme ceci:

#!/usr/bin/env python3 
# To download photos from Flickr 

import requests, bs4 

search_name = "spam" 
website_name = requests.get('https://www.flickr.com/search/?text=' 
         + search_name) 
website_name.raise_for_status() 
parse_obj = bs4.BeautifulSoup(website_name.text, "html.parser") 
elements = parse_obj.select('body #content main .main.search-photos-results \ 
       .view.photo-list-view.requiredToShowOnServer \ 
       .view.photo-list-photo-view.requiredToShowOnServer.awake \ 
       .interaction-view') 
print(elements) 

Il imprime uniquement:

[<div class="interaction-view"></div>, <div class="interaction-view"></div>...] 

Sans éléments imbriqués et je ne comprends pas pourquoi ... Thank you!

+0

pouvez-vous corriger le bloc de code? la première ligne devrait être '#!/usr/bin/env python3' et ensuite' Soup.select' devrait être 'parse_obj.select'. Cela rend plus facile pour les gens de reproduire – hansaplast

+0

Terminé. Je vous remercie. – Trarbish

Répondre

4

Le problème est que le contenu de <div class="interaction-view"></div> sur flickr est uniquement chargé via javascript. Vous pouvez vérifier que si vous affichez la source de la page, vous trouverez: <div class="interaction-view"></div> sans contenu dans l'étiquette div.

Vous devez exécuter le javascript en quelque sorte. Puisque beautifulsoup n'offre pas cela, une solution consiste à utiliser du sélénium pour cela. pip install selenium et installez geckodriver pour firefox (sur OSX: brew install geckodriver). Ensuite, changer votre code pour utiliser le sélénium pour charger la page:

#!/usr/bin/env python3 

import requests, bs4 
from selenium import webdriver 
from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC 

search_name = "spam" 
url = 'https://www.flickr.com/search/?text=%s' % search_name 

browser = webdriver.Firefox() 
browser.get(url) 
delay = 3 
WebDriverWait(browser, delay).until(EC.presence_of_element_located(browser.find_element_by_id('...'))) 

soup = bs4.BeautifulSoup(browser.page_source, "html.parser") 


elements = soup.select('body #content main .main.search-photos-results \ 
       .view.photo-list-view.requiredToShowOnServer \ 
       .view.photo-list-photo-view.requiredToShowOnServer.awake \ 
       .interaction-view') 
print(elements) 

La partie WebDriverWait est nécessaire si le sélénium attend avec parsing jusqu'à est chargé un certain élément. Vous devez remplacer ... par un identifiant dont vous savez qu'il sera présent. Voir this answer pour vérifier comment cela peut être fait avec les classes.

+0

Intéressant, merci! J'ai trouvé qu'il a besoin d'ajouter une pause (par exemple time.sleep (5)) avant de créer un objet BeautifulSoup. Sinon, je ne reçois pas la liste "remplie". Dois-je comprendre correctement: 1) quand je "inspecter l'élément" dans le navigateur, je cours le code JavaScript et peut voir "rempli" div? 2) Quand je presse juste F12 je n'exécute pas de code JavaScript. Par conséquent, il n'y a aucun contenu dans l'étiquette div? – Trarbish

+0

bon point. Vous devez d'abord attendre qu'un certain élément soit présent, j'ai mis à jour ma réponse. 'sleep' fonctionne probablement mais attend trop longtemps si le chargement est rapide ou pourrait échouer si le chargement est lent, mieux vaut utiliser WebDriverWait – hansaplast

+0

' F12' ouvre la console du développeur. Ce n'est pas la même chose que la source html. Qu'est-ce que beautifulsoup voit en faisant 'requests.get' vous voyez quand clic droit-> voir la source. Ce que le sélénium voit est ce que vous faites dans la console du développeur (par exemple lorsque vous exécutez '$ (" body #content ... ")') – hansaplast