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错误处理详解
Sep 28 Python
Python实现读取并保存文件的类
May 11 Python
Python字符串拼接六种方法介绍
Dec 18 Python
Python语言描述机器学习之Logistic回归算法
Dec 21 Python
通过python+selenium3实现浏览器刷简书文章阅读量
Dec 26 Python
python实现图像识别功能
Jan 29 Python
通过python顺序修改文件名字的方法
Jul 11 Python
python批量赋值操作实例
Oct 22 Python
详解如何为eclipse安装合适版本的python插件pydev
Nov 04 Python
Python高级特性与几种函数的讲解
Mar 08 Python
Python企业编码生成系统之主程序模块设计详解
Jul 26 Python
在Windows下安装配置CPU版的PyTorch的方法
Apr 02 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/10/07 PHP
解析PHP中的file_get_contents获取远程页面乱码的问题
2013/06/25 PHP
Destoon实现多表查询示例
2014/08/21 PHP
Yii分页用法实例详解
2014/12/04 PHP
Yii视图操作之自定义分页实现方法
2016/07/14 PHP
PHP中将一个字符串部分字符用星号*替代隐藏的实现代码
2019/09/08 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
Google Suggest ;-) 基于js的动态下拉菜单
2006/10/11 Javascript
jquery判断单个复选框是否被选中的代码
2009/09/03 Javascript
jQuery学习笔记之Ajax用法实例详解
2015/12/01 Javascript
Underscore源码分析
2015/12/30 Javascript
JavaScript获取当前运行脚本文件所在目录的方法
2016/02/03 Javascript
BootStrap文件上传样式超好看【持续更新】
2016/05/10 Javascript
基于jQuery实现火焰灯效果导航菜单
2017/01/04 Javascript
详解Vue 实例中的生命周期钩子
2017/03/21 Javascript
gulp教程_从入门到项目中快速上手使用方法
2017/09/14 Javascript
解决vue2.0路由跳转未匹配相应用路由避免出现空白页面的问题
2018/08/24 Javascript
Vuejs开发环境搭建及热更新【推荐】
2018/09/07 Javascript
原生JS实现汇率转换功能代码实例
2020/05/13 Javascript
easyUI使用分页过滤器对数据进行分页操作实例分析
2020/06/01 Javascript
如何利用javascript接收json信息并进行处理
2020/08/06 Javascript
vue实现图片裁剪后上传
2020/12/16 Vue.js
python使用urllib2模块获取gravatar头像实例
2013/12/18 Python
高效测试用例组织算法pairwise之Python实现方法
2017/07/19 Python
python版本的仿windows计划任务工具
2018/04/30 Python
Python批处理更改文件名os.rename的方法
2018/10/26 Python
详解分布式任务队列Celery使用说明
2018/11/29 Python
Python推导式简单示例【列表推导式、字典推导式与集合推导式】
2018/12/04 Python
对Python+opencv将图片生成视频的实例详解
2019/01/08 Python
浅谈对pytroch中torch.autograd.backward的思考
2019/12/27 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
解决Keras自带数据集与预训练model下载太慢问题
2020/06/12 Python
评估“风险”创业计划的几大要点
2019/08/12 职场文书
本地通过nginx配置反向代理的全过程记录
2021/03/31 Servers
Python利用zhdate模块实现农历日期处理
2022/03/31 Python
CSS list-style-type属性使用方法
2023/05/21 HTML / CSS