【问题标题】:Beautifulsoup returns incomplete htmlBeautifulsoup 返回不完整的 html
【发布时间】:2017-06-02 01:20:05
【问题描述】:

我现在正在读一本关于 Python 的书。有一个家庭作业的小项目: “编写一个程序,访问 Flickr 或 Imgur 等照片共享网站,搜索照片类别,然后下载所有生成的图像。” 建议仅使用 webbrowser、requests 和 bs4 库。

我不能为 Flickr 做这件事。我发现解析器无法进入元素内部(div class="interaction-view")。在 Chrome 中使用“检查元素”我可以看到其中有一些“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>...]

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

【问题讨论】:

  • 你能更正代码块吗?第一行应该是#!/usr/bin/env python3,然后Soup.select 应该是parse_obj.select。这使得人们更容易复制

标签: python parsing beautifulsoup flickr


【解决方案1】:

问题是flickr 上&lt;div class="interaction-view"&gt;&lt;/div&gt; 的内容只能通过javascript 加载。您可以检查一下,如果您查看页面源代码,您会发现:&lt;div class="interaction-view"&gt;&lt;/div&gt; 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 以检查如何使用类来完成。

【讨论】:

  • 有意思,谢谢!我发现它需要在创建 BeautifulSoup 对象之前添加暂停(例如 time.sleep(5))。否则,我没有得到“填充”列表。我是否理解正确:1)当我在浏览器中“检查元素”时,我运行 JavaScript 代码并可以看到“填充”的 div? 2) 当我按下 F12 时,我不运行 JavaScript 代码。结果是div标签里面没有内容?
  • 好点。您首先需要等待某个元素出现,我更新了我的答案。 sleep 可能有效,但如果加载速度快则等待时间过长,或者如果加载缓慢可能会失败,最好采用 WebDriverWait 方式
  • F12 打开开发者控制台。这与 html 源代码不同。执行requests.get 时beautifulsoup 会看到什么,您在右键单击->查看源代码时会看到。 selenium 看到的是您在开发者控制台中所做的任何事情(例如,当您运行 $("body #content...") 时)
  • 另外,如果您对答案满意,请点赞并接受。这个答案花了我大约 1 小时来制作,在这里,为此支付的费用是赞成并接受 ;-)
  • 谢谢!当然;)
猜你喜欢
  • 2018-11-24
  • 2019-03-12
  • 2021-11-04
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 2015-07-07
  • 2021-05-19
相关资源
最近更新 更多