7
votes

Python: Impossible de télécharger avec selenium en page Web

Mon but de télécharger un fichier zip de https: // www .shareinvestor.com / Prix / prix_download_zip_file.zip? Type = History_all & Market = Bursa C'est un lien dans cette page Web https://www.shareinvestor.com/ Prix ​​/ prix_download.html # /? Type = Prix_download_all_stocks_bursa . Ensuite, enregistrez-le dans ce répertoire "/ home / vinvin / shklse / code> (J'utilise Pythonaywherewhere). Puis décompressez-le et l'extrait de fichier CSV dans le répertoire.

Le code exécuté jusqu'à la fin avec Aucune erreur mais elle ne télécharge pas. Le fichier zip est automatiquement strud> téléchargé quand cliquez sur https : //www.shareinvestor.com/prices/price_download_zip_file.zip? Type = History_all & Market = Bursa manuellement. P>

Mon code avec un nom d'utilisateur et un mot de passe de travail est utilisé. Le nom d'utilisateur réel et mot de passe strud> est utilisé de manière à ce qu'il soit plus facile de comprendre le problème. P> xxx pré>

HTML Snippet: strong>

<li><a href="/prices/price_download_zip_file.zip?type=history_all&amp;market=bursa">All Historical Data</a> <span>About 220 MB</span></li>


4 commentaires

Était curieux de savoir si une solution sur la plate-forme Windows peut être acceptable pour vous? Merci


@Dev c'est acceptable. Tant que cela peut fonctionner de manière cohérente.


Observé que vous avez utilisé dolderlist , showwhenStarting , télécharger.dir & jetkask.savetodidisk dans votre code mais vous avez havn 't mentionné à leur sujet dans la description. Avez-vous des exigences en fonction de ces fonctionnalités? Merci


Non, tant qu'il est téléchargé dans le répertoire dans Zip et le décompressez-le.


5 Réponses :


1
votes

La raison est due à la page Web du chargement lentement. J'ai ajouté une attente de 20 secondes après ouvrir la page Web Link

   #!/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 commentaires

Merci, ça fonctionne bien avec votre code, avec de petits modifications



1
votes

Prenez le côté de la portée du sélénium. Changez les paramètres de préférence afin que lorsque le lien soit cliqué sur cliqué (première vérification si le lien est valide), il vous donne une pop up demandant d'enregistrer, utilisez maintenant sikuli http://www.sikuli.org/ Pour cliquer sur la fenêtre contextuelle. Les types MIME ne fonctionnent pas toujours et il n'y a pas de réponse noire et blanche pourquoi elle ne fonctionne pas.


1 commentaires

Comme mentionné, pas de pop-up. Vous essayez de pouvoir manuellement avec le nom d'utilisateur et le mot de passe.



1
votes

Je n'ai pas essayé sur le site que vous avez mentionné, cependant suivant le code fonctionne parfaitement et télécharge le zip. Si vous ne pouvez pas télécharger le zip, le type MIME pourrait être différent. Vous pouvez utiliser le navigateur chromé et l'inspection réseau pour vérifier le type MIME du fichier que vous essayez de télécharger.

 Entrez la description de l'image ici xxx


0 commentaires

3
votes

J'ai réécrit votre script, avec des commentaires expliquant pourquoi j'ai apporté les modifications que j'ai faites. Je pense que votre principal problème pourrait avoir été un mauvais mimeType, cependant, votre script avait un journal de problèmes systémiques qui l'auraient rendu plus fiable au mieux. Cette réécriture utilise des attentes explicites, qui supprime complètement la nécessité d'utiliser temps.sleep () code>, ce qui lui permet de fonctionner aussi vite que possible, tout en éliminant les erreurs résultant de la congestion du réseau.

Vous allez Nécessité de faire ce qui suit pour vous assurer que tous les modules sont installés: p>

Demandes d'installation PIP Explicit SELENIUM Réessayez PyvirtualDisplay Code> P>

#!/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()


4 commentaires

Pouvez-vous expliquer @retry (exception, essais = 5, délai = 3) et @ContextManager ? Y a-t-il un autre module commun qui peut utiliser pour remplacer réessayer et explicite ? Pythonanywhere n'a pas ces deux modules.


@BkCollection, avant de mettre à jour ma réponse, pouvez-vous d'abord me dire si vous pouvez l'utiliser pour installer des dépendances externes? Spécifiquement, réessayer et explicite ? https://help.pythonyanywhere.com/pages/installingnewmodules/


Cela fonctionne bien fondamentalement. Mais il est normalement bloqué après Imprimer "Firefox" ET BESOIN DE RECHERCHER à nouveau. Ça arrive comme 2 fois sur trois


Plus de détails L'explication sera meilleure pour les débutants



4
votes

Je ne vois aucun inconvénient majeur dans votre bloc de code comme tel. Mais voici quelques recommandations via cette solution et l'exécution de ce script de test automatisé:

  1. Ce code fonctionne parfaitement dans les heures de marché. Pendant les heures de marché, beaucoup de code> JavaScript AJAX appels CODE> sont en jeu et la gestion de ceux-ci sont au-delà de la portée de cette question. LI>
  2. Vous pouvez envisager de vérifier le répertoire de téléchargement recherché d'abord et si non disponible, en créer un nouveau. Ce bloc de code de cette fonctionnalité est sous Windows Style et fonctionne parfaitement sur la plate-forme Windows. LI>
  3. Une fois que vous avez cliqué sur "Connexion", induisez quelque chose attendre code> pour le DOM HTML pour rendant correctement. LI>
  4. Lorsque vous souhaitez découvrir le processus de téléchargement, vous devez définir certaines plus de préférences dans le firefoxprofile code> comme mentionné dans mon code ci-dessous. Li>
  5. Toujours envisager de maximiser la fenêtre du navigateur via Browser.maximze_window () Code> Li>
  6. Lorsque vous commencez à télécharger, vous devez attendre suffisamment de temps pour obtenir le fichier complètement téléchargé. LI>
  7. Si vous utilisez Browser.Quit () code> à la fin, vous n'avez pas besoin d'utiliser navigateur.close () code> li>
  8. Vous pouvez envisager de remplacer tous les temps.sleep () code> avec l'un des implicitlywait code> ou explicitwait code> ou fluentwait code >. li>
  9. Voici votre propre bloc de code avec quelques modifications simples dedans: P>

    #!/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)
    


7 commentaires

Merci. Comment suggérez-vous de remplacer le implicitlywait ou explicitwait ou fluentwait. ? Assurez-vous qu'il est téléchargé avant que procéda est la meilleure idée.


@bkCollection Vous pouvez induire implicitlywait une fois au début de votre script afin que le sélénium attend de manière cohérente. Vous pouvez également utiliser explicitwait pour que certains éléments soient visibles / cliquables dans le DOM HTML. Sinon, vous pouvez utiliser fluestwait pour accélérer votre exécution par interrogation fréquente, ignorer les exceptions. Pour Assurez-vous qu'il est téléchargé avant que procéda Vous pouvez envisager d'utiliser urllib.request.urlreTrieve module qui bloquera jusqu'à ce que le téléchargement soit effectué. Merci


Pourriez-vous modifier la réponse. Je sais que temps.sleep est une mauvaise idée. Merci


@BkCollection c'est tout votre propre code. Je viens d'ajouter les modifications minimales nécessaires pour faire fonctionner votre code de code :) merci


Pourriez-vous le rendre meilleur pour la partie de téléchargement, pour vous assurer qu'il est complètement téléchargé avant de décompresser le fichier? Merci beaucoup


@Debanjanb ça a fonctionné pour moi. Mais existe-t-il un moyen de renommer le fichier téléchargé?


@ ABHI1610 Pouvez-vous soulever une nouvelle question selon votre nouvelle exigence s'il vous plaît? Mais je suppose qu'il existe une QA / discussion existante sur ce sujet. S'il vous plaît vérifier une fois.