python selenum学习笔记(一) 登录bilibil

@[TOC](python selenum学习笔记(一) 登录bilibil)

利用selenum模拟浏览器操作登录bilibili

之前学习网站内容抓取的时候,一般都是get方法,获取response,主要是对HTML内的元素进行抓取。要获得与js代码交互之后的内容不是很方便。
利用 selenum 来进行一些交互操作就很便利了。目前学习中。

代码及思路

一、首先启动selenum的浏览器模拟器

from selenium import webdriver
browser = webdriver.Firefox()#创建firefox 浏览器模拟
browser.get("https://passport.bilibili.com/login") #bilibili登录网址

二、然后输入账号密码

usertext = browser.find_element_by_id('login-username')
usertext.send_keys("yourusername")
password = browser.find_element_by_id('login-passwd')
password.send_keys('yourpassword')
btn = browser.find_element_by_css_selector('.btn-login')#找到登录按钮

三、点击登录

btn.click()

四、这个时候会弹出一个滑块验证的对话框,查找html元素的方式是找不到图片的src的,要通过js注入的操作。这段代码当时也是参考网上的,但是找不到了那个作者了,sorry。

import base64
JS = 'return document.getElementsByClassName("geetest_canvas_bg geetest_absolute")[0].toDataURL("image/png");'
im_info = browser.execute_script(JS)
im_base64 = im_info.split(',')[1]  #拿到base64编码的图片信息
im_bytes = base64.b64decode(im_base64)  #转为bytes类型
with open('bg.png','wb') as f:  #保存图片到本地
    f.write(im_bytes)
JS = 'return document.getElementsByClassName("geetest_canvas_slice geetest_absolute")[0].toDataURL("image/png");'
im_info_slice = browser.execute_script(JS)
im_base64_slice = im_info_slice.split(',')[1]  #拿到base64编码的图片信息
im_bytes_slice = base64.b64decode(im_base64_slice)  #转为bytes类型
with open('btn.png','wb') as f0:  #保存图片到本地
    f0.write(im_bytes_slice)

五、然后对图像进行操作,获取需要滑动的距离。
这个时候需要引入一些库opencv,pillow,numpy。

from PIL import Image, ImageEnhance
import cv2
import numpy as np

六、按照网上的代码要要查找滑块在 背景图上的位置 ,代码应该是:

res = cv2.matchTemplate(template,img_gray,cv2.TM_CCOEFF_NORMED)

就可以返回查找的结果了,但是输出这个结果发现都是“[]”,空队列。怎么回事呢?
原来哔哩哔哩的滑块图片和背景图片一样大…其他地方全是白色,那么这两个图片肯定无法“查找到”匹配的位置了。
滑块背景图
两个图片一样大。那么必须对滑块图片进行一些裁剪。
但仔细观察,滑块图片带外发光的有没有?虽然不知道对查找有没有影响还是弄掉比较好。
外发光

def cut_img(img2):
    rows,cols,channels = img2.shape #获取文件大小
    img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY) 
    ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY) #获取蒙版
    
    kernel = np.ones((4,4),np.uint8) #...这个如果比较大,那么接下来操作的效果就比较狠,我是这么理解的
    erode=cv2.erode(mask,kernel,iterations=2) #侵蚀,让图片白色区域缩小
    dilate=cv2.dilate(erode,kernel,iterations=2)#再扩张白色部分,一来二去,小的白色区域就消失掉了(原来那些发光的痕迹),得到一个干净的蒙版
    img2_fg = cv2.bitwise_and(img2,img2,mask = dilate)#获取干净的滑块,但是文件大小还是260*160 
	# 因为对opencv不是很熟悉,也不知道怎么快速的裁切白色的区域就用了笨办法
    list_row = [] #存储行信息的list
    list_col = [] #存储列信息的list
    for i in range(rows):
        for j in range(cols):
            if all(img2_fg[i,j]==(0,0,0)): #如果是白色
                pass #那没事了
            else:
                list_row.append(i) #如果不是,把行号记录下来。
                break
    for i in range(cols):
        for j in range(rows):
            if all(img2_fg[j,i]==(0,0,0)):#如果是白色
                pass #那没事了
            else:
                list_col.append(i) #如果不是,把列号记录下来。
                break
    x,y = min(list_row),min(list_col) # 获取行和列的最小值
    x1,y1 = max(list_row),max(list_col) #行和列的最大值
	#res_img = img2_fg[x:x1,y:y1]  正常的裁切应该是这样的,但是我发现这个滑块居然有内发光,不知道是否影响图像查找,剪了剪了
    res_img = img2_fg[x+8:x1-8,y+8:y1-8] #所以左右再裁剪8像素。。。
    return res_img #返回裁剪后的图像

得到这样的图。。。最后裁切的结果
然后执行查找匹配的代码:

def match():
	img_tar = cv2.imread('btn.png') #加载滑块图片
	img_rgb = cut_img(img_tar) #利用刚刚的函数进行裁剪
	img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY) #获取灰度文件,灰度文件查找速度快,我没看出来区别,彩色查找也可以吧应该
	template = cv2.imread('bg.png',0) #获取灰度文件,如果不带,第二个参数 0 ,就是彩色。

	h, w = img_gray.shape[::-1] #获得裁剪后滑块图片的高和宽
	res = cv2.matchTemplate(template,img_gray,cv2.TM_CCOEFF_NORMED)  #查找匹配

	# 使用二分法查找阈值的精确值 ,这段是我抄的,大概意思是res列队中找到匹配的最好的。原理没看懂。
	L = 0
	R = 1
	run = 1
	while run < 20:
	    run += 1
	    threshold = (R + L) / 2
	    if threshold < 0:
	        return None
	    loc = np.where( res >= threshold)
	    if len(loc[1]) > 1:
	        L += (R - L) / 2
	    elif len(loc[1]) == 1:
	        print('目标区域起点x坐标为:%d' % loc[1][0])
	        break
	    elif len(loc[1]) < 1:
	        R -= (R - L) / 2
	print(loc)
	return loc[1][0] #返回最好匹配的顶点(x,y)的x值,就是横坐标啦

七、移动滑块,这个时候需要引入一些库。

from selenium.webdriver import ActionChains
distance = match() #得到匹配位置的顶点很坐标的位置。
offpx = (distance + 11 - 30) #一般经过裁剪的滑块图片宽为22像素,那么中心点横坐标就要加上11,但是因为滑块的起始位置不是0,而是所以加上30,这个30,在别的滑块验证的地方自己调整
slider = browser.find_element_by_css_selector('.geetest_slider_button')#获取滑块元素
#操作滑块 因为模拟人操作的感觉,所以做了一些调整,不是一步到位,网上参考的资料中,给滑块做一个滑行轨道值的方式,在b站貌似不需要的。
ActionChains(browser).click_and_hold(slider).perform() #按住不松
ActionChains(browser).move_by_offset(xoffset=offpx, yoffset=0).perform()
ActionChains(browser).move_by_offset(xoffset=-3, yoffset=0).perform()
time.sleep(0.2)
ActionChains(browser).move_by_offset(xoffset=3, yoffset=0).perform()
time.sleep(0.1)
ActionChains(browser).move_by_offset(xoffset=-2, yoffset=0).perform()
time.sleep(0.3)
ActionChains(browser).move_by_offset(xoffset=2, yoffset=0).perform()
time.sleep(0.1)
ActionChains(browser).release(slider).perform() #松开

目前登录还是蛮准确的,但是登录上去干啥还没想好。
因为代码在jupyter notebook中测试的,有点乱就不整理了。因为我发现:

使用浏览器配置文件自动登录网站
# coding = utf-8
from selenium import webdriver

profileDir = r'yourprofiledir' #你的配置文件目录
profile = webdriver.FirefoxProfile(profileDir)
driver = webdriver.Firefox(profile)
driver.get("https://passport.bilibili.com/login")

直接就登录了,气人不气人?
firefox: 获取配置文件目录的方法是:在浏览器中键入:about:support找到“配置文件夹”…
Chrome: 地址栏访问chrome://version,可以查看用户资料存储位置:

参考资料
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值