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中的对象,方法,类,实例,函数用法分析
Jan 15 Python
python通过shutil实现快速文件复制的方法
Mar 14 Python
Python记录详细调用堆栈日志的方法
May 05 Python
Python 3.x 连接数据库示例(pymysql 方式)
Jan 19 Python
利用pyinstaller将py文件打包为exe的方法
May 14 Python
Python读写及备份oracle数据库操作示例
May 17 Python
python MNIST手写识别数据调用API的方法
Aug 08 Python
python使用socket实现的传输demo示例【基于TCP协议】
Sep 24 Python
为什么说python更适合树莓派编程
Jul 20 Python
解决c++调用python中文乱码问题
Jul 29 Python
Python使用paramiko连接远程服务器执行Shell命令的实现
Mar 04 Python
TensorFlow的自动求导原理分析
May 26 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
PHP 面向对象详解
2012/09/13 PHP
APACHE的AcceptPathInfo指令使用介绍
2013/01/18 PHP
php上传大文件设置方法
2016/04/14 PHP
Thinkphp 中 distinct 的用法解析
2016/12/14 PHP
小程序微信支付功能配置方法示例详解【基于thinkPHP】
2019/05/05 PHP
PHP程序守护进程化实现方法详解
2020/07/16 PHP
WebGame《逆转裁判》完整版 代码下载(1月24日更新)
2007/01/29 Javascript
JQuery优缺点分析说明
2011/04/10 Javascript
jQuery绑定事件不执行但alert后可以正常执行
2014/06/03 Javascript
jQuery内部原理和实现方式浅析
2015/02/03 Javascript
javascript实现多级联动下拉菜单的方法
2015/02/06 Javascript
angular.js之路由的选择方法
2016/09/24 Javascript
JS实现预加载视频音频/视频获取截图(返回canvas截图)
2017/10/09 Javascript
Angular Renderer (渲染器)的具体使用
2018/05/03 Javascript
微信小程序实现收藏与取消收藏切换图片功能
2018/08/03 Javascript
实例详解BootStrap的动态模态框及静态模态框
2018/08/13 Javascript
微信小程序多音频播放进度条问题
2018/08/28 Javascript
javascript中join方法实例讲解
2019/02/21 Javascript
JS实现移动端在线签协议功能
2019/08/22 Javascript
微信小程序表单验证WxValidate的使用
2019/11/27 Javascript
python 输出一个两行字符的变量
2009/02/05 Python
Python写的Socks5协议代理服务器
2014/08/06 Python
Python使用pickle模块储存对象操作示例
2018/08/15 Python
python实现从文件中读取数据并绘制成 x y 轴图形的方法
2018/10/14 Python
Python 从列表中取值和取索引的方法
2018/12/25 Python
对python3 sort sorted 函数的应用详解
2019/06/27 Python
python中struct模块之字节型数据的处理方法
2019/08/27 Python
python中tkinter窗口位置\坐标\大小等实现示例
2020/07/09 Python
利用CSS3参考手册和CSS3代码生成工具加速来学习网页制
2012/07/11 HTML / CSS
高校师德师风自我剖析材料
2014/09/29 职场文书
单位员工收入证明样本
2014/10/09 职场文书
教师节倡议书2015
2015/04/27 职场文书
审查起诉阶段律师意见书
2015/05/19 职场文书
吧主申请感言怎么写
2015/08/03 职场文书
pytorch通过训练结果的复现设置随机种子
2021/06/01 Python
聊聊SpringBoot自动装配的魔力
2021/11/17 Java/Android