Python破解滑块验证码算法,完美避开人机识别

| 完美是不可能的,加个震惊!Python破解BiliBili滑块验证码,完美避开人机识别,可以有

准备工作

  • B站登录页 https://passport.bilibili.com/login
  • python3
  • pip install selenium (webdriver框架)
  • pip install PIL (图片处理)
  • chrome driver:http://chromedriver.storage.googleapis.com/index.html
  • firefox driver:https://github.com/mozilla/geckodriver/releases

B站滑块验证码

B站的滑块验证码如上。
这类验证码可以使用 selenium 操作浏览器拖拽滑块来进行破解,难点两个,一个如何确定拖拽到的位置,另一个是避开人机识别(反爬虫)。

确定滑块验证码需要拖拽的位移距离

有三种方式

  • 人工智能机器学习,确定滑块位置
  • 通过完整图片与缺失滑块的图片进行像素对比,确定滑块位置
  • 边缘检测算法,确定位置

各有优缺点。人工智能机器学习,确定滑块位置,需要进行训练,比较麻烦,也可以看是否存在在线api可以调用。以下介绍其他两种方式。

对比完整图片与缺失滑块的图片

| 仅介绍,本文不进行实现。对于B站来说,是准确率最高的方式(100%),但不能保证未来B站的滑块验证升级,导致不可用。

B站的滑块验证模块,一共有三张图片:完整图、缺失滑块图、滑块图,都是由画布绘制出的。类似于:

完整图:
完整图
缺失滑块图:
缺失滑块图
滑块图:
滑块图

HTML代码类似于:

<div class="geetest_canvas_img geetest_absolute" style="display: block;">
<div class="geetest_slicebg geetest_absolute"><canvas class="geetest_canvas_bg geetest_absolute" height="160" width="260"></canvas><canvas class="geetest_canvas_slice geetest_absolute" width="260" height="160"></canvas>
</div>
<canvas class="geetest_canvas_fullbg geetest_fade geetest_absolute" height="160" width="260" style="display: none;"></canvas>
</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

只需要通过selenium获取画布元素,执行js拿到画布像素,遍历完整图和缺失滑块图的像素,一旦获取到差异(需要允许少许像素误差),像素矩阵x轴方向即是滑块位置。
另外由于滑块图距离画布坐标原点有距离,还需要减去这部分距离。
最后使用 selenium 拖拽即可。

边缘检测算法,确定位置

| 滑块基本上是个方形,通过算法确定方形起始位置即可。

计算位置
介绍两种方式

  • 滑块是方形的,存在垂直与水平的边,该边在缺失滑块图中基本都是灰黑的。遍历像素找到基本都是灰黑的边即可。
  • 缺失滑块图中滑块位置是灰黑封闭的。通过算法可以找到封闭区域,大小与滑块相近,即是滑块需要拖拽到的位置。

第二种实现起来有些复杂,不进行实现了。
下面是第一种实现方式(只实现了垂直边的检测,水平边检测原理一致),会存在检测不出或错误的情况,使用时需要换一张验证码。也可能存在检测出的边是另一条(因为B站的滑块不是长方形,存在弧形边),那么需要减去滑块宽度


class VeriImageUtil():def __init__(self):self.defaultConfig = {"grayOffset": 20,"opaque": 1,"minVerticalLineCount": 30}self.config = copy.deepcopy(self.defaultConfig)def updateConfig(self, config):# temp = copy.deepcopy(config)for k in self.config:if k in config.keys():self.config[k] = config[k]def getMaxOffset(self, *args):# 计算偏移平均值最大的数av = sum(args) / len(args)maxOffset = 0for a in args:offset = abs(av - a)if offset > maxOffset:maxOffset = offsetreturn maxOffsetdef isGrayPx(self, r, g, b):# 是否是灰度像素点,允许波动offsetreturn self.getMaxOffset(r, g, b) < self.config["grayOffset"]def isDarkStyle(self, r, g, b):# 灰暗风格return r < 128 and g < 128 and b < 128def isOpaque(self, px):# 不透明return px[3] >= 255 * self.config["opaque"]def getVerticalLineOffsetX(self, bgImage):# bgImage = Image.open("./image/bg.png")# bgImage.im.mode = 'RGBA'bgBytes = bgImage.load()x = 0while x < bgImage.size[0]:y = 0# 点》》线,灰度线条数量verticalLineCount = 0while y < bgImage.size[1]:px = bgBytes[x, y]r = px[0]g = px[1]b = px[2]# alph = px[3]# print(px)if self.isDarkStyle(r, g, b) and self.isGrayPx(r, g, b) and self.isOpaque(px):verticalLineCount += 1else:verticalLineCount = 0y += 1continueif verticalLineCount >= self.config["minVerticalLineCount"]:# 连续多个像素都是灰度像素,直线# print(x, y)return xy += 1x += 1passif __name__ == '__main__':bgImage = Image.open("./image/bg.png")veriImageUtil = VeriImageUtil()# veriImageUtil.updateConfig({#     "grayOffset": 20,#     "opaque": 0.6,#     "minVerticalLineCount": 10# })bgOffsetX = veriImageUtil.getVerticalLineOffsetX(bgImage)print("bgOffsetX:{} ".format(bgOffsetX))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88

使用selenium进行滑动验证(会失败)

首先,我们需要从html中获取滑块验证的图片,通过执行js,将画布像素转为base64,然后python即可获取,进行拖拽处理:


from selenium import webdriver
import time
import base64
from PIL import Image
from io import BytesIO
from selenium.webdriver.support.ui import WebDriverWaitdef checkVeriImage(driver):    WebDriverWait(driver, 5).until(lambda driver: driver.find_element_by_css_selector('.geetest_canvas_bg.geetest_absolute'))time.sleep(1)im_info = driver.execute_script('return document.getElementsByClassName("geetest_canvas_bg geetest_absolute")[0].toDataURL("image/png");')# 拿到base64编码的图片信息im_base64 = im_info.split(',')[1]# 转为bytes类型im_bytes = base64.b64decode(im_base64)with open('./temp_bg.png', 'wb') as f:# 保存图片到本地,方便查看预览f.write(im_bytes)image_data = BytesIO(im_bytes)bgImage = Image.open(image_data)# 滑块距离左边有 5~10 像素左右误差offsetX = VeriImageUtil().getVerticalLineOffsetX(bgImage)eleDrag = driver.find_element_by_css_selector(".geetest_slider_button")action_chains = webdriver.ActionChains(driver)action_chains.drag_and_drop_by_offset(eleDrag,offsetX-10,0).perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

貌似可以了,但实际上,验证时会遇到“拼图被怪物吃掉了,请重试”,导致失败。这是因为被检测到机器人(爬虫)操作了。

避开人机识别

| B站滑块验证码的人机识别,其实不咋滴,主要靠是否存在停留间隔来判断。一开始被网上文章误导,弄了什么距离=初速度乘以时间t + 1/2加速度乘以(时间平方)模拟拖拽,实际上是完全不对路的。

人机识别-怪物吃了拼图

webdriver.ActionChains(driver).drag_and_drop_by_offset(eleDrag,offsetX-10,0).perform() 拖动滑块会导致验证失败。在B站中,这是因为这个动作太快了的缘故。
有的同学就打算直接加 time.sleep(1) 了,这么做是不会成功的,会提示拼图被怪物吃掉了,请重试

实际上人做滑块验证的过程可以归为:手指快速拖拽验证码到指定位置,修正误差,停留一会儿,释放滑块。

简单实现

代码可以简单实现,都不需要模拟人修正拖拽误差的过程,普通网站不会去统计这个,至少B站不会。

    def simpleSimulateDragX(self, source, targetOffsetX):"""简单拖拽模仿人的拖拽:快速沿着X轴拖动,直接一步到达正确位置,再暂停一会儿,然后释放拖拽动作B站是依据是否有暂停时间来分辨人机的,这个方法适用。:param source: :param targetOffsetX: :return: None"""#参考`drag_and_drop_by_offset(eleDrag,offsetX-10,0)`的实现,使用move方法action_chains = webdriver.ActionChains(self.driver)# 点击,准备拖拽action_chains.click_and_hold(source)action_chains.pause(0.2)action_chains.move_by_offset(targetOffsetX,0)action_chains.pause(0.6)action_chains.release()action_chains.perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

添加修正过程的实现

其实也就最后一段多出了fix的过程, action_chains.move_by_offset(10,0)

    def fixedSimulateDragX(self, source, targetOffsetX):#参考`drag_and_drop_by_offset(eleDrag,offsetX-10,0)`的实现,使用move方法action_chains = webdriver.ActionChains(self.driver)# 点击,准备拖拽action_chains.click_and_hold(source)action_chains.pause(0.2)action_chains.move_by_offset(targetOffsetX-10,0)action_chains.pause(0.6)action_chains.move_by_offset(10,0)action_chains.pause(0.6)action_chains.release()action_chains.perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

终极版实现

| 为了更像人类操作,可以进行拖拽间隔时间和拖拽次数、距离的随机化。虽然这对B站没什么用,还可能会导致验证时间变久一些。

拖拽多次,可以使用循环遍历,不过代码可能不好理解,直接判断就行,最多也就两到3次就完成修正误差的过程。

def __getRadomPauseScondes(self):""":return:随机的拖动暂停时间"""return random.uniform(0.6, 0.9)def simulateDragX(self, source, targetOffsetX):"""模仿人的拖拽动作:快速沿着X轴拖动(存在误差),再暂停,然后修正误差防止被检测为机器人,出现“图片被怪物吃掉了”等验证失败的情况:param source:要拖拽的html元素:param targetOffsetX: 拖拽目标x轴距离:return: None"""action_chains = webdriver.ActionChains(self.driver)# 点击,准备拖拽action_chains.click_and_hold(source)# 拖动次数,二到三次dragCount = random.randint(2, 3)if dragCount == 2:# 总误差值sumOffsetx = random.randint(-15, 15)action_chains.move_by_offset(targetOffsetX + sumOffsetx, 0)# 暂停一会action_chains.pause(self.__getRadomPauseScondes())# 修正误差,防止被检测为机器人,出现图片被怪物吃掉了等验证失败的情况action_chains.move_by_offset(-sumOffsetx, 0)elif dragCount == 3:# 总误差值sumOffsetx = random.randint(-15, 15)action_chains.move_by_offset(targetOffsetX + sumOffsetx, 0)# 暂停一会action_chains.pause(self.__getRadomPauseScondes())# 已修正误差的和fixedOffsetX = 0# 第一次修正误差if sumOffsetx < 0:offsetx = random.randint(sumOffsetx, 0)else:offsetx = random.randint(0, sumOffsetx)fixedOffsetX = fixedOffsetX + offsetxaction_chains.move_by_offset(-offsetx, 0)action_chains.pause(self.__getRadomPauseScondes())# 最后一次修正误差action_chains.move_by_offset(-sumOffsetx + fixedOffsetX, 0)action_chains.pause(self.__getRadomPauseScondes())else:raise Exception("莫不是系统出现了问题?!")# 参考action_chains.drag_and_drop_by_offset()action_chains.release()action_chains.perform()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

终章(完整代码)

| 示例代码和效果图。完整示例代码本身只是示例,方便测试用的,不进行成功验证等处理,验证成功后python会直接异常退出。

效果图

本文完整示例代码如下

# -*- coding: utf-8 -*-
# @Date:2020/2/15 2:09
# @Author: Lu
# @Description bilibili滑块验证码识别。B站有反爬限制,过快地拖拽会提示“怪物吃了拼图,请重试”。
# 目前B站有三张图片,只要对比完整图和缺失滑块背景图的像素,就可以得到偏移图片y轴距离,减去滑块空白距离=需要滑动的像素距离
# 这里采用边缘检测,检测缺失滑块的底图是否存在一条灰色竖线,即认为是滑块目标位置,存在失败的概率,适用范围应该更大些。from selenium import webdriver
import time
import base64
from PIL import Image
from io import BytesIO
from selenium.webdriver.support.ui import WebDriverWait
import random
import copyclass VeriImageUtil():def __init__(self):self.defaultConfig = {"grayOffset": 20,"opaque": 1,"minVerticalLineCount": 30}self.config = copy.deepcopy(self.defaultConfig)def updateConfig(self, config):# temp = copy.deepcopy(config)for k in self.config:if k in config.keys():self.config[k] = config[k]def getMaxOffset(self, *args):# 计算偏移平均值最大的数av = sum(args) / len(args)maxOffset = 0for a in args:offset = abs(av - a)if offset > maxOffset:maxOffset = offsetreturn maxOffsetdef isGrayPx(self, r, g, b):# 是否是灰度像素点,允许波动offsetreturn self.getMaxOffset(r, g, b) < self.config["grayOffset"]def isDarkStyle(self, r, g, b):# 灰暗风格return r < 128 and g < 128 and b < 128def isOpaque(self, px):# 不透明return px[3] >= 255 * self.config["opaque"]def getVerticalLineOffsetX(self, bgImage):# bgImage = Image.open("./image/bg.png")# bgImage.im.mode = 'RGBA'bgBytes = bgImage.load()x = 0while x < bgImage.size[0]:y = 0# 点》》线,灰度线条数量verticalLineCount = 0while y < bgImage.size[1]:px = bgBytes[x, y]r = px[0]g = px[1]b = px[2]# alph = px[3]# print(px)if self.isDarkStyle(r, g, b) and self.isGrayPx(r, g, b) and self.isOpaque(px):verticalLineCount += 1else:verticalLineCount = 0y += 1continueif verticalLineCount >= self.config["minVerticalLineCount"]:# 连续多个像素都是灰度像素,直线,认为需要滑动这么多# print(x, y)return xy += 1x += 1passclass DragUtil():def __init__(self, driver):self.driver = driverdef __getRadomPauseScondes(self):""":return:随机的拖动暂停时间"""return random.uniform(0.6, 0.9)def simulateDragX(self, source, targetOffsetX):"""模仿人的拖拽动作:快速沿着X轴拖动(存在误差),再暂停,然后修正误差防止被检测为机器人,出现“图片被怪物吃掉了”等验证失败的情况:param source:要拖拽的html元素:param targetOffsetX: 拖拽目标x轴距离:return: None"""action_chains = webdriver.ActionChains(self.driver)# 点击,准备拖拽action_chains.click_and_hold(source)# 拖动次数,二到三次dragCount = random.randint(2, 3)if dragCount == 2:# 总误差值sumOffsetx = random.randint(-15, 15)action_chains.move_by_offset(targetOffsetX + sumOffsetx, 0)# 暂停一会action_chains.pause(self.__getRadomPauseScondes())# 修正误差,防止被检测为机器人,出现图片被怪物吃掉了等验证失败的情况action_chains.move_by_offset(-sumOffsetx, 0)elif dragCount == 3:# 总误差值sumOffsetx = random.randint(-15, 15)action_chains.move_by_offset(targetOffsetX + sumOffsetx, 0)# 暂停一会action_chains.pause(self.__getRadomPauseScondes())# 已修正误差的和fixedOffsetX = 0# 第一次修正误差if sumOffsetx < 0:offsetx = random.randint(sumOffsetx, 0)else:offsetx = random.randint(0, sumOffsetx)fixedOffsetX = fixedOffsetX + offsetxaction_chains.move_by_offset(-offsetx, 0)action_chains.pause(self.__getRadomPauseScondes())# 最后一次修正误差action_chains.move_by_offset(-sumOffsetx + fixedOffsetX, 0)action_chains.pause(self.__getRadomPauseScondes())else:raise Exception("莫不是系统出现了问题?!")# 参考action_chains.drag_and_drop_by_offset()action_chains.release()action_chains.perform()def simpleSimulateDragX(self, source, targetOffsetX):"""简单拖拽模仿人的拖拽:快速沿着X轴拖动,直接一步到达正确位置,再暂停一会儿,然后释放拖拽动作B站是依据是否有暂停时间来分辨人机的,这个方法适用。:param source: :param targetOffsetX: :return: None"""action_chains = webdriver.ActionChains(self.driver)# 点击,准备拖拽action_chains.click_and_hold(source)action_chains.pause(0.2)action_chains.move_by_offset(targetOffsetX, 0)action_chains.pause(0.6)action_chains.release()action_chains.perform()def checkVeriImage(driver):WebDriverWait(driver, 5).until(lambda driver: driver.find_element_by_css_selector('.geetest_canvas_bg.geetest_absolute'))time.sleep(1)im_info = driver.execute_script('return document.getElementsByClassName("geetest_canvas_bg geetest_absolute")[0].toDataURL("image/png");')# 拿到base64编码的图片信息im_base64 = im_info.split(',')[1]# 转为bytes类型im_bytes = base64.b64decode(im_base64)with open('./temp_bg.png', 'wb') as f:# 保存图片到本地f.write(im_bytes)image_data = BytesIO(im_bytes)bgImage = Image.open(image_data)# 滑块距离左边有 5 像素左右误差offsetX = VeriImageUtil().getVerticalLineOffsetX(bgImage)print("offsetX: {}".format(offsetX))if not type(offsetX) == int:# 计算不出,重新加载driver.find_element_by_css_selector(".geetest_refresh_1").click()checkVeriImage(driver)returnelif offsetX == 0:# 计算不出,重新加载driver.find_element_by_css_selector(".geetest_refresh_1").click()checkVeriImage(driver)returnelse:dragVeriImage(driver, offsetX)def dragVeriImage(driver, offsetX):# 可能产生检测到右边缘的情况# 拖拽eleDrag = driver.find_element_by_css_selector(".geetest_slider_button")dragUtil = DragUtil(driver)dragUtil.simulateDragX(eleDrag, offsetX - 10)time.sleep(2.5)if isNeedCheckVeriImage(driver):checkVeriImage(driver)returndragUtil.simulateDragX(eleDrag, offsetX - 6)time.sleep(2.5)if isNeedCheckVeriImage(driver):checkVeriImage(driver)return# 滑块宽度40左右dragUtil.simulateDragX(eleDrag, offsetX - 56)time.sleep(2.5)if isNeedCheckVeriImage(driver):checkVeriImage(driver)returndragUtil.simulateDragX(eleDrag, offsetX - 52)if isNeedCheckVeriImage(driver):checkVeriImage(driver)returndef isNeedCheckVeriImage(driver):if driver.find_element_by_css_selector(".geetest_panel_error").is_displayed():driver.find_element_by_css_selector(".geetest_panel_error_content").click();return Truereturn Falsedef task():# 此步骤很重要,设置chrome为开发者模式,防止被各大网站识别出来使用了Selenium# options = webdriver.ChromeOptions()# options.add_experimental_option('excludeSwitches', ['enable-automation'])options = webdriver.FirefoxOptions()# driver = webdriver.Firefox(executable_path=r"../../../res/webdriver/geckodriver_x64_0.26.0.exe",options=options)driver = webdriver.Firefox(executable_path=r"../../../res/webdriver/geckodriver_x64_0.26.0.exe",options=options)driver.get('https://passport.bilibili.com/login')time.sleep(3)driver.find_element_by_css_selector("#login-username").send_keys("1234567")driver.find_element_by_css_selector("#login-passwd").send_keys("abcdefg")driver.find_element_by_css_selector(".btn.btn-login").click()time.sleep(2)checkVeriImage(driver)pass#   该方法用来确认元素是否存在,如果存在返回flag=true,否则返回false
def isElementExist(driver, css):try:driver.find_element_by_css_selector(css)return Trueexcept:return Falseif __name__ == '__main__':task()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/547499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 分页类

2019独角兽企业重金招聘Python工程师标准>>> 分页公式&#xff1a;页数&#xff08;总记录数-1&#xff09;/每页显示记录数1&#xff1b; 借助这个公式&#xff0c;实现以下分页类&#xff1b; <?php class Fpage{ private $total; //数据表中总记录数 …

Docker中的Nginx搭建HTTPS环境

准备 1.已安装好docker环境 2.申请好域名 3.SSL证书&#xff08;可选&#xff09; 一、安装Nginx docker pull nginx 查看docker镜像&#xff1a; docker images 二、进行配置 建目录用于存放nginx配置文件、证书文件 mkdir /opt/docker/nginx/conf.d -p touch /opt/docke…

Android的引用jar包

先来个基础的&#xff0c;在eclips里在工程名上右键->build path->contigure bud path->java build path里有个几个选项add external jars 增加工程外部的包add jars 增加工程内包add library 增加一个库add class folder 增加一个类文件夹下面着重介绍add libra…

Android木马分析实验,Android木马简介与分析

本文介绍基于Android的手机恶意软件&#xff0c;是一个基础性的介绍&#xff0c;给新入门的人提供一个分析和工具指引。要分析的木马是一个2013年的syssecApp.apk&#xff0c;这个木马的分析能对Android恶意软件有个大概了解。基础&#xff1a;1 –Android应用基础Android是goo…

Visual Studio 2012资源管理器里单击打开改为双击打开文件

Visual Studio 2012资源管理器里&#xff0c;单击打开文件改为双击打开文件&#xff0c;如图&#xff1a;

监控服务器容量 MOM

http://xxglx.jxcfs.com/net/zyk/htmlfiles/practice/practice00097.htm转载于:https://www.cnblogs.com/Kazaf/p/3286409.html

解决VM 与 Device/Credential Guard 不兼容。在禁用 Device/Credential Guard 后,可以运行 VM 的方法

在启用了Credential Guard或Device Guard的Windows 10主机上启动12.5版之前的VMware Workstation中的虚拟机时&#xff0c;将显示蓝色诊断屏幕&#xff08;BSOD&#xff09;。 会看到类似于以下内容的错误&#xff1a; VMware Workstation和Device / Credential Guard不兼容。禁…

android怎么升级版本5.0,一加手机怎么升级安卓5.0系统

谷歌今天正式发布了最新的安卓5.0正式版&#xff0c;作为一次非常大的系统升级&#xff0c;安卓5.0带来了非常多明显的升级&#xff0c;体验上相比安卓4.4要精进不少。在众多手机纷纷向Android 5.0发起冲击之时&#xff0c;一加手机官方论坛也放出了首个Android 5.0固件&#x…

Asp.Net使用Yahoo.Yui.Compressor.dll压缩Js|Css

网上压缩css和js工具很多&#xff0c;但在我们的系统中总有特殊的地方。也许你会觉得用第三方的压缩工具很麻烦。我就遇到了这样问题&#xff0c;我不想在本地压缩,只想更新到服务器上去压缩&#xff0c;服务器压缩也不用备份之类的操作。于是我就想着自己实现压缩工具。 初步…

Android 自动化测试——Monkey测试

2019独角兽企业重金招聘Python工程师标准>>> 1、Monkey测试简介 Monkey主要应用在压力和可靠性测试上&#xff0c;运行该命令可以随机地向目标程序发送各种模拟键盘事件流&#xff0c;并且可以自己定义发送的次数&#xff0c;以此观察被测应用程序的稳定性和可靠性…

android默认开机动画,修改安卓开机动画(除了部分系统 如MIUI等)

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼这技术已经很久了&#xff0c;但还是忍不住搬运了一下。出处是百度的&#xff0c;很久很久以前玩手机在百度上学的我这里说的开机动画是指开机的第二屏开机动画可以在下载的rom里修改&#xff0c;也可以刷机后修改(推荐后者&#x…

MongoDB Query 的几个方法

Query.All("name", "a", "b");//通过多个元素来匹配数组Query.And(Query.EQ("name", "a"), Query.EQ("title", "t"));//同时满足多个条件Query.EQ("name", "a");//等于Query.Exist…

android 页面无法点击,为什么点击不跳转到下一界面,哪位大神帮瞅瞅

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼package com.example.udp;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.Menu;import android.widget.Button;import android.widget.EditText;public class Temp ext…

一个网卡绑定多个IP

2019独角兽企业重金招聘Python工程师标准>>> 今天在做公司行业网站时&#xff0c;遇到这样一个问题&#xff0c;由于做了多个行业网站&#xff0c;每个行业网站都要一个会员模板网站&#xff0c;这种网站需要域名泛指向功能&#xff0c;而一个IP地址&#xff0c;80端…

如何在Jupyter中运行R语言(两种解决方案)

Python用Jupyter写分析记录比较舒服&#xff0c;学了R也想在Jupyter上运行。 复杂方案 安装R语言、Jupyter程序 在R Console中安装1 install.packages(c(repr, IRdisplay, evaluate, crayon, pbdZMQ, devtools, uuid, digest))安装需要的基础包 devtools::install_github(IRk…

android高仿天天动听,Android仿天天动听歌曲自动滚动view

最近项目中要做一个类似天天动听歌曲自动滚动行数的效果。首先自己想了下Android要滚动的那就是scroller类或者scrollto、scrollby结合了&#xff0c;或者view.layout()方法&#xff0c;或者使用动画。但是要循环滚动&#xff0c;貌似这些到最后一行滚动到第一行都有往回滚的效…

Pechkin:html - pdf 利器

Pechkin 是GitHub上的一个开源项目&#xff0c;可方便将html转化成pdf文档&#xff0c;使用也很方便&#xff0c;下面是winform项目中的示例代码&#xff1a; using System; using System.Diagnostics; using System.Drawing.Printing; using System.IO; using System.Windows.…

packer build 报错 无任何输出 一直报“skipping line: 1 skipping line: 2 skipping line: 3.....”

最近使用packer build 报错 无任何输出 一直报“skipping line: 1 skipping line: 2 skipping line: 3.....” &#xff0c; 解决方法如下&#xff1a; # Install wget and unzip before executing the below steps wget https://releases.hashicorp.com/packer/1.0.0/packer_…

使用ZeroClipboard解决跨浏览器复制到剪贴板的问题

Zero Clipboard的实现原理Zero Clipboard 利用透明的Flash让其漂浮在复制按钮之上&#xff0c;这样其实点击的不是按钮而是 Flash &#xff0c;这样将需要的内容传入Flash&#xff0c;再通过Flash的复制功能把传入的内容复制到剪贴板。 Zero Clipboard的安装方法首先需要下载 …

android inflate 三个参数的含义,LayoutInflater.inflate 3个参数的含义

LayoutInflater.inflate 天天都在用但对它 3 个参数的含义没有很好的理解之前 root 一直传 null , 现在才知道传 null 在多数情况下都是不对的public View inflate(LayoutRes int resource, Nullable ViewGroup root, boolean attachToRoot)第一个参数是布局ID 没什么说的第二个…