FirefoxのsaveToDiskの代わりに、このソリューションはもう少し "ハッキー"ですが、ChromeとFirefoxの両方で動作し、いつでも変更できるブラウザ固有の機能には依存しません。それ以外のものがあれば、将来の課題を解決する方法について、誰かに少し違った視点を与えるでしょう。
前提条件:
- あなたはセレンを持っていることを確認し、インストールpyvirtualdisplay ...のPython 2:
sudo pip install selenium pyvirtualdisplay
- のPython 3:
sudo pip3 install selenium pyvirtualdisplay
マジック
import pyvirtualdisplay
import selenium
import selenium.webdriver
import time
import base64
import json
root_url = 'https://www.google.com'
download_url = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
print('Opening virtual display')
display = pyvirtualdisplay.Display(visible=0, size=(1280, 1024,))
display.start()
print('\tDone')
print('Opening web browser')
driver = selenium.webdriver.Firefox()
#driver = selenium.webdriver.Chrome() # Alternately, give Chrome a try
print('\tDone')
print('Retrieving initial web page')
driver.get(root_url)
print('\tDone')
print('Injecting retrieval code into web page')
driver.execute_script("""
window.file_contents = null;
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
window.file_contents = reader.result;
};
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', %(download_url)s);
xhr.send();
""".replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ') % {
'download_url': json.dumps(download_url),
})
print('Looping until file is retrieved')
downloaded_file = None
while downloaded_file is None:
# Returns the file retrieved base64 encoded (perfect for downloading binary)
downloaded_file = driver.execute_script('return (window.file_contents !== null ? window.file_contents.split(\',\')[1] : null);')
print(downloaded_file)
if not downloaded_file:
print('\tNot downloaded, waiting...')
time.sleep(0.5)
print('\tDone')
print('Writing file to disk')
fp = open('google-logo.png', 'wb')
fp.write(base64.b64decode(downloaded_file))
fp.close()
print('\tDone')
driver.close() # close web browser, or it'll persist after python exits.
display.popen.kill() # close virtual display, or it'll persist after python exits.
我々は最初から私たちは、ファイルのダウンロードをターゲットにしているドメイン上のURLをロード
、について説明。これにより、cross site scriptingの問題が発生することなく、そのドメインでAJAXリクエストを実行できます。
次に、AJAXリクエストを発生させるDOMにjavascriptを注入しています。 AJAXリクエストがレスポンスを返すと、レスポンスを取得してFileReaderオブジェクトにロードします。そこから、readAsDataUrl()を呼び出して、ファイルのbase64でコード化されたコンテンツを抽出することができます。次に、base64でエンコードされたコンテンツを取り出し、それを曖昧にアクセス可能な変数window
に追加します。
最後に、AJAXリクエストが非同期であるため、コンテンツをウィンドウに追加するのを待っている間にPythonを入力します。追加されると、ウィンドウから取得したbase64コンテンツをデコードし、ファイルに保存します。
このソリューションは、Seleniumでサポートされているすべての最新のブラウザで動作し、テキストまたはバイナリ、およびすべてのMIMEタイプに対応しています。
代替アプローチ
私はこれをテストしていませんが、セレンはあなたに要素がDOMに存在するまで待機する能力を買う余裕はありません。グローバルにアクセス可能な変数が移入されるまでループするのではなく、DOMに特定のIDを持つ要素を作成し、その要素のバインディングをトリガーとして使用してダウンロードしたファイルを取得することができます。
docs = document
.querySelector('downloads-manager')
.shadowRoot.querySelector('#downloads-list')
.getElementsByTagName('downloads-item')
この溶液をクロムに拘束されている:私はその後、私はこのようなシャドウDOMからダウンロードしたファイルの一覧を取得し、その後chrome://downloads
ページを開くと、リンクをクリックしてファイルをダウンロードしてくださいChromeで
私は 'urllib'を使用して、' urll'がリンクが送るURLである 'urllib.urlretrieve(url)'を使ってダウンロードを取得することをお勧めしますクリックイベントでのみ機能するため、 – Serial
は使用できません。 – sam
ページのHTMLを解析すると、クリックイベントがブラウザに送信するリンクを取得し、それを使用することができます。 – Serial