0%

Python利用selenium实现淘宝自动登录

由于最近在做一些关于淘宝的项目,需要用到淘宝的cookie,所以就想写个自动登录的脚本。本来以为利用selenium来做是件很简单的事情,没想到陷入了大坑。

在使用selenium登录淘宝的时候,发现滑动认证一直不通过,手动滑动也不通过。经过一番搜索后发现很多网站对selenium都有检测机制,如检测是否存在特有标识$cdc_lasutopfhvcZLmcflwindow.navigator.webdriver等。根据这条线索,我在淘宝的js里找到了相关的检测代码

既然找到了原因就想办法解决它,根据搜索发现$cdc_asdjflasutopfhvcZLmcfl是chromedriver中定义好的变量,我们只需要将这个变量名改成其他的就好了。变量名修改教程在《Can a website detect when you are using selenium with chromedriver?》,若大家嫌麻烦,也可以选择下载我修改好的chromedriver,但是要注意chromedriver和chrome的版本需一致。window.navigator.webdriver这个就比较麻烦了,这东西没办法通过修改driver来解决,只用修改原网站代码解决,我这里的解决方案是利用mitmproxy做中间人代理将对应的屏蔽代码注入到原网站中。虽然有点曲线救国,但是我目前还没有比较好的方法来解决这个问题。如果大家有更好的建议也欢迎留言。

配置mitmproxy

  • 自定义过滤器

    1
    2
    3
    4
    5
    6
    7
    TARGET_URL = 'https://g.alicdn.com/secdev/sufei_data/3.6.8/index.js'
    INJECT_TEXT = 'Object.defineProperties(navigator,{webdriver:{get:() => false}});'

    def response(flow):
    if flow.request.url.startswith(TARGET_URL):
    flow.response.text = INJECT_TEXT + flow.response.text
    print('注入成功')
  • 启动代理

    1
    mitmdump -s HttpProxy.py -p 9000

淘宝自动登录源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import time

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options

TB_LOGIN_URL = 'https://login.taobao.com/member/login.jhtml'
CHROME_DRIVER = './browser/chromedriver.exe'


class SessionException(Exception):
"""
会话异常类
"""

def __init__(self, message):
super().__init__(self)
self.message = message

def __str__(self):
return self.message


class SessionDriver:

def __init__(self):
self.browser = None

def get_session(self, username, password):
cookies = {}
try:
self.__init_browser()
self.__switch_to_password_mode()
time.sleep(0.5)
self.__write_username(username)
time.sleep(0.5)
self.__write_password(password)
time.sleep(0.5)
if self.__lock_exist():
self.__unlock()
self.__submit()
# 提取cookie
for cookie in self.browser.get_cookies():
cookies[cookie['name']] = cookie['value']
finally:
self.__destroy_browser()

return cookies

def __switch_to_password_mode(self):
"""
切换到密码模式
:return:
"""
if self.browser.find_element_by_id('J_QRCodeLogin').is_displayed():
self.browser.find_element_by_id('J_Quick2Static').click()

def __write_username(self, username):
"""
输入账号
:param username:
:return:
"""
username_input_element = self.browser.find_element_by_id('TPL_username_1')
username_input_element.clear()
username_input_element.send_keys(username)

def __write_password(self, password):
"""
输入密码
:param password:
:return:
"""
password_input_element = self.browser.find_element_by_id("TPL_password_1")
password_input_element.clear()
password_input_element.send_keys(password)

def __lock_exist(self):
"""
判断是否存在滑动验证
:return:
"""
return self.__is_element_exist('#nc_1_wrapper') and self.browser.find_element_by_id(
'nc_1_wrapper').is_displayed()

def __unlock(self):
"""
执行滑动解锁
:return:
"""
bar_element = self.browser.find_element_by_id('nc_1_n1z')
ActionChains(self.browser).drag_and_drop_by_offset(bar_element, 350, 0).perform()
time.sleep(0.5)
self.browser.get_screenshot_as_file('error.png')
if self.__is_element_exist('.errloading > span'):
error_message_element = self.browser.find_element_by_css_selector('.errloading > span')
error_message = error_message_element.text
self.browser.execute_script('noCaptcha.reset(1)')
raise SessionException('滑动验证失败, message = ' + error_message)

def __submit(self):
"""
提交登录
:return:
"""
self.browser.find_element_by_id('J_SubmitStatic').click()
time.sleep(0.5)
if self.__is_element_exist("#J_Message"):
error_message_element = self.browser.find_element_by_css_selector('#J_Message > p')
error_message = error_message_element.text
raise SessionException('登录出错, message = ' + error_message)

def __init_browser(self):
"""
初始化selenium浏览器
:return:
"""
options = Options()
# options.add_argument("--headless")
options.add_argument('--proxy-server=http://127.0.0.1:9000')
self.browser = webdriver.Chrome(executable_path=CHROME_DRIVER, options=options)
self.browser.implicitly_wait(3)
self.browser.maximize_window()
self.browser.get(TB_LOGIN_URL)

def __destroy_browser(self):
"""
销毁selenium浏览器
:return:
"""
if self.browser is not None:
pass
# self.browser.quit()

def __is_element_exist(self, selector):
"""
检查是否存在指定元素
:param selector:
:return:
"""
try:
self.browser.find_element_by_css_selector(selector)
return True
except NoSuchElementException:
return False


def get_session(username, password):
return SessionDriver().get_session(username, password)