python 模拟登录B站的示例代码


Posted in Python onDecember 15, 2020

需要将模拟的浏览器,添加到环境变量中哦。代码中用的是chrome

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import TimeoutException
from PIL import Image
from io import BytesIO
from time import sleep
import random

"""
info:
author:CriseLYJ
github:https://github.com/CriseLYJ/
update_time:2019-3-7
"""


class BiliBili():
  """
  登陆B站, 处理验证码
  电脑的缩放比例需要为100%, 否则验证码图片的获取会出现问题
  """

  def __init__(self, username, password):
    """
    初始化
    """
    options = webdriver.ChromeOptions()
    # 设置为开发者模式,避免被识别
    options.add_experimental_option('excludeSwitches',
                    ['enable-automation'])
    self.browser = webdriver.Chrome(options=options)
    self.url = 'https://passport.bilibili.com/login'
    self.browser.get(self.url)
    self.wait = WebDriverWait(self.browser, 5, 0.2)
    self.username = username
    self.password = password

  def get_button(self):
    """
    获取滑动块, 并且返回
    :return: button
    """
    button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'gt_slider_knob')))
    return button

  def get_screenshot(self, button):
    """
    获取网页两次截图:
      1. 鼠标悬停于button的截图
      2. 鼠标点击button后的截图
    :param button: 滑动块
    :return: 两次截图的结果
    """
    ActionChains(self.browser).move_to_element(button).perform()
    screenshot1 = self.browser.get_screenshot_as_png()
    screenshot1 = Image.open(BytesIO(screenshot1))
    ActionChains(self.browser).click_and_hold(button).perform()
    screenshot2 = self.browser.get_screenshot_as_png()
    screenshot2 = Image.open(BytesIO(screenshot2))
    return (screenshot1, screenshot2)

  def get_position(self, button):
    """
    获取验证码图片的位置
    :return: 位置的四个点参数
    """
    ActionChains(self.browser).move_to_element(button).perform()
    img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'gt_box')))
    sleep(2)
    location = img.location
    size = img.size
    print(location, size)
    top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], \
                  location['x'] + size['width']
    return top, bottom, left, right

  def get_geetest_image(self, button, name1='captcha1.png', name2='captcha2.png'):
    """
    获取两次验证码的截图:
      1. 鼠标悬停于button的截图
      2. 鼠标点击button后的截图
    :param button: 滑动块
    :param name1: 原始验证码保存的名字
    :param name2: 缺块验证码保存的名字
    :return: 两次验证码截图的结果
    """
    top, bottom, left, right = self.get_position(button)
    print('验证码位置', top, bottom, left, right)
    screenshot = self.get_screenshot(button)
    captcha1 = screenshot[0].crop((left, top, right, bottom))
    captcha1.save(name1)
    captcha2 = screenshot[1].crop((left, top, right, bottom))
    captcha2.save(name2)
    return (captcha1, captcha2)

  def login(self):
    """
    打开浏览器,并且输入账号密码
    :return: None
    """
    self.browser.get(self.url)
    username = self.wait.until(EC.element_to_be_clickable((By.ID, 'login-username')))
    password = self.wait.until(EC.element_to_be_clickable((By.ID, 'login-passwd')))
    sleep(1)
    username.send_keys(self.username)
    sleep(1)
    password.send_keys(self.password)

  def is_pixel_equal(self, img1, img2, x, y):
    """
    判断两个像素是否相同
    :param img1: 原始验证码
    :param img2: 缺块验证码
    :param x: 像素点的x坐标
    :param y: 像素点的y坐标
    :return: 像素是否相同
    """
    pixel1 = img1.load()[x-1, y]
    pixel2 = img2.load()[x-1, y]
    threshold = 100
    if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
        pixel1[2] - pixel2[2]) < threshold:
      return True
    else:
      return False

  def get_gap(self, img1, img2):
    """
    获取缺口偏移量
    :param img1: 原始验证码
    :param img2: 缺块验证码
    :return: 第二个缺块的左侧的x坐标
    """
    left = 60 # 大致忽略掉第一个缺块
    for i in range(left, img1.size[0]):
      for j in range(img1.size[1]):
        if not self.is_pixel_equal(img1, img2, i, j):
          left = i
          return left
    return left

  def get_track(self, distance):
    """
    获取滑块移动轨迹的列表
    :param distance: 第二个缺块的左侧的x坐标
    :return: 滑块移动轨迹列表
    """
    track = []
    current = 0
    mid = distance * 2 / 3
    t = 0.2
    v = 0
    distance += 10 # 使滑块划过目标地点, 然后回退
    while current < distance:
      if current < mid:
        a = random.randint(1, 3)
      else:
        a = -random.randint(3, 5)
      v0 = v
      v = v0 + a * t
      move = v0 * t + 0.5 * a * t * t
      current += move
      track.append(round(move))
    for i in range(2):
      track.append(-random.randint(2, 3))
    for i in range(2):
      track.append(-random.randint(1, 4))
    print(track)
    return track

  def move_button(self, button, track):
    """
    将滑块拖动到指定位置
    :param button: 滑动块
    :param track: 滑块运动轨迹列表
    :return: None
    """
    ActionChains(self.browser).click_and_hold(button).perform()
    for i in track:
      ActionChains(self.browser).move_by_offset(xoffset=i, yoffset=0).perform()
      sleep(0.0005)
    sleep(0.5)
    ActionChains(self.browser).release().perform()

  def crack(self):
    """
    串接整个流程:
      1. 输入账号密码
      2. 获取滑动块
      3. 获取两张验证码图片
      4. 获取滑块移动轨迹
      5. 将滑块拖动至指定位置
    :return:
    """
    self.login()
    button = self.get_button()
    captcha = self.get_geetest_image(button)
    left = self.get_gap(captcha[0], captcha[1])
    print(left)
    track = self.get_track(left)
    # 如果尝试登陆失败, 则重新验证, 最多三次
    times = 0
    while times < 3:
      self.move_button(button, track)
      try:
        success = self.wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME, 'gt_info_type'), '验证通过:'))
        print(success)
      except TimeoutException as e:
        times += 1
        print('fail')
      else:
        print('success')
        return None


if __name__ == '__main__':
  ACCOUNT = input('请输入您的账号:')
  PASSWORD = input('请输入您的密码:')

  test = BiliBili(ACCOUNT, PASSWORD) # 输入账号和密码
  test.crack()

以上就是python 模拟登录B站的示例代码的详细内容,更多关于python 模拟登陆B站的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python随机生成均匀分布在单位圆内的点代码示例
Nov 13 Python
Python通过调用mysql存储过程实现更新数据功能示例
Apr 03 Python
致Python初学者 Anaconda入门使用指南完整版
Apr 05 Python
解决tensorflow测试模型时NotFoundError错误的问题
Jul 26 Python
BP神经网络原理及Python实现代码
Dec 18 Python
在python中利用opencv简单做图片比对的方法
Jan 24 Python
python3反转字符串的3种方法(小结)
Nov 07 Python
python 使用opencv 把视频分割成图片示例
Dec 12 Python
python实现指定ip端口扫描方式
Dec 17 Python
Python Opencv轮廓常用操作代码实例解析
Sep 01 Python
Python如何实现机器人聊天
Sep 10 Python
python自动化操作之动态验证码、滑动验证码的降噪和识别
Aug 30 Python
python 模拟登陆163邮箱
Dec 15 #Python
详解numpy1.19.4与python3.9版本冲突解决
Dec 15 #Python
python空元组在all中返回结果详解
Dec 15 #Python
python中delattr删除对象方法的代码分析
Dec 15 #Python
详解python中的三种命令行模块(sys.argv,argparse,click)
Dec 15 #Python
python 基于Apscheduler实现定时任务
Dec 15 #Python
next在python中返回迭代器的实例方法
Dec 15 #Python
You might like
上海牌131型七灯四波段四喇叭一级收音机
2021/03/02 无线电
php array_flip() 删除数组重复元素
2009/01/14 PHP
php模拟js函数unescape的函数代码
2012/10/20 PHP
PHP基于回溯算法解决n皇后问题的方法示例
2017/11/07 PHP
php面试中关于面向对象的相关问题
2019/02/13 PHP
PHP iconv()函数字符编码转换的问题讲解
2019/03/22 PHP
js停止输出代码
2008/07/20 Javascript
jquery创建一个新的节点对象(自定义结构/内容)的好方法
2013/01/21 Javascript
JavaScript跨域方法汇总
2014/10/16 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
js 声明数组和向数组中添加对象变量的简单实例
2016/07/28 Javascript
jQuery表单对象属性过滤选择器实例详解
2016/09/13 Javascript
使用JS读取XML文件的方法
2016/11/25 Javascript
Angular 4.x中表单Reactive Forms详解
2017/04/25 Javascript
微信小程序数据存储与取值详解
2018/01/30 Javascript
深入理解与使用keep-alive(配合router-view缓存整个路由页面)
2018/09/25 Javascript
JavaScript实现滑块验证解锁
2021/01/07 Javascript
Python自定义主从分布式架构实例分析
2016/09/19 Python
Python 实现随机数详解及实例代码
2017/04/15 Python
初探利用Python进行图文识别(OCR)
2019/02/26 Python
python GUI图形化编程wxpython的使用
2019/07/19 Python
Python自动化导出zabbix数据并发邮件脚本
2019/08/16 Python
python自动下载图片的方法示例
2020/03/25 Python
纯CSS3制作的鼠标悬停时边框旋转
2017/01/03 HTML / CSS
Html5新特性用canvas标签画多条直线附效果截图
2014/06/30 HTML / CSS
找到您丢失的钥匙、钱包和手机:Tile
2017/05/19 全球购物
英国领先的瓷砖专家:Walls and Floors
2018/04/27 全球购物
我的网上商城创业计划书
2013/12/26 职场文书
上课迟到检讨书100字
2014/01/11 职场文书
犯错检讨书
2014/02/21 职场文书
精神文明建设汇报材料
2014/12/24 职场文书
事业单位聘任报告
2015/03/02 职场文书
工程款催款函
2015/06/24 职场文书
2016年植树节红领巾广播稿
2015/12/17 职场文书
sql字段解析器的实现示例
2021/06/23 SQL Server
win10电脑老是死机怎么办?win10系统老是死机的解决方法
2022/08/05 数码科技