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 fileinput模块使用介绍
Nov 30 Python
Python通过PIL获取图片主要颜色并和颜色库进行对比的方法
Mar 19 Python
利用Python开发微信支付的注意事项
Aug 19 Python
python3+PyQt5实现使用剪贴板做复制与粘帖示例
Jan 24 Python
Python 文件操作的详解及实例
Sep 18 Python
Python实现感知器模型、两层神经网络
Dec 19 Python
基于python绘制科赫雪花
Jun 22 Python
Python实现随机漫步功能
Jul 09 Python
python 搭建简单的http server,可直接post文件的实例
Jan 03 Python
spark dataframe 将一列展开,把该列所有值都变成新列的方法
Jan 29 Python
python3 json数据格式的转换(dumps/loads的使用、dict to str/str to dict、json字符串/字典的相互转换)
Apr 01 Python
python中if和elif的区别介绍
Nov 07 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 如何向 MySQL 发送数据
2006/10/09 PHP
php+mysql分页代码详解
2008/03/27 PHP
PHP 图像尺寸调整代码
2010/05/26 PHP
php 截取字符串并以零补齐str_pad() 函数
2011/05/07 PHP
Laravel框架实现简单的学生信息管理平台案例
2019/05/07 PHP
laravel中数据显示方法(默认值和下拉option默认选中)
2019/10/11 PHP
javascript 函数式编程
2007/08/16 Javascript
基于jquery的下拉框改变动态添加和删除表格实现代码
2020/09/12 Javascript
jQuery实现按键盘方向键翻页特效
2015/03/18 Javascript
js制作带有遮罩弹出层实现登录注册表单特效代码分享
2015/09/05 Javascript
JS实现完全语义化的网页选项卡效果代码
2015/09/15 Javascript
原生JS简单实现ajax的方法示例
2016/11/29 Javascript
关于angular js_$watch监控属性和对象详解
2017/04/24 Javascript
js评分组件使用详解
2017/06/06 Javascript
vue使用axios实现文件上传进度的实时更新详解
2017/12/20 Javascript
Vue中render方法的使用详解
2018/01/26 Javascript
详解微信小程序input标签正则初体验
2018/08/18 Javascript
搭建基于express框架运行环境的方法步骤
2018/11/15 Javascript
Vuejs学习笔记之使用指令v-model完成表单的数据双向绑定
2019/04/29 Javascript
websocket4.0+typescript 实现热更新的方法
2019/08/14 Javascript
vue+element树组件 实现树懒加载的过程详解
2019/10/21 Javascript
jquery实现上传图片功能
2020/06/29 jQuery
Python面向对象编程基础解析(一)
2017/10/26 Python
Python爬虫包BeautifulSoup简介与安装(一)
2018/06/17 Python
python脚本监控Tomcat服务器的方法
2018/07/06 Python
python实现换位加密算法的示例
2018/10/14 Python
Python3使用PySynth制作音乐的方法
2019/09/09 Python
python 单线程和异步协程工作方式解析
2019/09/28 Python
Python实现子类调用父类的初始化实例
2020/03/12 Python
HTML5学习笔记之html5与传统html区别
2016/01/06 HTML / CSS
Html5基于canvas实现电子签名并生成PDF文档
2020/12/07 HTML / CSS
JACK & JONES荷兰官网:男士服装和鞋子
2021/03/07 全球购物
行政副总岗位职责
2014/02/23 职场文书
驾驶员培训方案
2014/05/01 职场文书
伊琍体标语
2014/06/25 职场文书
爱心募捐通知范文
2015/04/27 职场文书