以下是我的情况:我必须登录一个网站并从那里下载一个CSV,从linux服务器无头。该页面使用JS,没有它就无法工作。
经过一些研究后,我选择了Selenium和PhantomJS。 登录,设置CSV参数和使用Selenium / PhantomJS / Py3查找下载按钮都没有问题,实际上令人惊讶的是令人愉快。
但是点击下载按钮没有做任何事情。经过一些研究后,我发现PhantomJS似乎不支持下载对话框和下载,但它正在即将推出的功能列表中。
所以当我发现下载按钮只是调用REST API URL时,我认为我使用了urllib
的解决方法。问题是,它只有在您登录网站时才有效。
所以第一次尝试失败了,因为它返回:b'{"success":false,"session":"expired"}'
这是有道理的,因为我希望Selenium和urllib使用不同的会话。
所以我想我在urrlib中使用Seleniums驱动程序的头文件试试这个:
...
url = 'http://www.foo.com/api/index'
data = urllib.parse.urlencode({
'foopara': 'cadbrabar',
}).encode('utf-8')
headers = {}
for cookie in driver.get_cookies():
headers[cookie['name']] = cookie['value']
req = urllib.request.Request(url, data, headers)
with urllib.request.urlopen(req) as response:
page = response.read()
driver.close()
不幸的是,这产生了与过期会话相同的结果。我做错了什么,有没有办法绕过这个,其他建议还是我走到了尽头?提前谢谢。
答案 0 :(得分:3)
我找到了一个解决方案并想分享它。
一个要求发生了变化,我不再使用PhantomJS
,而是使用虚拟帧缓冲区无头工作的chromedriver
。同样的结果,它完成了工作。
您需要的是:
pip install selenium pyvirtualdisplay
apt-get install xvfb
我使用Py3.5和来自ovh.net的测试文件,带有标签而不是按钮。
脚本等待页面上出现然后单击它。如果您不等待该元素并且位于异步站点上,则您尝试单击的元素可能尚未存在。下载位置是相对于脚本位置的文件夹。如果文件已经下载了第二次延迟,脚本将检查该目录。如果我没有错,文件应该是.part在下载期间,一旦它成为filename
中指定的.dat,脚本就会完成。如果在下载无法完成之前关闭虚拟帧缓冲区和驱动程序。
完整的脚本如下所示:
# !/usr/bin/python
# coding: utf-8
import os
import sys
import time
from pyvirtualdisplay import Display
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import glob
def main(argv):
url = 'http://ovh.net/files'
dl_dir = 'downloads'
filename = '1Mio.dat'
display = Display(visible=0, size=(800, 600))
display.start()
chrome_options = webdriver.ChromeOptions()
dl_location = os.path.join(os.getcwd(), dl_dir)
prefs = {"download.default_directory": dl_location}
chrome_options.add_experimental_option("prefs", prefs)
chromedriver = "./chromedriver"
driver = webdriver.Chrome(executable_path=chromedriver, chrome_options=chrome_options)
driver.set_window_size(800, 600)
driver.get(url)
WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH, '//a[@href="' + filename + '"]')))
hyperlink = driver.find_element_by_xpath('//a[@href="' + filename + '"]')
hyperlink.click()
while not(glob.glob(os.path.join(dl_location, filename))):
time.sleep(1)
driver.close()
display.stop()
if __name__ == '__main__':
main(sys.argv)
我希望将来可以帮助某人。
答案 1 :(得分:1)
如果要下载的按钮具有文件链接,则可以使用python代码测试下载,因为PhantonJs不支持自行下载。因此,如果您的下载按钮未提供文件链接,则表示您无法测试。
要使用文件链接和phyton(断言该文件存在)进行测试,您可以按照此主题进行操作。由于我是C#开发人员和睾丸工程师,我不知道在python中编写代码的更好方法没有错误,但我相信你可以:
答案 2 :(得分:1)
我最近使用Selenium利用ChromeDriver从网上下载文件。这是有效的,因为Chrome会自动下载该文件并将其存储在下载文件中。这比使用PhantomJS更容易。
我建议将ChromeDriver与Selenium一起使用并走这条路线:https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver
编辑 - 如下所述,我忽略了如何设置ChromeDriver以无头模式运行。以下是更多信息:http://www.chrisle.me/2013/08/running-headless-selenium-with-chrome/
答案 3 :(得分:0)
您可以尝试以下内容:
from requests.auth import HTTPBasicAuth
import requests
url = "http://some_site/files?file=file.csv" # URL used to download file
# GET-request to get file content using your web-site's credentials to access file
r = requests.get(url, auth=HTTPBasicAuth("your_username", "your_password"))
# Saving response content to file on your computer
with open("path/to/folder/to/save/file/filename.csv", 'w') as my_file:
my_file.write(r.content)