Beautifulsoup returns 不完整 html

Beautifulsoup returns incomplete html

我正在读一本关于 Python 的书。有一个作业的小项目: "Write a program that goes to a photo-sharing site like Flickr or Imgur, searches for a category of photos, and then downloads all the resulting images." 建议仅使用 webbrowser、requests 和 bs4 库。

我不能为 Flickr 做这件事。我发现解析器无法进入元素内部 (div class="interaction-view")。在 Chrome 中使用 "Inspect element" 我可以看到其中有一些 "div" 元素和 "a" 元素。但是,当我使用 bs4 库时,它看不到它。

我的代码是这样的:

#!/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)

它只打印:

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

没有任何嵌套元素,我不明白为什么... 谢谢!

问题是 flickr 上 <div class="interaction-view"></div> 的内容只能通过 javascript 加载。您可以检查一下,如果您查看页面源代码,您会发现:<div class="interaction-view"></div> div 标签中没有任何内容。

您需要以某种方式执行javascript。由于 beautifulsoup 不提供此功能,因此一种解决方案是为此使用硒。 pip install selenium 并为 firefox 安装 geckodriver(在 OSX 上:brew install geckodriver)。然后更改代码以使用 selenium 加载页面:

#!/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)

WebDriverWait 部分是必需的,因此 selenium 会等待解析,直到某个元素被加载。您需要将 ... 更改为您知道会出现的 ID。请参阅 this answer 了解如何使用 类.

完成