【问题标题】:Python - Downloading PDF's contained in a JQueryFileTreePython - 下载包含在 JQueryFileTree 中的 PDF
【发布时间】:2020-08-14 12:05:40
【问题描述】:

我正在创建一个下载文件,以便从与我雇主公司相关的网站自动下载 PDF。

看起来 PDF 包含在 JQueryFileTree 中。有没有办法可以下载以下文件夹之一并将其与内容 PDF 一起保存到磁盘?

到目前为止,我正在使用 Python 和 selenium 来自动登录等。

谢谢

到目前为止我的代码:

from selenium import webdriver
from time import sleep 
import requests
from bs4 import BeautifulSoup as bs 

import secrets

class manual_grabber():
    """ A class creating a manual downloader for the Roger Technology website """
    def __init__(self):
        """ Initialize attributes of manual grabber """
        self.driver = webdriver.Chrome('\\Users\\Joel\\Desktop\\Python\\manual_grabber\\chromedriver.exe')

    def login(self):
        """ Function controlling the login logic """
        self.driver.get('urltosite')

        sleep(1)

        # Locate elements and enter login details
        user_in = self.driver.find_element_by_xpath('/html/body/div[2]/form/input[6]')
        user_in.send_keys(secrets.username)   

        pass_in = self.driver.find_element_by_xpath('/html/body/div[2]/form/input[7]')
        pass_in.send_keys(secrets.password)

        enter_button = self.driver.find_element_by_xpath('/html/body/div[2]/form/div/input')
        enter_button.click()
        
        # Click Self Service Area button
        self_service_button = self.driver.find_element_by_xpath('//*[@id="bs-example-navbar-collapse-1"]/ul/li[1]/a')
        self_service_button.click()


grab = manual_grabber()
grab.login()

文件结构是这样的:

单击其中一个文件夹时,会在树右侧的窗口中打开内容 PDF。

还有 DOM:

【问题讨论】:

  • 嗨,您能分享一下您目前的代码、DOM 结构以及如何从这样的显示器手动下载文件夹吗?
  • @RichEdwards 您好,我已经编辑了显示文件结构等的问题。您无法直接手动下载文件夹。您可以通过单击右侧的下载按钮下载每个单独的文件。希望这会有所帮助。
  • Selenium 会做你能做的——你将如何下载文件? - 我假设单击左侧的树然后单击右侧的下载按钮? - ... 对于 selenium,识别树项目(如果可能,通过文本),对所有符合您的条件的 a 使用 find_elements (复数)并循环下载所有 - 或使用 libcurl 之类的库来控制从从 sleneium 下载的 href 是“不受控制的”(即没有进度的 ida) - 如果您可以从 devtools 共享每个阶段的 DOM,我可以帮助您使用标识符,否则伪是我可以去的地方
  • @RichEdwards 谢谢。感谢您的帮助!
  • @RichEdwards 在尝试使用左侧树上的 .click() 函数后,它告诉我找不到元素。这是因为它包含在 JQueryFileTree 中还是无关紧要?

标签: python jquery selenium web-scraping download


【解决方案1】:

根据 DOM 和您可以从 jquery 树中选择的屏幕截图。

您可以使用此 xpath 从左侧树中选择:

//a[.//nobr[text()='Products catalogue and brouches']]

对于这个 xpath:

  • //a 是相对的 a(页面上的任何位置)
  • [ 开头意味着我们将其标识为...
  • . 来自该位置的孩子(即在a 下方)
  • //nobr任何nobr标签
  • 其中text() = '产品目录和手册'(区分大小写)

简而言之,任何a 都有一个子nobr,其中包含我们想要的文本。

我把它放在简单的页面中,它与输出的唯一匹配:

还有更多的 xpath 标识符和方法 - this is great learning resource

希望使用该 xpath,您只需输入要单击的文本,它就会为您完成。

如果找不到您的标识符 - 请告诉我,我会再看一遍。


第一季度的一些额外想法:

根据您的应用程序以及树的工作方式,您可能需要a wait strategy

有两种主要方法,显式和隐式。为了简单起见(因为这个答案已经足够长了),请先尝试隐式等待:

driver.implicitly_wait(10)

在你的__init__ 中设置一次,selenium 将等待长达 10 秒,然后再抱怨不存在的对象。 (如果不起作用,请告诉我!)

您可能还需要滚动树才能看到元素。在这种情况下,试试这个 - 只需使用上面的 xpath 识别您的元素并将其传递到此处:

def ScrollIntoView(element):
    actions = ActionChains(driver)
    actions.move_to_element(element).perform()

您问题的下一部分是下载文件。点击右侧的链接。

您需要共享更多 DOM - 如果您可以共享 2 或 3 个启动下载的 a 或“img”,我将能够提供定制的响应。

一般而言,如果您想获得“所有”链接以供下载,您需要执行以下操作:

#get all the elements - needs a condition that identifies just these anchors
allLinks = driver.find_elements_by_xpath(some condition)

#loop through all links and action the click
for link in allLinks:
    link.click()
    time.sleep(3) # don't download too many at once - depending on their size let them complete

可以在 selenium 中下载文件,但您无法获得下载大小、进度或速度。从本质上讲,一旦它开始,你就对它视而不见。

有替代方案,但它们会增加复杂性。

如果您需要更多帮助,请随时向我发布额外的 DOM 内容。很高兴看到更多并提供更多支持。


从下面的 cmets 更新。 要管理 iframe,您需要识别它并切换到它以执行您的操作。 我无法测试 xpath - 所以试一试并根据需要进行更新。

frame = driver.find_element_by_xpath('//iframe[contains(@src,"ManageFiles")]')
driver._switch_to.frame(frame)
#do the actions on the frame
#when ready...
driver._switch_to.default_content()

最后,请务必切换回您的默认内容或需要与之交互的下一个 iframe。


切换、查找并等待点击:

WebDriverWait(driver, 15).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,'//iframe[contains(@src,"ManageFiles")]')))

#Watch spelling and case on this line
myListObject = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH,"//a[.//nobr[text()='Products catalogue and brochures']]")))

myListObject.click()

【讨论】:

  • 在我尝试之前无法测试代码的乐趣 :-) - 首先检查是否找到了一个元素:element = self.driver.find_element_by_xpath("//a[.//nobr[text()='Products catalogue and brochures']]") - 注意 Text() 中的任何拼写错误 - 我无法复制和粘贴,我在上面输入了“brouches”(不是小册子)
  • 如果找到了元素,但你不能这样做 element.click() - 你可以试试这个作为计划 b driver.execute_script("arguments[0].click();",element) ...如果我可以访问你的网站,我会尝试所有这些您并对其进行了全面测试
  • framesiframes 在场吗? (他们需要特殊处理)-您可能已经这样做了,但请检查拼写或尝试您可以看到的另一个树项目-如果您还没有。在 devtools 中试一下 xpath 看看是否找到它:-)
  • 在使用 selenium 处理帧的末尾添加了一些示例代码的更新
  • @j4yman 从图像来看很难——通常它是一个试错过程来微调 xpath 和等待。我在底部添加了另一个新部分,其中包含同步查找和单击...如果这不起作用,我需要知道错误,请配合...并且请注意项目的拼写和大小写!只有在项目可见时才能单击,因此如果树需要扩展,请将其更改为更高级别的项目
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-14
  • 2010-10-14
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 2022-10-08
相关资源
最近更新 更多