Проспект Обзор
я здесьМысли, вызванные входом в NuggetsВ этой статье анализируются некоторые знания о входе в Nuggets.Хотя можно напрямую вызвать интерфейс входа в систему после сборки параметров входа через программу, производительность по затратам слишком низкая. Кроме того, если политика входа изменена, она может оказатьсяБамбуковая корзина пуста, белый занят.
Итак, сегодня подумайте об этом с другой стороны и используйте Selenium (инструмент для тестирования веб-приложений) для завершения входа в систему.
техническое образование
Все, что вам нужно, — это краткое введение в технологии, используемые в этой статье. Конечно, не беда, если вы не разбираетесь в этих технологиях, и это не мешает нам смотреть вниз.
- Передовые знанияВведение в файлы cookie
- Передовые знанияУчебник XPath
- Тестирование веб-приложенийРуководство пользователя Python Selenium
Реализовать вход
Давайте посмотрим непосредственно на то, как выполнить вход в систему с помощью Selenium, который примерно разделен на следующие шаги:
- Получите скользящий проверочный код, имитируя работу браузера
- Проведите код подтверждения
- а. Рассчитайте расстояние, на которое слайдер должен скользить
- Б. Имитируйте перетаскивание браузера, чтобы завершить распознавание скользящего кода подтверждения.
- Имитация браузера для входа
1. Знакомство с окружающей средой
- Аппаратное обеспечение Mac
- Язык Python3
- Редактор PyCharm
- Браузер Хром
2. Получите скользящий код подтверждения
Анализируя процесс входа в систему, можно определить, что проверочный код слайдера состоит из двух картинок. Одно изображение слайдера, а другое фоновое изображение. Здесь вам нужно только использовать Selenium для имитации работы браузера, чтобы завершить переход на страницу перед входом в систему и, наконец, получить URL-адрес изображения кода подтверждения.На этом этапе не так уж много сложностей.Код выглядит следующим образом:
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
driver = webdriver.Chrome(executable_path="./chromedriver")
driver.get("https://juejin.cn/")
# 代码中的注释为从首页开始到获取URL的每一步骤,可以自己打开浏览器尝试
# 点击登录按钮
login_button = driver.find_element(By.XPATH, '''//button[text()="登录"]''')
ActionChains(driver).move_to_element(login_button).click().perform()
time.sleep(2)
# 选择账号密码登录
other_login_span = driver.find_element(By.XPATH, '''//span[text()="
其他登录方式
"]''')
ActionChains(driver).move_to_element(other_login_span).click().perform()
time.sleep(2)
# 填充用户名密码
username_input = driver.find_element(By.XPATH, '//input[@name="loginPhoneOrEmail"]')
password_input = driver.find_element(By.XPATH, '//input[@name="loginPassword"]')
username_input.send_keys("") # 掘金的账号
password_input.send_keys("") # 掘金的密码
# 点击登录
login_button = driver.find_element(By.XPATH, '''//button[text()="
登录
"]''')
ActionChains(driver).move_to_element(login_button).click().perform()
time.sleep(2)
# 获取滑块验证码图片
verify_image1 = driver.find_element(By.XPATH, '''//img[@id="captcha-verify-image"]/../img[1]''')
verify_image2 = driver.find_element(By.XPATH, '''//img[@id="captcha-verify-image"]/../img[2]''')
verify_image1_src = verify_image1.get_attribute("src")
verify_image2_src = verify_image1.get_attribute("src")
3. Определите проверочный код слайдера.
На следующем рисунке показан соответствующий ползунок, фоновое изображение и соответствующий процесс распознавания.
Проще говоря: процесс распознавания заключается в перетаскивании изображения, соответствующего ползунку, в углубленное место на фоновом изображении.
3.1 Координаты ползунка позиционирования
При этом используется сопоставление шаблонов Python Opencv. Сопоставление шаблонов — это поиск небольших участков во всей области изображения, которые соответствуют заданному субизображению. Процесс примерно на изображении, которое нужно обнаружить, слева направо, сверху вниз, чтобы вычислить степень совпадения между шаблонным изображением и перекрывающимися субизображениями.Чем больше степень совпадения, тем больше вероятность того, что два подобные.
cv2.matchTemplateПервые два параметра — это изображение шаблона и фоновое изображение соответственно, а третий параметр — это алгоритм сопоставления, который используется здесь TM_CCOEFF_NORMED (сопоставление стандартного коэффициента корреляции). Функция возвращает результирующий набор (многомерный массив), состоящий из комбинации результатов сравнения в каждой позиции.
Например, если размер входного изображения (исходного изображения) — W H, а размер шаблона — w h, размер возвращаемого значения равен (W-w+1)*(H-h+1).
# 这里需要注意 slider_pic background_pic 是灰度化 二值化后的图片
# 读取滑块
slider_pic = cv2.imread("slider_pic")
# 读取背景图
background_pic = cv2.imread("background_pic")
# 比较两张图的重叠区域
result = cv2.matchTemplate(slider_pic, background_pic, cv2.TM_CCOEFF_NORMED)
# 获取图片的缺口位置 top, left 为滑块相对于图片左上角的位置
top, left = np.unravel_index(result.argmax(), result.shape)
Примечание:np.unravel_index(result.argmax(), result.shape)Получить значение координаты, соответствующее максимальному значению многомерного массива (соответствующее координате пикселя найденного изображения). Поскольку движение ползунка учитывает только горизонтальное движение, оно здесь напрямую опущено.topВот и все.
3.2 Создание скользящей дорожки
Хорошо известно, что людям трудно работать с одинаковой скоростью при перетаскивании изображений, поэтому необходимо использовать программу для имитации перетаскивания человеком. Делает траекторию движения изображения более беспорядочной. Идея и код здесь взяты изЭкстремальное скользящее распознавание проверочного кода
Поскольку ползунок нельзя перетащить в указанное положение за один раз, здесь необходимо имитировать обычное перетаскивание. Следовательно, логика перетаскивания состоит в том, чтобы выполнить равномерное ускорение для переднего ползуна и равномерное замедление для заднего ползунка.Проверку можно выполнить, используя формулу ускорения физики.
滑块滑动的加速度用 a 来表示,当前速度用 v 表示,初速度用 v0 表示,位移用 x 表示,所需时间用 t 表示,它们之间满足如下关系:
x = v0 * t + 0.5 * a * t * t
v = v0 + a * t
# 其中 track 为滑块拖动的轨迹
def get_track(distance): # distance为传入的总距离
# 移动轨迹
track = []
# 当前位移
current = 0
# 减速阈值
mid = distance * 4 / 5
# 计算间隔
t = 0.2
# 初速度
v = 1
while current < distance:
if current < mid:
# 加速度
a = 4
else:
# 加速度
a = -3
v0 = v
# 当前速度
v = v0 + a * t
# 移动距离
move = v0 * t + 1 / 2 * a * t * t
# 当前位移
current += move
# 加入轨迹
track.append(round(move))
return track
4. Работа слайдера страницы
На предыдущем шаге opencv использовался для завершения позиционирования проверочного кода ползунка и генерации траектории.Следующее — для завершения перетаскивания ползунка на странице.
# 定位到移动按钮
verify_div = self.driver.find_element(By.XPATH, '''//div[@class="sc-kkGfuU bujTgx"]''')
# 按下鼠标左键
ActionChains(self.driver).click_and_hold(verify_div).perform()
time.sleep(0.5)
# 遍历轨迹进行滑动
for t in track:
time.sleep(0.01)
ActionChains(self.driver).move_by_offset(xoffset=t, yoffset=0).perform()
# 释放鼠标 完成拖拽
ActionChains(self.driver).release(on_element=verify_div).perform()
Примечание: в кодеtime.sleep()Это для коротких пауз в операциях со страницами, а не для последовательных быстрых операций.
5. Получить куки
После завершения идентификации проверочного кода ползунка страница успешно зарегистрирована и успешно перепрыгнула.На данный момент вам нужно только получитьjuejin.cn Можно использовать соответствующий файл cookie.
# 获取当前页面 cookie
driver.get_cookies()
'''
[{'domain': '.juejin.cn',
'expiry': 1632902943,
'httpOnly': False,
'name': 'MONITOR_WEB_ID',
'path': '/',
'secure': False,
'value': 'e7fa2492-...-8ff5e04c6727'},
# ...
{'domain': '.juejin.cn',
'expiry': 1630310943,
'httpOnly': True,
'name': 'sessionid_ss',
'path': '/',
'sameSite': 'None',
'secure': True,
'value': 'bfac25b956...f7be812054f'},
{'domain': '.juejin.cn',
'expiry': 1630310943,
'httpOnly': True,
'name': 'sessionid',
'path': '/',
'secure': False,
'value': 'bfac25b956b...42f7be812054f'},
]
'''
постскриптум
Если вы считаете, что мой проект полезен для вас,Добро пожаловать в один клик три раза ❤️❤️❤️, Оригинальность не так просто.
Посмотреть весь код для этого проекта GitHub , добро пожаловать в звездную вилку.
Точки для оптимизации
- Многократное локальное хранение и считывание изображений занимает много времени и оптимизировано для обработки изображений непосредственно в памяти.
- Код свален в один файл, оптимизированный для разделения разных объектов по функциям.
- Для определения вероятности ошибок сюда необходимо добавить механизм повторной попытки ошибки (как показано на рисунке ниже).