【问题标题】:python selenium, find out when a download has completed?python selenium,找出下载何时完成?
【发布时间】:2016-03-24 04:13:03
【问题描述】:

我使用 selenium 来启动下载。下载完成后,需要采取一些措施,有没有什么简单的方法可以判断下载完成的时间? (我使用的是 FireFox 驱动)

【问题讨论】:

    标签: python selenium


    【解决方案1】:

    我最近遇到了这个问题。我一次下载多个文件,如果下载失败,我必须以超时的方式构建。

    代码每秒检查某个下载目录中的文件名,并在完成或完成时间超过 20 秒后退出。返回的下载时间用于检查下载是否成功或是否超时。

    import time
    import os
    
    def download_wait(path_to_downloads):
        seconds = 0
        dl_wait = True
        while dl_wait and seconds < 20:
            time.sleep(1)
            dl_wait = False
            for fname in os.listdir(path_to_downloads):
                if fname.endswith('.crdownload'):
                    dl_wait = True
            seconds += 1
        return seconds
    

    我相信这仅适用于 chrome 文件,因为它们以 .crdownload 扩展名结尾。可能有类似的方法可以在其他浏览器中进行检查。

    编辑:我最近更改了使用此功能的方式,因为.crdownload 没有作为扩展名出现。本质上,这也只是等待正确数量的文件。

    def download_wait(directory, timeout, nfiles=None):
        """
        Wait for downloads to finish with a specified timeout.
    
        Args
        ----
        directory : str
            The path to the folder where the files will be downloaded.
        timeout : int
            How many seconds to wait until timing out.
        nfiles : int, defaults to None
            If provided, also wait for the expected number of files.
    
        """
        seconds = 0
        dl_wait = True
        while dl_wait and seconds < timeout:
            time.sleep(1)
            dl_wait = False
            files = os.listdir(directory)
            if nfiles and len(files) != nfiles:
                dl_wait = True
    
            for fname in files:
                if fname.endswith('.crdownload'):
                    dl_wait = True
    
            seconds += 1
        return seconds
    

    【讨论】:

    • 比公认的答案好得多(实际上根本没有提供任何解决方案)。
    【解决方案2】:

    没有内置到 selenium 的方式来等待下载完成。


    这里的一般想法是等到文件出现在您的“下载”目录中

    这可以通过一遍又一遍地检查文件是否存在来实现:

    或者,通过使用 watchdog 之类的东西来监控目录:

    【讨论】:

      【解决方案3】:
      import os
      import time
      
      def latest_download_file():
            path = r'Downloads folder file path'
            os.chdir(path)
            files = sorted(os.listdir(os.getcwd()), key=os.path.getmtime)
            newest = files[-1]
      
            return newest
      
      fileends = "crdownload"
      while "crdownload" == fileends:
          time.sleep(1)
          newest_file = latest_download_file()
          if "crdownload" in newest_file:
              fileends = "crdownload"
          else:
              fileends = "none"
      

      这是几种解决方案的组合。我不喜欢我必须扫描整个下载文件夹以查找以“crdownload”结尾的文件。此代码实现了一个功能,该功能可在下载文件夹中提取最新文件。然后它只是检查该文件是否仍在下载。将它用于我正在构建的 Selenium 工具,效果很好。

      【讨论】:

        【解决方案4】:

        我知道答案为时已晚,但想为未来的读者分享一个技巧。

        您可以从主线程创建一个线程,例如 thread1 并在此处启动您的下载。 现在,创建另一个线程,比如 thread2 并在那里,让它等到 thread1 使用 join() 方法完成。现在,您可以在之后继续执行流程下载完成。

        仍然确保您不使用 selenium 启动下载,而是使用 selenium 提取链接并使用 requests 模块进行下载。

        Download using requests module

        例如:

        def downloadit():
             #download code here    
        
        def after_dwn():
             dwn_thread.join()           #waits till thread1 has completed executing
             #next chunk of code after download, goes here
        
        dwn_thread = threading.Thread(target=downloadit)
        dwn_thread.start()
        
        metadata_thread = threading.Thread(target=after_dwn)
        metadata_thread.start()
        

        【讨论】:

          【解决方案5】:

          如前所述,没有本地方法可以检查下载是否完成。所以这里有一个辅助函数可以为 Firefox 和 Chrome 完成这项工作。一个技巧是在开始新下载之前清除临时下载文件夹。此外,使用原生 pathlib 进行跨平台使用。

          from pathlib import Path
          
          def is_download_finished(temp_folder):
              firefox_temp_file = sorted(Path(temp_folder).glob('*.part'))
              chrome_temp_file = sorted(Path(temp_folder).glob('*.crdownload'))
              downloaded_files = sorted(Path(temp_folder).glob('*.*'))
              if (len(firefox_temp_file) == 0) and \
                 (len(chrome_temp_file) == 0) and \
                 (len(downloaded_files) >= 1):
                  return True
              else:
                  return False
          

          【讨论】:

          • 好一个,没有这么想。效果很好
          【解决方案6】:

          在下载目录的文件名中检查“Unconfirmed”关键字:

          # wait for download complete
          wait = True
          while(wait==True):
              for fname in os.listdir('\path\to\download directory'):
                  if ('Unconfirmed') in fname:
                      print('downloading files ...')
                      time.sleep(10)
                  else:
                      wait=False
          print('finished downloading all files ...')
          

          文件下载完成后立即退出while循环。

          【讨论】:

            【解决方案7】:
            x1=0
            while x1==0:
                count=0
                li = os.listdir("directorypath")
                for x1 in li:
                    if x1.endswith(".crdownload"):
                         count = count+1        
                if count==0:
                    x1=1
                else:
                    x1=0
            

            如果您尝试检查一组文件(多个)是否已完成下载,则此方法有效。

            【讨论】:

              【解决方案8】:

              这对我有用:

              fileends = "crdownload"
              while "crdownload" in fileends:
                  sleep(1)
                  for fname in os.listdir(some_path): 
                      print(fname)
                      if "crdownload" in fname:
                          fileends = "crdownload"
                      else:
                          fileends = "None"
              

              【讨论】:

                【解决方案9】:

                如果使用 Selenium 和 Chrome,您可以编写自定义等待条件,例如:

                class file_has_been_downloaded(object):
                def __init__(self, dir, number):
                    self.dir = dir
                    self.number = number
                
                def __call__(self, driver):
                    print(count_files(dir), '->', self.number)
                    return count_files(dir) > self.number
                

                count_files 函数只是验证文件是否已添加到文件夹中

                def count_files(direct):
                for root, dirs, files in os.walk(direct):
                    return len(list(f for f in files if f.startswith('MyPrefix') and (
                            not f.endswith('.crdownload')) ))
                

                然后在你的代码中实现这个:

                files = count_files(dir)
                << copy the file. Possibly use shutil >>
                WebDriverWait(driver, 30).until(file_has_been_downloaded(dir, files))
                

                【讨论】:

                  【解决方案10】:

                  对于 Chrome,未完成下载的文件具有扩展名 .crdownload。如果你 set your download directory 正确,那么你可以等到你想要的文件不再有这个扩展名。原则上,这与等待文件存在(如suggested by alecxe)没有太大区别——但至少您可以通过这种方式监控进度。

                  【讨论】:

                    【解决方案11】:

                    我有一个更好的:

                    所以重定向开始下载的函数。例如download_function= lambda: element.click()

                    检查目录中的文件数并等待没有下载扩展名的新文件。之后重命名它。 (可以更改以移动文件而不是在同一目录中重命名)

                    def save_download(self, directory, download_function, new_name, timeout=30):
                        """
                        Download a file and rename it
                        :param directory: download location that is set
                        :param download_function: function to start download
                        :param new_name: the name that the new download gets
                        :param timeout: number of seconds to wait for download
                        :return: path to downloaded file
                        """
                        self.logger.info("Downloading " + new_name)
                        files_start = os.listdir(directory)
                        download_function()
                        wait = True
                        i = 0
                        while (wait or len(os.listdir(directory)) == len(files_start)) and i < timeout * 2:
                            sleep(0.5)
                            wait = False
                            for file_name in os.listdir(directory):
                                if file_name.endswith('.crdownload'):
                                    wait = True
                        if i == timeout * 2:
                            self.logger.warning("Documents not downloaded")
                            raise TimeoutError("File not downloaded")
                        else:
                            self.logger.info("Downloading done")
                            new_file = [name for name in os.listdir(directory) if name not in files_start][0]
                            self.logger.info("New file found renaming " + new_file + " to " + new_name)
                            while not os.access(directory + r"\\" + new_file, os.W_OK):
                                sleep(0.5)
                                self.logger.info("Waiting for write permission")
                            os.rename(directory + "\\" + new_file, directory + "\\" + new_name)
                            return directory + "\\" + new_file
                    

                    【讨论】:

                    • 我喜欢这个外观。比其他一些答案复杂一点,但看起来更健壮。要使其适用于 Firefox,请查找以 .part 而不是 .crdownload 结尾的文件。可能值得使用 os.path.join 而不是硬编码“\\”以避免 Windows 与 Unix 斜线方向问题。
                    • 您的代码中存在错误。你永远不会增加 i 的值。因此,如果下载失败,它将卡在 i
                    • 我还发现,如果在之前的执行中浏览器在完成下载之前崩溃并在下载文件夹中留下剩余的 .crdownload 文件,则每次下载都会超时。
                    【解决方案12】:

                    创建一个使用“请求”获取文件内容并调用该函数的函数,除非文件被下载,否则您的程序将不会前进

                    import requests
                    from selenium import webdriver
                    driver = webdriver.Chrome()
                    # Open the website
                    driver.get(website_url_)
                    
                    x = driver.find_element_by_partial_link_text('download')
                    y = x.get_attribute("href")
                    fc = requests.get(y)
                    fname = x.text
                    with open(fname, 'wb') as f:
                        f.write(fc.content)
                    

                    【讨论】:

                      猜你喜欢
                      • 2018-05-25
                      • 2023-01-28
                      • 1970-01-01
                      • 2020-06-20
                      • 2020-07-11
                      • 2015-03-14
                      • 2020-09-30
                      • 1970-01-01
                      • 2017-05-12
                      相关资源
                      最近更新 更多