python - 登录后使用请求下载运行时文件
问题描述
我是网络抓取的新手,我想在登录后下载运行时 csv 文件(按钮没有 URL,它使用 JS 功能),我尝试使用https://curl.trillworks.com/#,它可以工作很好,但它使用动态cookies。
import requests
cookies = {
...,
}
headers = {
...
}
data = {
...
}
s = requests.Session()
response = s.post(posturl, headers=headers, cookies=cookies, data=data, verify=False)
Cookies 是动态的,所以每次我想下载文件时,我都必须获取新的 cookie,所以我尝试了使用相同脚本的不同方法
payload = {
'login': 'login',
'username': 'My_name',
'password': 'My_password',
}
logurl = "http:..."
posturl = 'http:...'
s = requests.Session()
response = s.post(logurl, headers=headers, data=data)
# response = s.post(posturl, data=payload,auth=(my_name, my_password)) #This too gives me the wrong output
但这并没有给我正确的输出,它给了我第一页文本/html,响应标题给了我两种不同的内容类型
print response.headers['Content-Type']
正确的输出是'text/csv;charset=UTF-8'
,但它给了我信息'text/html;charset=UTF-8'
,status_code for both is 200
CSV文件的posturl与html页面相同
解决方案
经过深入搜索,我发现:网络抓取有完全不同的工具:
1. request
or urllib
: 广泛使用的工具,它使我们可以使用...进行发布和获取请求、登录、创建持久性 cookie Session()
,我们可以使用一个很棒的工具curl
访问https://curl.trillworks.com/,但这对于复杂的数据提取是不够的。
Beautifullsoup
orlxml
:使用 forHTML Parser
,在源 html 中导航,类似正则表达式以从 HTML 页面中提取所需元素get Title
,找到div with id=12345
,这些工具无法理解 JS 按钮,并且无法在表单中执行post
orget
or orclick button
or之类的操作submit
,其只是如何从请求中读取数据。Mechnize
orrobobrowser
orMechnicalSoup
:用于网页浏览和 cookie 处理、浏览器历史记录的出色工具,我们可以将这些工具视为 and 的组合request
,BeautifullSoup
因此我们可以轻松地在页面 html 内容中制作get
和post
和导航,例如,这些技术不是真正的浏览器,所以它不能执行和理解 JS,不能发送异步请求,不能移动滚动条,不能导出选定的数据表格......所以这些工具不足以发出复杂的请求。submit in form
BeautifullSoup
Selenium
: 是一个强大的工具和一个真正的浏览器,我们可以随心所欲地获取数据,我们可以制作get
andpost
,search
,submit
,selecting
,move scroolbar
它就像我们使用任何导航器一样使用,Selemenium
什么都不用是不可能的,我们可以使用带有GUI的真正浏览器或我们可以option = 'headless'
用于服务器环境。
吹我解释我们如何submit
在一个表格JS button
中server environment
一步一步地点击。
A. 为服务器环境安装 webdriver: 打开终端:
sudo apt install chromium-chromedriver
sudo pip install selenium
如果您想使用 webdriver 进行 GUI 界面下载,请从 https://chromedriver.chromium.org/downloads
B. Python 2.7 中的示例,它也适用于 Python 3,只需编辑打印行
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')
# define downlaoded directory
options.add_experimental_option("prefs", {
"download.default_directory": "/tmp/",
"download.prompt_for_download": False,
})
browser = webdriver.Chrome(chrome_options=options) # see edit for recent code change.
USERNAME = 'mail'
PASSWORD = 'password'
browser.get('http://www.example.com')
print browser.title
user_input = browser.find_element_by_id('mail_input')
user_input.send_keys(USERNAME)
pass_input = browser.find_element_by_id('pass_input')
pass_input.send_keys(PASSWORD)
login_button = browser.find_element_by_id("btn_123")
login_button.click()
csv_button = browser.find_element_by_id("btn45875465")
csv_button.click()
browser.close() # to close current page or you can use too `browser.quit()` to destroy the hole of webdriver instance
# Check if the file was downloaded completely and seccessfully
file_path = '/tmp/file_name'
while not os.path.exists(file_path):
time.sleep(1)
if os.path.isfile(file_path):
print 'The file was downloaded completely and seccessfully'
推荐阅读
- javascript - 试图创建一个大的表情命令
- json - 调用 API 的 VBA 代码返回 XML 而不是 JSON
- r - 使用 if else 语句 R 创建一个新字段
- python - 为模拟 assert_call_once_with() 指定“类 Foo 的任何实例”?
- javascript - 我可以使用 PrevState 让我的组件在刷新时保持用户输入吗?
- python - 在字典中查找字典中的最大值
- docker-compose - TestNG docker-compose 找不到本地主机 url
- shinyjs - 使用重置(shinyJS 功能)并一起单击然后观察单击的按钮的问题
- azure - Azure 应用程序网关未在后端池中显示来自其他 VNet 的 VM
- java - 如何在 swagger yaml 文件中使用属性定义 java 枚举?