如何使用 'requests' in Python (GET/POST) 执行成功登录 - 409 冲突
How to perform a successful login with 'requests' in Python (GET/POST) - 409 Conflict
通过本网站登录的正确方法是什么?
我想使用 requests
模块登录 here。
到目前为止我已经这样做了:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
import requests
from utils.user_agents import get_random_user_agent
class StudentsWebSession(QtCore.QThread):
def __init__(self, url, _url=None, username=None, password=None, payload=None):
QtCore.QThread.__init__(self)
self.session = requests.Session()
self.ua = get_random_user_agent('desktop')
self.headers_get_one = {
'host': 'studentsweb.teimes.gr',
'user-agent': self.ua,
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
'connection': 'keep-alive',
'upgrade-insecure-requests': '1'
}
self.headers_post_one = {
'host': 'studentsweb.teimes.gr',
'user-agent': self.ua,
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
'referer': 'https://studentsweb.teimes.gr/unistudent/login.asp',
'content-type': 'application/x-www-form-urlencoded',
'connection': 'keep-alive',
'upgrade-insecure-requests': '1'
}
self.headers_get_two = {
'host': 'studentsweb.teimes.gr',
'user-agent': self.ua,
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
'referer': 'https://studentsweb.teimes.gr/unistudent/login.asp',
'connection': 'keep-alive',
'upgrade-insecure-requests': '1'
}
self.url = url
self._url = _url
self.username = username
self.password = password
self.payload = payload
def __del__(self):
self.wait()
def get(self):
with self.session as s:
if not self.payload:
self.payload = {
'userName': self.username,
'pwd': self.password,
'submit1': 'Login',
'loginTrue': 'login'
}
r = s.get(self.url, headers=self.headers_get_one,
params={'lang': 'en-us'})
print(r.content.decode('cp1253'))
#print(r.url)
r = s.post(self.url, headers=self.headers_post_one,
data=self.payload)
#print(r.content.decode('cp1253'))
#print(r.url)
#r = s.get(self._url, headers=self.headers_get_two)
#print(r.content.decode('cp1253'))
#print(r.url)
def run(self):
self.get()
我是这样初始化的:
stweb = StudentsWebSession(db.get('studentsweb', {}).get('url'),
db.get('studentsweb', {}).get('url_after'),
self.extract_username_from_email(),
self.form_password.text())
stweb.start()
其中 db
是一个包含所有所需信息的字典。
db.get('studentsweb', {}).get('url')
db.get('studentsweb', {}).get('url_after')
因此,我收到了一份 HTML 文件,标题如下(409 http 代码)
<title>409 Conflict</title>
我认为您必须执行一个简单的 GET 请求来存储 cookie,然后使用所有必需的负载、headers 和 cookie 执行 POST 请求。然后,执行 GET 请求以接收所需的结果。
下面是上述请求的演示:
我不喜欢使用 selenium、无头浏览器以及 non-threadsafe 库
如果您需要更多信息,请随时向他们索取。
您如何初始化 StudentsWebSession
和调用 .get()
?假设 self.payload
是 None
并且它使用 .get
的 if
中定义的 self.payload
,那么:
'submit1'
应该是 'Είσοδος'
,而不是 '%C5%DF%F3%EF%E4%EF%F2'
。但是由于 '%C5...' 已经进行了表单编码,并且您想将其与表单数据一起发送,以防止 requests.post 再次对其进行表单编码,请发送 payload as a string:
There are times that you may want to send data that is not form-encoded. If you pass in a string instead of a dict, that data will be posted directly.
For example, the GitHub API v3 accepts JSON-Encoded POST/PATCH data:
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))
不要在headers_post_one
中指定'content-length'。
当您执行 with requests.Session() as s:
时,一旦登录完成,会话就会丢失。将其设为 with ... as self.session:
并在以后的请求中使用 self.session
。
POST 完成后似乎设置了一个随机 cookie。它是由表单提交上的 js 生成的。您需要查看它并重新创建 cookie 并将其与 post 请求一起发送。此外,它不是您以 GET 形式获得的 rcva_
cookie。只有前 64 个字符匹配:
Set-Cookie:rcva%5F=FCDB7353DAFB81C0DBDF61BD76CBBB0B4B6D6E39BC7381BEDB8A79416CBE4E9E16B9A45ABBE6175E103D0CCBBB848AF2C4000C03DDB27444CAFFBFAA7D6D6731A538DC737CE33D5A2B443E4CEF01911D08512B74B2C7062854F0857937DB92793E1FAE8518917CAD3EC03997942C7DB3FEBDD27840ECFF697EFDA93CC6CCF80A83F3A8487917131301BF32EF1B9E36CF; path=/
与发送的那个...
Cookie:ASPSESSIONIDCWCQTDDT=CINLLKKBNLNBKMPOMCPPKCFH; rcva%5F=FCDB7353DAFB81C0DBDF61BD76CBBB0B4B6D6E39BC7381BEDB8A79416CBE4E9EEF49F13C3FD75EBFCE526F8984772FCB4A39EE0A3563DCAFD81050CAE03092E7B0AF2A5ABB6EBE0CADF06AB9F405A1AABBC521DEF74668744D66327E2F0C6CEB17EC3757B623A057444FF457A13D97DC7438CA446840E71C358E5D1F942566602B3E31061989C8DC5A7F1F846A0680BD
此外,发送的表单数据也有部分 cookie 具有随机生成的名称,并且只有前 32 个字符匹配:
c4134bbd3f648974b8ecdc237b5ebe2fd:FCDB7353DAFB81C0DBDF61BD76CBBB0BD085AD5A217BAD80C33CC6A27FDAD06DC7E81968BC5C18767860BB38E4285D9A9E02BEE0FDFF9C7B133FAC5FE6BFAC04ED88B3038686B94083AB20C44C9CB94CA067CC376892B9F9E91514A73C659E5BD05BF72B2DC8BCD5AD399D191CC58818
不要执行 self.cookies = r.cookies
,因为请求将管理该会话本身中的 cookie(通过重新发送收到的 cookie)。你也不需要明确提供它,除非你想添加一个单独的 cookie,并且应该只有那些项目(以前收到的 cookie 无论如何都会被发送)。
注意:您需要弄清楚js在提交表单时是如何设置cookie的。然后在 Python 中重新创建它或...使用 selenium/or 其他无头浏览器 - 你说过你不想这样做。
表单数据中的'lang': 'en-us'
可能达不到预期的效果,可能会导致错误。要按照网站的方式进行设置,请在每个请求中为页面设置参数:r.get(... params={'lang': 'en-us'} ...)
。当你这样做时,'submit1'
应该是 'Login'
,对于上面的 #1。
这并未提供您登录所需的所有信息,但您首先必须进行上述更改,然后查看您获得的信息。
通过本网站登录的正确方法是什么?
我想使用 requests
模块登录 here。
到目前为止我已经这样做了:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
import requests
from utils.user_agents import get_random_user_agent
class StudentsWebSession(QtCore.QThread):
def __init__(self, url, _url=None, username=None, password=None, payload=None):
QtCore.QThread.__init__(self)
self.session = requests.Session()
self.ua = get_random_user_agent('desktop')
self.headers_get_one = {
'host': 'studentsweb.teimes.gr',
'user-agent': self.ua,
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
'connection': 'keep-alive',
'upgrade-insecure-requests': '1'
}
self.headers_post_one = {
'host': 'studentsweb.teimes.gr',
'user-agent': self.ua,
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
'referer': 'https://studentsweb.teimes.gr/unistudent/login.asp',
'content-type': 'application/x-www-form-urlencoded',
'connection': 'keep-alive',
'upgrade-insecure-requests': '1'
}
self.headers_get_two = {
'host': 'studentsweb.teimes.gr',
'user-agent': self.ua,
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'accept-language': 'en-US,en;q=0.5',
'accept-encoding': 'gzip, deflate, br',
'referer': 'https://studentsweb.teimes.gr/unistudent/login.asp',
'connection': 'keep-alive',
'upgrade-insecure-requests': '1'
}
self.url = url
self._url = _url
self.username = username
self.password = password
self.payload = payload
def __del__(self):
self.wait()
def get(self):
with self.session as s:
if not self.payload:
self.payload = {
'userName': self.username,
'pwd': self.password,
'submit1': 'Login',
'loginTrue': 'login'
}
r = s.get(self.url, headers=self.headers_get_one,
params={'lang': 'en-us'})
print(r.content.decode('cp1253'))
#print(r.url)
r = s.post(self.url, headers=self.headers_post_one,
data=self.payload)
#print(r.content.decode('cp1253'))
#print(r.url)
#r = s.get(self._url, headers=self.headers_get_two)
#print(r.content.decode('cp1253'))
#print(r.url)
def run(self):
self.get()
我是这样初始化的:
stweb = StudentsWebSession(db.get('studentsweb', {}).get('url'),
db.get('studentsweb', {}).get('url_after'),
self.extract_username_from_email(),
self.form_password.text())
stweb.start()
其中 db
是一个包含所有所需信息的字典。
db.get('studentsweb', {}).get('url')
db.get('studentsweb', {}).get('url_after')
因此,我收到了一份 HTML 文件,标题如下(409 http 代码)
<title>409 Conflict</title>
我认为您必须执行一个简单的 GET 请求来存储 cookie,然后使用所有必需的负载、headers 和 cookie 执行 POST 请求。然后,执行 GET 请求以接收所需的结果。
下面是上述请求的演示:
我不喜欢使用 selenium、无头浏览器以及 non-threadsafe 库
如果您需要更多信息,请随时向他们索取。
您如何初始化 StudentsWebSession
和调用 .get()
?假设 self.payload
是 None
并且它使用 .get
的 if
中定义的 self.payload
,那么:
'submit1'
应该是'Είσοδος'
,而不是'%C5%DF%F3%EF%E4%EF%F2'
。但是由于 '%C5...' 已经进行了表单编码,并且您想将其与表单数据一起发送,以防止 requests.post 再次对其进行表单编码,请发送 payload as a string:There are times that you may want to send data that is not form-encoded. If you pass in a string instead of a dict, that data will be posted directly.
For example, the GitHub API v3 accepts JSON-Encoded POST/PATCH data:
>>> import json >>> url = 'https://api.github.com/some/endpoint' >>> payload = {'some': 'data'} >>> r = requests.post(url, data=json.dumps(payload))
不要在
headers_post_one
中指定'content-length'。当您执行
with requests.Session() as s:
时,一旦登录完成,会话就会丢失。将其设为with ... as self.session:
并在以后的请求中使用self.session
。POST 完成后似乎设置了一个随机 cookie。它是由表单提交上的 js 生成的。您需要查看它并重新创建 cookie 并将其与 post 请求一起发送。此外,它不是您以 GET 形式获得的
rcva_
cookie。只有前 64 个字符匹配:Set-Cookie:rcva%5F=FCDB7353DAFB81C0DBDF61BD76CBBB0B4B6D6E39BC7381BEDB8A79416CBE4E9E16B9A45ABBE6175E103D0CCBBB848AF2C4000C03DDB27444CAFFBFAA7D6D6731A538DC737CE33D5A2B443E4CEF01911D08512B74B2C7062854F0857937DB92793E1FAE8518917CAD3EC03997942C7DB3FEBDD27840ECFF697EFDA93CC6CCF80A83F3A8487917131301BF32EF1B9E36CF; path=/
与发送的那个...
Cookie:ASPSESSIONIDCWCQTDDT=CINLLKKBNLNBKMPOMCPPKCFH; rcva%5F=FCDB7353DAFB81C0DBDF61BD76CBBB0B4B6D6E39BC7381BEDB8A79416CBE4E9EEF49F13C3FD75EBFCE526F8984772FCB4A39EE0A3563DCAFD81050CAE03092E7B0AF2A5ABB6EBE0CADF06AB9F405A1AABBC521DEF74668744D66327E2F0C6CEB17EC3757B623A057444FF457A13D97DC7438CA446840E71C358E5D1F942566602B3E31061989C8DC5A7F1F846A0680BD
此外,发送的表单数据也有部分 cookie 具有随机生成的名称,并且只有前 32 个字符匹配:
c4134bbd3f648974b8ecdc237b5ebe2fd:FCDB7353DAFB81C0DBDF61BD76CBBB0BD085AD5A217BAD80C33CC6A27FDAD06DC7E81968BC5C18767860BB38E4285D9A9E02BEE0FDFF9C7B133FAC5FE6BFAC04ED88B3038686B94083AB20C44C9CB94CA067CC376892B9F9E91514A73C659E5BD05BF72B2DC8BCD5AD399D191CC58818
不要执行
self.cookies = r.cookies
,因为请求将管理该会话本身中的 cookie(通过重新发送收到的 cookie)。你也不需要明确提供它,除非你想添加一个单独的 cookie,并且应该只有那些项目(以前收到的 cookie 无论如何都会被发送)。注意:您需要弄清楚js在提交表单时是如何设置cookie的。然后在 Python 中重新创建它或...使用 selenium/or 其他无头浏览器 - 你说过你不想这样做。
表单数据中的'lang': 'en-us'
可能达不到预期的效果,可能会导致错误。要按照网站的方式进行设置,请在每个请求中为页面设置参数:r.get(... params={'lang': 'en-us'} ...)
。当你这样做时,'submit1'
应该是'Login'
,对于上面的 #1。
这并未提供您登录所需的所有信息,但您首先必须进行上述更改,然后查看您获得的信息。