咳咳,再这样下去会进橘子叭hhhhhh
以及,这个我觉得大概率是成功的,因为测试了太多次,登录并且验证之后,qq提醒我要我修改密码才可以登录捏QAQ
有关selenium具体是啥,这里就不再赘述了,其他的博客分享的都很清楚,我就大概说一下:selenium是一个模拟用户操作的工具,通过selenium就可以点击网页中某一按钮,或者拖动某一图形(是捏,首先想到的就是滑块验证hhhhh
写在最前面:
如果想要使用selenium,就需要安装对应的浏览器驱动。例如使用谷歌浏览器,就要安装对应版本的驱动;使用火狐浏览器,就要安装对应版本的火狐驱动
除此之外,敲重点!!!selenium需安装3.x的版本,否则就会有闪退的情况哈!!!
我所使用的是谷歌浏览器,版本号如下(想要查询谷歌的版本号,点击右上角的三个点,找到最下面的帮助->关于谷歌就看到啦):
根据这个版本号,去网上搜了一下,找到了一个可以下载驱动的网址~
我看其他人也会用这个下载驱动的网址,不过截至到2024年2月初,谷歌的最新版本已经是121啦,有点高,所以大家用第一个就好啦
下载了驱动后,将其放进谷歌的文件夹里,我的是这个(应该一般都是C盘的这个文件夹叭hhhhhh)
然后将绿线的这个文件路径放到环境变量里就好啦
接下来,看一下怎么使用这个驱动哈~
from selenium import webdriver from selenium.webdriver import ChromeOptions # 实现规避检测 option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) # 实例化浏览器 Chrome_Drive_Path = 'C:\Program Files\Google\Chrome\Application\chromedriver.exe' driver = webdriver.Chrome(executable_path=Chrome_Drive_Path, options=option) # 网页屏幕最大化 driver.maximize_window() driver.get('https://im.qq.com/index/')
然后就发现qq的页面被自动打开啦!!!
打开了qq页面后,我们需要点击登录按钮,但是这个操作肯定不能由我们自己做,所以就需要selenium来帮咱们完成这个工作啦(power!!!)
首先,需要找到这个登录按钮的位置,找到之后,就可以根据这个标签的name在网页中定位到这个标签,然后点击它啦
# find_element_by_name根据name定位 # 如果标签中有id也可以用id定位,如果有class也可以用class定位 login_btn = driver.find_element_by_name('im.qq.com.login') # 找到后点击 login_btn.click()
然后,点击登录后,就会出现如下界面啦,咱们肯定选择密码登录啦,需要找到密码登录的按钮,也就是红线标出的位置~
但是这里可以看到,密码登录这个按钮是在整个页面的子页面里,也就是html里又嵌套了一个html,这个也就是iframe。如果想要在这个子页面中找到某个标签,就需要多一步——即进入这个页面的操作
# 进入嵌套的子页面中,frame-login就是
然后,就可以到输入账号密码这一环节啦~
老规矩,定位到这两个文本框的位置,然后借助selenium输入咱的qq号和密码~
name = driver.find_element_by_id('u') # 向文本框中填入 name.send_keys('qq号') pwd = driver.find_element_by_id('p') pwd.send_keys('qq密码') sleep(1) btn = driver.find_element_by_id('login_button') btn.click() # 点击登录后的下一个页面是验证,为了避免页面还未加载完就定位标签,在这里加上1s的停顿,然后再进行后续的操作 sleep(1)
然后,验证的页面就出现啦!!!
这个部分我做了两天,吐血了!!!
先简述一下这部分怎么做哈:
其实整体思路还挺简单的,但是有关截图和点击坐标那里,实在是太麻烦啦!!!
(当然也有可能是我的技术有限,如果大家有其他的方法请指导我一下,蟹蟹您!!!)
首先,封装一个超级鹰的工具:
def getCode(filePath): c = Chaojiying_Client('超级鹰的账号', '超级鹰的密码', '软件Key') im = open(filePath, 'rb').read() # 注意这个的9004,由字母数字验证码的1902改成了图像识别验证码的9004 return c.PostPic(im, 9004)['pic_str']
然后,将整个页面截取下来,并且获取页面的尺寸和截图下来的页面的尺寸(是的,这两个尺寸不一样,这就是整个操作中最狗的地方)
driver.save_screenshot('total.png') # 整个页面的尺寸 size_total = driver.get_window_size() # 截图页面的尺寸 img_total = Image.open('total.png') w, h =img_total.size
然后,我们想要将验证码这一部分截取下来,就需要验证码的尺寸,定位到验证码这里,就发现这六张图片其实是一个图片,当然,它依旧在一个iframe里~
# 进入iframe中 driver.switch_to.frame('tcaptcha_iframe_dy') # 定位到验证码的图片部分,我这里用的是xpath(在img标签右键->copy->full xpath就有啦) code_total = driver.find_element_by_xpath('/html/body/div/div[3]/div[2]/div[1]/div[1]/img') # 获取验证码的尺寸 size = code_total.size
接下来就对验证码的部分进行截取(这里需要注意一个问题,网页的尺寸和截图网页的尺寸是不一样的,而咱们获得的验证码的尺寸与网页的尺寸是吻合的,所以如果要在截图网页上再截取验证码部分,就没办法太精确,我的建议是截的大一些)
rangle = ( int(w/2 - size['width']*w/size_total['width']), int(h/2 - size['height']*h/size_total['height']), int(w/2 + size['width']*w/size_total['width']), int(h/2 + size['height']*h/size_total['height']) ) img_code = img_total.crop(rangle) img_code.save('code.png')
这里的rangle就是坐标啦,这样就可以获得验证码的图片啦(就是这么大~)
然后,得到了验证码的图片后,就可以提交给超级鹰啦
# res的结果是这样的,中间以“|”作为分隔符 # x1的坐标,y1的坐标|x2的坐标,y2的坐标|x3的坐标,y3的坐标 res = getCode('code.png')
在这里需要判断一下这个结果res是不是一个空值,如果是空值,就点击一下刷新的按钮
if len(res)==0: print('超级鹰结果为空') ref = driver.find_element_by_css_selector('.status-normal') ref.click()
然后,从res中分割出坐标,放进列表里(这里就是抄的网课啦)~
axis_list = [] if '|' in res: list = res.split('|') count = len(list) for i in range(count): xy_list = [] x = int(list[i].split(',')[0]) y = int(list[i].split(',')[1]) xy_list.append(x) xy_list.append(y) axis_list.append(xy_list) else: xy_list = [] x = int(res.split(',')[0]) y = int(res.split(',')[1]) xy_list.append(x) xy_list.append(y) axis_list.append(xy_list)
然后然后然后,就是点击图片这里啦
这里需要注意,我们所得到的截图的尺寸,和网页的尺寸是不一样的,所以这里要转成网页的坐标,就需要处理一下经过截图得到的坐标~
for axis in axis_list: # 这里是截图的坐标,在原截图的坐标上加超级鹰的结果就行 x = int(w/2-size['width']*w/size_total['width']+axis[0]) y = int(h/2-size['height']*h/size_total['height']+axis[1]) # 截图的尺寸转成网页的尺寸 x = int(x*size_total['width']/w) y = int(y*size_total['height']/h) # 这是一个动作链,简单来说,就是鼠标一次会移动距离(x, y),然后点击一下click() # 为了使得上面这个动作链执行,需要perform() ActionChains(driver).move_by_offset(x, y).click().perform() # 这里注意一下,每次move_by_offset都是在上一次操作的坐标那里开始移动吗,也就是相对距离 # 但是我们得到的绝对坐标吖,所以就需要加上reset_actions(),让动作链每一次都返回到(0,0)原坐标 ActionChains(driver).reset_actions() # 每次停顿1s sleep(1) # 点击确认按钮 ver_btn = driver.find_element_by_css_selector('.verify-btn') ver_btn.click()
在网页上就可以看到相应的图片被选中了,如果没有选中,那一定是你的坐标算错啦!!!
最后,最后的结果就变成这个样了(叹气)
from selenium import webdriver from selenium.webdriver import ActionChains, ChromeOptions from selenium.webdriver.chrome.service import Service from time import sleep from PIL import Image from chaojiying import Chaojiying_Client def getCode(filePath): c = Chaojiying_Client('超级鹰账号', '超级鹰密码', '软件Key') im = open(filePath, 'rb').read() return c.PostPic(im, 9004)['pic_str'] if __name__ == "__main__": # 实现规避检测 option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) # 实例化浏览器 Chrome_Drive_Path = 'C:\Program Files\Google\Chrome\Application\chromedriver.exe' # 4.x版本的用法,但是因为会闪退,就放弃了 # chrome_driver_path_obj = Service(Chrome_Drive_Path) # driver = webdriver.Chrome(service=chrome_driver_path_obj) driver = webdriver.Chrome(executable_path=Chrome_Drive_Path, options=option) driver.maximize_window() driver.get('https://im.qq.com/index/') login_btn = driver.find_element_by_name('im.qq.com.login') login_btn.click() driver.switch_to.frame('frame-login') pwd_btn = driver.find_element_by_id('switcher_plogin') pwd_btn.click() name = driver.find_element_by_id('u') name.send_keys('qq账号') pwd = driver.find_element_by_id('p') pwd.send_keys('qq密码') sleep(1) btn = driver.find_element_by_id('login_button') btn.click() sleep(1) # 图片验证码 # 定位整张验证码图片的标签 driver.switch_to.frame('tcaptcha_iframe_dy') code_total = driver.find_element_by_xpath('/html/body/div/div[3]/div[2]/div[1]/div[1]/img') size_total = driver.get_window_size() size = code_total.size # # 对整张图片进行截图 driver.save_screenshot('total.png') img_total = Image.open('total.png') w, h =img_total.size rangle = ( int(w/2 - size['width']*w/size_total['width']), int(h/2 - size['height']*h/size_total['height']), int(w/2 + size['width']*w/size_total['width']), int(h/2 + size['height']*h/size_total['height']) ) img_code = img_total.crop(rangle) img_code.save('code.png') # # print('网页尺寸', size_total) # # 超级鹰 res = getCode('code.png') print(res) # if len(res)==0: print('超级鹰结果为空') ref = driver.find_element_by_css_selector('.status-normal') ref.click() axis_list = [] if '|' in res: list = res.split('|') count = len(list) for i in range(count): xy_list = [] x = int(list[i].split(',')[0]) y = int(list[i].split(',')[1]) xy_list.append(x) xy_list.append(y) axis_list.append(xy_list) else: xy_list = [] x = int(res.split(',')[0]) y = int(res.split(',')[1]) xy_list.append(x) xy_list.append(y) axis_list.append(xy_list) # 点击验证码 for axis in axis_list: x = int(w/2-size['width']*w/size_total['width']+axis[0]) y = int(h/2-size['height']*h/size_total['height']+axis[1]) x = int(x*size_total['width']/w) y = int(y*size_total['height']/h) print('超级鹰结果', x, y) ActionChains(driver).move_by_offset(x, y).click().perform() # 每一次都从(0,0)开始移动 ActionChains(driver).reset_actions() sleep(1) # 点击确认 ver_btn = driver.find_element_by_css_selector('.verify-btn') ver_btn.click() sleep(1)