DrissionPage搞定京东滑块

声明

本文章中所有内容仅供学习交流使用,不用于其他任何目的,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责。
若有侵权,请在评论区联系作者立即删除!

前言

本文章主要是我结合自己的工作经验,讲解一下基于 DrissionPage 如何实现京东网页端登录流程,涉及到一些 DrissionPage 的简单使用,滑块算法和图像识别算法的说明和使用。如有更专业高效的方案欢迎在评论区探讨,有不正之处还望指正。

一、DrissionPage 启动浏览器

参考官方文档 DrissionPage 使用文档,先将浏览器启动起来。

1.1 安装 DrissionPage

 pip install DrissionPage 

我使用的版本
在这里插入图片描述

1.2 自动化打开浏览器

使用最简单的配置,成功打开一个新的浏览器。

import time
from DrissionPage import Chromium, ChromiumOptions
def new_browser():
    co = ChromiumOptions()
    # 指定其他端口,新开一个浏览器,不影响当前已打开的浏览器的使用
    co.set_paths(local_port=10086)
    # 设置启动时最大化
    co.set_argument("--start-maximized")
    # 设置浏览器可视窗口大小
    co.set_argument("--window-size=1920,1080")
    # 以该配置创建页面对象
    browser = Chromium(addr_or_opts=co)
    time.sleep(10)
    # 关闭浏览器
    browser.quit()
if __name__ == "__main__":
    new_browser()

1.3 登录主流程实现

写好登录流程的主要逻辑,如下所示:

import time
from DrissionPage import Chromium, ChromiumOptions

class JDCrawler:
    def new_browser(self):
        co = ChromiumOptions()
    	# 指定其他端口,新开一个浏览器,不影响当前已打开的浏览器的使用
        co.set_paths(local_port=10086)
        # 设置启动时最大化
        co.set_argument("--start-maximized")
        # 设置浏览器可视窗口大小
        co.set_argument("--window-size=1920,1080")
        # 以该配置创建页面对象
        browser = Chromium(addr_or_opts=co)
        return browser

    def login(self, page):
        print("============= 账号密码登录页面加载完成 =============")
        # TODO: 实现具体登录逻辑


if __name__ == "__main__":
    print("============= 程序开始 =============")
    jd_crawler = JDCrawler()

    try:
        browser = jd_crawler.new_browser()
        page = browser.latest_tab

        print("============= 准备进入登录页 =============")
        page.get(JD_LOGIN_URL)
        time.sleep(3)
        jd_crawler.login(page)
    except Exception as e:
        print("执行报错:", e)

    finally:
        print("============= 准备关闭浏览器 =============")
        page.close()
        browser.quit()

    print("============= 程序退出 =============")

二、分析登录流程

我们打开进入 京东登录页,输入账号密码会发现整体登录流程可以拆解为这几个步骤:

  1. 输入账号
  2. 输入密码
  3. 点击登录
  4. 滑块校验
  5. 校验通过,登录完成
    在这里插入图片描述

2.1 输入账号

我这里根据 css 选择器 规则 #loginname 定位到账号输入框元素。
在这里插入图片描述
通过 DP 提取元素并输入账户名:page.ele("#loginname", timeout=DEFAULT_TIMEOUT).clear().input(JD_ACCOUNT),其中 clear() 是为了清除输入框内容。

2.2 输入密码

css 选择器 规则 #nloginpwd 定位到密码输入框元素。
在这里插入图片描述
通过 DP 输入密码:page.ele("#nloginpwd", timeout=DEFAULT_TIMEOUT).clear().input(JD_PASS)

2.3 点击提交

page.ele("#loginsubmit", timeout=DEFAULT_TIMEOUT).click() 实现点击操作,提交账号。
在这里插入图片描述

2.4 提交账户登录

点击登录后因为风控规则可能会出现滑块,需要检查一下是出现了滑块,再进行后续操作。

在这里插入图片描述
检查代码:

 slider_ele = page.ele('xpath://div[@class="JDJRV-suspend-slide"]',timeout=DEFAULT_TIMEOUT)
 if slider_ele and slider_ele.states.is_displayed:
     # TODO: 处理滑块

三、滑块校验

3.1 获取背景图片

利用 xpath 规则://div[@class="JDJRV-bigimg"]/img获取背景图片,DP 提取元素:page.ele('xpath://div[@class="JDJRV-bigimg"]/img')
在这里插入图片描述

3.2 获取缺口图片

page.ele('xpath://div[@class="JDJRV-smallimg"]/img')
在这里插入图片描述

3.3 定位滑块按钮位置

page.ele('xpath://div[@class="JDJRV-slide-inner JDJRV-slide-btn"]')
在这里插入图片描述

3.4 图像识别,计算出移动距离

3.4.1 转换文件格式

网页的图片是base64格式,需要将图片转成 OpenCV 可以处理的图像格式。

 @staticmethod
 def img2cv(img_data):
     """openCV 读取 base64 图片"""
     data = img_data.replace("data:image/png;base64,", "").replace(
         "data:image/jpg;base64,", ""
     )
     img_data = base64.b64decode(data)
     # 将图片的二进制数据转换为图像的原始字节数据;np.uint8 指定将数据解析为 8 位无符号整数
     img_np = np.frombuffer(img_data, np.uint8)
     # 图像的原始字节数据解码为 OpenCV 可以处理的图像格式
     img = cv2.imdecode(img_np, cv2.IMREAD_COLOR)
     return img

3.4.2 滑动距离识别

完成了对图片的处理之后,我们继续利用 OpenCV 来识别背景图片和缺口图片之间的距离。

def img2xy(bg_img, tp_img):
    """
    识别图片缺口位置
    Args:
        bg_img : 背景图片
        tp_img : 缺口图片
    Returns:
        返回缺口的左上角、右下角坐标
    """
    # 边缘检测:利用边缘检测算法 cv2.Canny 识别图片的边缘
    bg_edge = cv2.Canny(bg_img, 100, 200)
    # 100 和 200 是 Canny 算法的阈值参数,用于控制边缘检测的灵敏度
    tp_edge = cv2.Canny(tp_img, 100, 200)
    # 转换图片格式:将边缘检测结果从灰度图转换为 RGB 格式
    bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
    tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
    # 缺口匹配
    res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
    # 寻找最优匹配
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    # 左上角点的坐标
    tl = max_loc
    # th 和 tw 分别是缺口图片的高度和宽度
    th, tw = tp_pic.shape[:2]
    # 右下角点的坐标
    br = (tl[0] + tw, tl[1] + th)
    # 返回缺口区域的左上角坐标 (x1, y1) 和右下角坐标 (x2, y2)
    return max_loc, br

上面是图片缺口识别的算法,最终返回左上角坐标和右下角坐标,在登录流程中,我们只需要左上角坐标 max_locx 坐标,这个就是我们要的滑动距离 distance
需要注意的是网页会存在对图片进行不同比例的渲染,这时候移动的距离也要等比例延长或者缩短,才能移动到目标位置,这个比例系数 coefficient 我们可以通过观察图片的 Rendered Size(渲染尺寸)Intrinsic Size(固有尺寸) 的比值得出,比如这里 Rendered Size / Intrinsic Size = 0.95,因此我们真实的滑动距离为 distance * 0.95
在这里插入图片描述

3.5 生成滑动轨迹

3.5.1 公式原理

  • 位移公式:s = v₀t + ½at²
  • 速度公式:v = v₀ + at
  • s 表示距离;v₀ 表示初速度;v 表示末速度;t 表示时间;a 表示加速度
    利用上面两个公式,模拟人在滑动滑块时先加速后减速的行为,s 的值则是上面步骤得出的 distance,加速度 a 则根据我们调整不同的数值,观察滑动的情况来优化。

3.5.2 轨迹生成示例代码

数据需要根据实际滑动的情况来调整,直到效果跟人滑动出的效果差不多,则证明这个轨迹坐标是有效的。

def handle_distance(distance):
    """生成轨迹"""

    v = 0  # 初始速度为 0
    t = 2  # 每 2 秒生成一个坐标
    forward_tracks = []  # 保存坐标值 x

    current = 0  # 当前已滑动的距离
    # 加速和减速的距离转折点
    mid = "给一个距离"
    while current < distance:
        if current < mid:
            a = "给一个加速数值"
        else:
            a = "给一个减速数值"

        s = v * t + 0.5 * a * (t**2)    # 位移公式
        v = v + a * t   # 速度公式
        current += s
        forward_tracks.append(round(s))

3.6 DrissionPage 实现拖拽

利用 DP 的动作链实现鼠标拖拽。

 def slider(
     self, page, bg_ele_xpath, patch_ele_xpath, button_ele_xpath, coefficient
 ):
     """
     移动滑块
     Args:
         page (string): page对象
         bg_ele_xpath (string): 背景图片选择器表达式
         patch_ele_xpath (string): 缺口图片选择器表达式
         button_ele_xpath (string): 拖动按钮选择器表达式
         coefficient (float): 图片缩放比例系数
     """

     print("============= 识别图片 =============")
     # 识别缺口距离
     picture_distance = self.recognize_position(page, bg_ele_xpath, patch_ele_xpath)
     distance = picture_distance * coefficient  # 调整滑动距离
     tracks = self.handle_distance(distance)  # 生成轨迹坐标

     button = page.ele(button_ele_xpath)  # 获取滑块按钮
     ac = Actions(page)  # 动作链对象
     print("============= 开始移动滑块 =============")
     ac.move_to(button)  # 移动鼠标到滑块按钮位置
     ac.hold(button)  # 按住滑块
     # 移动滑块
     for pos in tracks:
         y = random.uniform(-1, 2)  # 模拟鼠标上下晃动
         ac.move(pos, y)  # 移到坐标位置
     # 模拟停顿
     time.sleep(random.uniform(0.5, 0.8))
     ac.release(button)  # 松开按钮

四、验证效果

滑块校验通过。
在这里插入图片描述

5、交流群

不会经常刷博客,有需要者可以加本人,搜索 LOVE_SELF_AD_LIFE,进逆向群聊,一起探讨技术
在这里插入图片描述

<think>好的,我需要帮助用户找到DrissionPage的相关文档,包括使用说明和API参考。首先,用户提到的引用[1]和[2]已经指出DrissionPage的文档是重要的资源,特别是官方文档,里面详细介绍了安装、配置和使用方法。用户需要具体的文档链接或获取方式,但根据提供的引用,似乎没有直接给出网址。 接下来,我应该检查提供的引用内容。引用[1]提到,使用时应参考官方文档或源码,引用[2]强调官方文档的重要性,包括API参考和快速入门指南。但用户提供的引用[3]是关于钉钉的SDK,可能与DrissionPage无关,可能是误引。 由于用户给出的引用中没有直接的文档链接,我需要建议用户通过常规途径查找,比如访问DrissionPage的GitHub仓库,通常开源项目会在GitHub的README或Wiki部分提供文档链接。另外,用户可以通过搜索引擎查找“DrissionPage 官方文档”,或者访问Python的包索引页面PyPI,查找DrissionPage的项目页面,那里通常会有文档链接。 此外,用户可能需要安装DrissionPage后,通过查看内置的文档字符串或使用help()函数获取API信息。例如,在Python中导入DrissionPage后,使用help(DrissionPage)或查看相关类的文档。 还需要提醒用户注意,由于DrissionPage可能不是非常流行的库,确保他们访问的是最新和官方的文档,避免使用过时的信息。如果用户无法找到,建议他们联系社区支持或查看项目的Issue部分寻求帮助。 总结步骤: 1. 访问GitHub搜索DrissionPage仓库。 2. 检查PyPI页面获取文档链接。 3. 使用搜索引擎查找官方资源。 4. 利用Python内置帮助功能。 5. 提醒用户验证文档的时效性和官方性。</think>以下是关于DrissionPage文档和API参考的说明: ### DrissionPage文档获取方式 1. **官方GitHub仓库** DrissionPage作为开源项目,其文档通常托管在GitHub仓库的`README`或`Wiki`中。可通过搜索"DrissionPage GitHub"找到项目主页[^2]。 2. **PyPI页面指引** 在Python包索引(PyPI)的DrissionPage页面(可通过`pip show drissionpage`获取路径)中,通常包含文档链接和基础使用示例[^1]。 3. **内置文档查询** 安装后可通过Python交互环境直接查看: ```python import drissionpage help(drissionpage) # 查看模块帮助 help(drissionpage.SessionPage) # 查看具体类方法 ``` ### 核心内容覆盖范围 官方文档一般包含: - 安装与配置要求 - 快速入门教程 - API详细参数说明 - 实战案例(如数据抓取、自动化操作) - 常见问题排查
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值