Autodownload для firefox в селене с использованием python [duplicate]

ваше описание довольно запутанно; прямая конкатенация десятичных значений не кажется полезной в большинстве контекстов. следующий код будет прикладывать каждую букву к 8-битовому символу, а THEN - конкатенацию. так работает стандартная кодировка ASCII

def ASCII(s):
    x = 0
    for i in xrange(len(s)):
        x += ord(s[i])*2**(8 * (len(s) - i - 1))
    return x
6
задан bkcollection 22 May 2017 в 01:24
поделиться

5 ответов

Я переписал ваш сценарий с комментариями, объясняющими, почему я внес изменения, которые я сделал. Я думаю, что ваша главная проблема могла быть плохим миметиком, однако ваш сценарий имел журнал системных проблем, которые сделали бы его в лучшем случае ненадежным. В этом переписании используются явные ожидания, что полностью устраняет необходимость использования time.sleep(), позволяя ему работать как можно быстрее, а также устранять ошибки, возникающие из-за перегрузки сети.

Вам понадобится сделать следующее: убедитесь, что все модули установлены:

pip install requests explicit selenium retry pyvirtualdisplay

Сценарий:

#!/usr/bin/python

from __future__ import print_function  # Makes your code portable

import os
import glob
import zipfile
from contextlib import contextmanager

import requests
from retry import retry
from explicit import waiter, XPATH, ID
from selenium import webdriver
from pyvirtualdisplay import Display
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait

DOWNLOAD_DIR = "/tmp/shKLSE/"


def build_profile():
    profile = webdriver.FirefoxProfile()
    profile.set_preference('browser.download.folderList', 2)
    profile.set_preference('browser.download.manager.showWhenStarting', False)
    profile.set_preference('browser.download.dir', DOWNLOAD_DIR)
    # I think your `/zip` mime type was incorrect. This works for me
    profile.set_preference('browser.helperApps.neverAsk.saveToDisk',
                           'application/vnd.ms-excel,application/zip')

    return profile


# Retry is an elegant way to retry the browser creation
# Though you should narrow the scope to whatever the actual exception is you are
# retrying on
@retry(Exception, tries=5, delay=3)
@contextmanager  # This turns get_browser into a context manager
def get_browser():
    # Use a context manager with Display, so it will be closed even if an
    # exception is thrown
    profile = build_profile()
    with Display(visible=0, size=(800, 600)):
        browser = webdriver.Firefox(profile)
        print("firefox")
        try:
            yield browser
        finally:
            # Let a try/finally block manage closing the browser, even if an
            # exception is called
            browser.quit()


def main():
    print("hello from python 2")
    with get_browser() as browser:
        browser.get("https://www.shareinvestor.com/my")

        # Click the login button
        # waiter is a helper function that makes it easy to use explicit waits
        # with it you dont need to use time.sleep() calls at all
        login_xpath = '//*/div[@class="sic_logIn-bg"]/a'
        waiter.find_element(browser, login_xpath, XPATH).click()
        print(browser.current_url)

        # Log in
        username = "bkcollection"
        username_id = "sic_login_header_username"
        password = "123456"
        password_id = "sic_login_header_password"
        waiter.find_write(browser, username_id, username, by=ID)
        waiter.find_write(browser, password_id, password, by=ID, send_enter=True)

        # Wait for login process to finish by locating an element only found
        # after logging in, like the Logged In Nav
        nav_id = 'sic_loggedInNav'
        waiter.find_element(browser, nav_id, ID)

        print("log in done")

        # Load the target page
        target_url = ("https://www.shareinvestor.com/prices/price_download.html#/?"
                      "type=price_download_all_stocks_bursa")
        browser.get(target_url)
        print(browser.current_url)

        # CLick download button
        all_data_xpath = ("//*[@href='/prices/price_download_zip_file.zip?"
                          "type=history_all&market=bursa']")
        waiter.find_element(browser, all_data_xpath, XPATH).click()

        # This is a bit challenging: You need to wait until the download is complete
        # This file is 220 MB, it takes a while to complete. This method waits until
        # there is at least one file in the dir, then waits until there are no
        # filenames that end in `.part`
        # Note that is is problematic if there is already a file in the target dir. I
        # suggest looking into using the tempdir module to create a unique, temporary
        # directory for downloading every time you run your script
        print("Waiting for download to complete")
        at_least_1 = lambda x: len(x("{0}/*.zip*".format(DOWNLOAD_DIR))) > 0
        WebDriverWait(glob.glob, 300).until(at_least_1)

        no_parts = lambda x: len(x("{0}/*.part".format(DOWNLOAD_DIR))) == 0
        WebDriverWait(glob.glob, 300).until(no_parts)

        print("Download Done")

        # Now do whatever it is you need to do with the zip file
        # zip_ref = zipfile.ZipFile(DOWNLOAD_DIR, 'r')
        # zip_ref.extractall(DOWNLOAD_DIR)
        # zip_ref.close()
        # os.remove(zip_ref)

        print("Done!")


if __name__ == "__main__":
    main()

Полное раскрытие: я поддерживаю явный модуль. Он предназначен для того, чтобы упростить использование явных ожиданий для таких ситуаций, когда сайты медленно загружаются в динамический контент на основе пользовательских взаимодействий. Вы могли бы заменить все вызовы waiter.XXX выше с прямыми явными ожиданиями.

3
ответ дан Levi Noecker 19 August 2018 в 07:12
поделиться
  • 1
    Можете ли вы объяснить @retry(Exception, tries=5, delay=3) и @contextmanager ? Есть ли другой общий модуль, который может использоваться для замены retry и explicit? Pythonanywhere не имеет этих двух модулей. – bkcollection 26 May 2017 в 02:22
  • 2
    @bkcollection, прежде чем обновить свой ответ, можете ли вы сначала сказать мне, можете ли вы использовать это для установки внешних зависимостей? В частности, retry и explicit? https://help.pythonanywhere.com/pages/InstallingNewModules/ – Levi Noecker 26 May 2017 в 02:37
  • 3
    он отлично работает в основном. Но он обычно застревает после print "firefox" и снова должен повториться. Это происходит как 2 раза из трех – bkcollection 26 May 2017 в 08:28
  • 4
    более подробное объяснение будет лучше для начинающих – bkcollection 28 May 2017 в 07:58

Я не вижу существенного недостатка в вашем блоке кода как такового. Но вот несколько рекомендаций через это решение & amp; выполнение этого автоматизированного тестового сценария:

  1. Этот код отлично работает в режиме Off Market Hours. В течение Рыночных часов много JavaScript & amp; Ajax Calls находятся в игре, и обработка которых выходит за рамки этого Вопроса.
  2. Вы можете сначала проверить, есть ли загруженный каталог для загрузки, и & amp; если он недоступен, создайте новый.
  3. После того, как вы нажмете на «Login», вы вызываете некоторые wait для HTML DOM для правильной рендеринга.
  4. Этот код для этой функции работает в стиле Windows и отлично работает на платформе Windows. ] Если вы хотите просмотреть процесс загрузки, вам нужно установить некоторые дополнительные настройки в FirefoxProfile, как указано в моем коде ниже.
  5. Всегда следует использовать максимальное окно браузера через browser.maximize_window()
  6. Когда вы начинаете загрузку, вам нужно подождать достаточное количество времени, чтобы полностью загрузить файл.
  7. Если вы используете browser.quit() в конце, вам не нужно использовать browser.close()
  8. Вы можете заменить все time.sleep() на любой из ImplicitlyWait или ExplicitWait или FluentWait.
  9. Вот ваш собственный блок кода с некоторыми простыми настройками в нем:
    #!/usr/bin/python
    print "hello from python 2"
    
    import urllib2
    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    import time
    from pyvirtualdisplay import Display
    import requests, zipfile, os    
    
    display = Display(visible=0, size=(800, 600))
    display.start()
    
    newpath = 'C:\\home\\vivvin\\shKLSE'
    if not os.path.exists(newpath):
        os.makedirs(newpath)    
    
    profile = webdriver.FirefoxProfile()
    profile.set_preference("browser.download.dir",newpath);
    profile.set_preference("browser.download.folderList",2);
    profile.set_preference("browser.helperApps.neverAsk.saveToDisk", "application/zip");
    profile.set_preference("browser.download.manager.showWhenStarting",False);
    profile.set_preference("browser.helperApps.neverAsk.openFile","application/zip");
    profile.set_preference("browser.helperApps.alwaysAsk.force", False);
    profile.set_preference("browser.download.manager.useWindow", False);
    profile.set_preference("browser.download.manager.focusWhenStarting", False);
    profile.set_preference("browser.helperApps.neverAsk.openFile", "");
    profile.set_preference("browser.download.manager.alertOnEXEOpen", False);
    profile.set_preference("browser.download.manager.showAlertOnComplete", False);
    profile.set_preference("browser.download.manager.closeWhenDone", True);
    profile.set_preference("pdfjs.disabled", True);
    
    for retry in range(5):
        try:
            browser = webdriver.Firefox(profile)
            print "firefox"
            break
        except:
            time.sleep(3)
    time.sleep(1)
    
    browser.maximize_window()
    browser.get("https://www.shareinvestor.com/my")
    time.sleep(10)
    login_main = browser.find_element_by_xpath("//*[@href='/user/login.html']").click()
    time.sleep(10)
    print browser.current_url
    username = browser.find_element_by_id("sic_login_header_username")
    password = browser.find_element_by_id("sic_login_header_password")
    print "find id done"
    username.send_keys("bkcollection")
    password.send_keys("123456")
    print "log in done"
    login_attempt = browser.find_element_by_xpath("//*[@type='submit']")
    login_attempt.submit()
    browser.get("https://www.shareinvestor.com/prices/price_download.html#/?type=price_download_all_stocks_bursa")
    print browser.current_url
    time.sleep(20)
    dl = browser.find_element_by_xpath("//*[@href='/prices/price_download_zip_file.zip?type=history_all&market=bursa']").click()
    time.sleep(900)
    
    browser.close()
    browser.quit()
    display.stop()
    
    zip_ref = zipfile.ZipFile(/home/vinvin/sh/KLSE, 'r')
    zip_ref.extractall(/home/vinvin/sh/KLSE)
    zip_ref.close()
    os.remove(zip_ref)
    

Дайте мне знать, если это ответит на ваш вопрос.

3
ответ дан DebanjanB 19 August 2018 в 07:12
поделиться
  • 1
    Благодарю. Как вы предлагаете заменить ImplicitlyWait или ExplicitWait или FluentWait.? Удостоверьтесь, что он загружен, прежде чем procedured станет лучшей идеей. – bkcollection 26 May 2017 в 08:27
  • 2
    @bkcollection Вы можете вызвать ImplicitlyWait один раз в начале вашего скрипта, так что Selenium будет ждать последовательно. Вы также можете использовать ExplicitWait, чтобы определенные элементы были видимыми / кликабельными в HTML DOM. В качестве альтернативы вы можете использовать FluentWait, чтобы ускорить выполнение, частым опросом, игнорируя Исключения. В Make sure it is downloaded before procedd вы можете использовать urllib.request.urlretrieve модуль, который будет блокироваться до завершения загрузки. благодаря – DebanjanB 26 May 2017 в 11:45
  • 3
    вы можете отредактировать ответ. Я знаю, что time.sleep - плохая идея. благодаря – bkcollection 26 May 2017 в 12:04
  • 4
    @bkcollection Свой все свой собственный код. Я просто добавил минимальные настройки, необходимые для работы вашего блока кода :) Спасибо – DebanjanB 26 May 2017 в 12:10
  • 5
    @DebanjanB Это сработало для меня. Но есть ли способ переименовать загруженный файл? – abhi1610 28 May 2018 в 11:43

Я не пробовал на упомянутом вами сайте, однако следующий код работает отлично и загружает ZIP. если вы не можете загрузить zip, тип Mime может быть другим. вы можете использовать браузер Chrome и сетевой контроль, чтобы проверить тип mime файла, который вы пытаетесь загрузить.

profile = webdriver.FirefoxProfile()
profile.set_preference('browser.download.folderList', 2)
profile.set_preference('browser.download.manager.showWhenStarting', False)
profile.set_preference('browser.download.dir', "/home/vinvin/shKLSE/")
profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/zip')

browser = webdriver.Firefox(profile)
browser.get("http://www.colorado.edu/conflict/peace/download/peace.zip")
1
ответ дан Gaurang Shah 19 August 2018 в 07:12
поделиться

Возьмите его за рамки селена. Измените настройки предпочтений так, чтобы при щелчке ссылки (сначала проверьте, действительно ли ссылка), она дает вам всплывающее окно с просьбой сохранить, теперь используйте sikuli http://www.sikuli.org/ для нажмите на всплывающее окно. Мимические типы не всегда работают, и нет черного и белого ответа, почему он не работает.

1
ответ дан Subrata Fouzdar 19 August 2018 в 07:12
поделиться

Причина в том, что веб-страница медленно загружается. Я добавил ожидание через 20 секунд после открытия ссылки на веб-страницу

login_attempt.submit()
browser.get("https://www.shareinvestor.com/prices/price_download.html#/?type=price_download_all_stocks_bursa")
print browser.current_url
time.sleep(20)
dl = browser.find_element_by_xpath("//*[@href='/prices/price_download_zip_file.zip?type=history_all&market=bursa']").click()

Не возвращается ошибка.

Дополнительно, /zip неверен тип MIME. Изменить на profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/zip')

Окончательная коррекция:

   #!/usr/bin/python
    print "hello from python 2"

    import urllib2
    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    import time
    from pyvirtualdisplay import Display
    import requests, zipfile, os    

    display = Display(visible=0, size=(800, 600))
    display.start()

    profile = webdriver.FirefoxProfile()
    profile.set_preference('browser.download.folderList', 2)
    profile.set_preference('browser.download.manager.showWhenStarting', False)
    profile.set_preference('browser.download.dir', "/home/vinvin/shKLSE/")
    # application/zip not /zip
    profile.set_preference('browser.helperApps.neverAsk.saveToDisk', 'application/zip')

    for retry in range(5):
        try:
            browser = webdriver.Firefox(profile)
            print "firefox"
            break
        except:
            time.sleep(3)
    time.sleep(1)

    browser.get("https://www.shareinvestor.com/my")
    time.sleep(10)
    login_main = browser.find_element_by_xpath("//*[@href='/user/login.html']").click()
    print browser.current_url
    username = browser.find_element_by_id("sic_login_header_username")
    password = browser.find_element_by_id("sic_login_header_password")
    print "find id done"
    username.send_keys("bkcollection")
    password.send_keys("123456")
    print "log in done"
    login_attempt = browser.find_element_by_xpath("//*[@type='submit']")
    login_attempt.submit()
    browser.get("https://www.shareinvestor.com/prices/price_download.html#/?type=price_download_all_stocks_bursa")
    print browser.current_url
    time.sleep(20)
    dl = browser.find_element_by_xpath("//*[@href='/prices/price_download_zip_file.zip?type=history_all&market=bursa']").click()
    time.sleep(30)

    browser.close()
    browser.quit()
    display.stop()

   zip_ref = zipfile.ZipFile('/home/vinvin/shKLSE/file.zip', 'r')
   zip_ref.extractall('/home/vinvin/shKLSE')
   zip_ref.close()
   # remove with correct path
   os.remove('/home/vinvin/shKLSE/file.zip')
1
ответ дан user 19 August 2018 в 07:12
поделиться
  • 1
    ОП уже упоминает и спит в своем сценарии тоже. – Aperçu 21 May 2017 в 16:03
  • 2
    Спасибо, он отлично работает с вашим кодом, с небольшими настройками – bkcollection 26 May 2017 в 09:36
Другие вопросы по тегам:

Похожие вопросы: