【问题标题】:Selenium Webscraping JavaScript elementsSelenium Webscraping JavaScript 元素
【发布时间】:2018-08-29 23:15:48
【问题描述】:

我正在尝试使用 selenium 和 PhantomJS 来抓取 JavaScript 生成的一些元素。

我的代码:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.ui import Select

from bs4 import BeautifulSoup
from selenium import webdriver
from collections import OrderedDict
import time

driver = webdriver.PhantomJS()
driver.get('http://www.envirostor.dtsc.ca.gov/public/profile_report?global_id=01290021&starttab=landuserestrictions')

driver.find_element_by_id('sitefacdocsTab').click()
time.sleep(5)

html = driver.page_source
soup = BeautifulSoup(html)

点击操作后,我仍然得到旧的页面数据,而不是 jQuery 给出的新数据。

【问题讨论】:

  • 但是脚本里没有点击,是吗?
  • 我不明白你的问题..
  • 您对不使用 Selenium 获取表格的解决方案是否满意?

标签: python selenium-webdriver beautifulsoup phantomjs


【解决方案1】:

使用requests

在浏览器中打开开发者工具 > 网络 > XHR 选项卡。然后,单击Site/Facility Docs 选项卡。您将在 XHR 选项卡中看到 AJAX 请求。请求发送到this site 以获取标签数据。

您只需使用requests 模块即可从该选项卡中抓取任何您想要的内容。

import requests

r = requests.get('http://www.envirostor.dtsc.ca.gov/public/profile_report_include?global_id=01290021&ou_id=&site_id=&tabname=sitefacdocs&orderby=&schorderby=&comporderby=&rand=0.07839738919075079&_=1521609095041')
soup = BeautifulSoup(r.text, 'lxml')

# And to check whether we've got the correct data:
table = soup.find('table', class_='display-v4-default')
print(table.find('a', target='_documents').text)
# Soil Management Plan Implementation Report, Public Market Infrastructure Relocation, Phase 1-B Infrastructure Area

使用Selenium

当您想等待页面加载时,您应该切勿使用time.sleep()。您应该改用Eplicit Waits。使用后,您可以使用.get_attribute('innerHTML') 属性获取整个标签内容。

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('http://www.envirostor.dtsc.ca.gov/public/profile_report?global_id=01290021&starttab=landuserestrictions')

driver.find_element_by_id('sitefacdocsTab').click()
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.ID, 'docdatediv')))

html = driver.find_element_by_id('sitefacdocs').get_attribute('innerHTML')
soup = BeautifulSoup(html, 'lxml')
table = soup.find('table', class_='display-v4-default')
print(table.find('a', target='_documents').text)
# Soil Management Plan Implementation Report, Public Market Infrastructure Relocation, Phase 1-B Infrastructure Area

其他信息:

带有id="docdatediv" 的元素是包含日期范围过滤器的div 标记。我使用了它,因为它不在第一个选项卡上,但出现在您想要的选项卡上。您可以将任何此类元素用于WebDriverWait

并且,带有id="sitefacdocs" 的元素是div 标记,其中包含整个选项卡内容(即日期过滤器和下面的所有表格)。所以,你的 soup 对象将有所有这些东西要刮掉。

【讨论】:

  • 多么棒的答案!另一个提醒我们,我们认为合适的解决方案可能根本不是最佳解决方案。
  • 我同意该解决方案,但如果我想抓取另一个选项卡活动,我无法看到该选项卡中唯一的任何元素更改。那么在这种情况下怎么办?
  • @SriramArvindLakshmanakumar,您可以使用该选项卡中任何元素的id,因为id 始终是unqiue。对于Activities 标签,您可以使用(By.ID, 'activities')
  • expected_conditions 可以使用很多东西。只需浏览我上面链接的显式等待文档即可。告诉你关于他们的一切都太宽泛了,超出了这个问题的范围。我相信这个解决方案可以解决所有标签的问题(使用id's 甚至不同的classes)。
  • @KeyurPotdar 是的,我可以使用第一种方法并且可以工作,它不会动态工作,因为我正在抓取的页面会根据名为 global_id 的特定参数而变化。加上它在 XHR 中为每个选项卡生成新的 url,所以我必须如何执行点击。
猜你喜欢
  • 2019-10-29
  • 1970-01-01
  • 2019-01-18
  • 2018-06-21
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多