一个网页不需要登录,就可以随意访问网站的所有具体信息的话,那就好比是一个敞开了大门的网站,摆好酒桌好吃好喝招待爬虫脚本们,数据提取的成本非常低。于是比较常规的网站,都会使用账号登录来提高网站对于每个想要查看网站数据的门槛,所以模拟登陆的问题就是必修课

我目前接触到的模拟登录方式就两种,一个是解析登录接口,查看具体提交的表单,密码的加密方式,用到的一般是request这样的库。优点是运行快,缺点是开发成本大;第二个就是selenium这种自动化测试工具模拟一个正常用户的具体登录操作:打开,鼠标移动、点击,输入账号密码,最后点击登录,这种方式的有点是省事,不需要慢慢查看具体提交的表单信息,但在缺点上除了运行慢之外,一般还有一个不小的麻烦,就是形式复杂的验证码。

说实话第一种实现方式,过于复杂,基本没有接触(对于大流量网站),于是主要还是说明第二种实现方式:selenium库和验证码破解

selenium的模拟操作上,无非就是webdriver.find_element_by_XXX("")找到某个input元素,用.send_keys("user or password")输入后,使用.click()来点击登录,这上面一般没有问题。

但是最大的麻烦一般就会在.click()操作后出现,那就是验证码...

注意

图片缺失:2020/08/weibo_V.png 原因:uploads 归档中不存在此路径的文件 原链接:https://kutake.site/wp-content/uploads/2020/08/weibo_V.png

比如微博的验证码

当你打开F12,找到验证码的请求url时,会发现一个问题,那就是每次请求返回的图片结果都不一样,所以我们使用selenium的截图功能来实现

具体流程:

  • 打开页面
  • 输入账号密码
  • 点击登录弹出验证码
  • webdriver.save_screenshot截全图
  • find定位验证码元素
  • .location获取验证码元素坐标
  • 依据坐标使用.crop剪裁
  • 得到的图片使用云打码平台等识别验证码
  • 输入,点击登录

验证码处理

如果使用靠谱的打码平台,那可能不需要使用这种手段对得到的验证码图片进行处理,但如果是使用百度阿里等图片识别平台,那就需要进行转灰和二值化验证码操作

注意

图片缺失:2020/08/convert_ver.png 原因:uploads 归档中不存在此路径的文件 原链接:https://kutake.site/wp-content/uploads/2020/08/convert_ver.png

普通验证码转灰

注意

图片缺失:2020/08/convert.jpg 原因:uploads 归档中不存在此路径的文件 原链接:https://kutake.site/wp-content/uploads/2020/08/convert.jpg

转灰

注意

图片缺失:2020/08/pcode.jpg 原因:uploads 归档中不存在此路径的文件 原链接:https://kutake.site/wp-content/uploads/2020/08/pcode.jpg

复杂背景验证码

就像这样

可以方便模型更好识别出文字,字母或者数字

代码

#weibo_login_sele.py
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
import requests
from selenium.common.exceptions import NoSuchElementException
from PIL import Image
import matplotlib.pyplot as plt
from aip import AipOcr
def main():
    test_webdriver = webdriver.Chrome()
    test_webdriver.maximize_window()
    test_webdriver.get("https://weibo.com/login.php")
    user="user"
    passwd = "pass"
    element_user = WebDriverWait(test_webdriver,5,0.5).until(EC.presence_of_element_located((By.XPATH,"//input[@id='loginname']")))
    time.sleep(0.5)
    element_user.send_keys(user)
    element_pw = WebDriverWait(test_webdriver,5,0.5).until(EC.presence_of_element_located((By.XPATH,"//input[@name='password']")))
    time.sleep(0.5)
    element_pw.click()
    time.sleep(0.5)
    element_pw.send_keys(passwd)
    #test_webdriver.find_element_by_xpath("//a[@node-type='submitBtn']").click()
    time.sleep(2.5)

    e = test_webdriver.find_element_by_xpath("//img[@node-type='verifycode_image']")
    time.sleep(0.5)
    img = "weibo.png"
    element_verify = e
    time.sleep(1)
    test_webdriver.save_screenshot(img)
    print(element_verify.location)
    print(element_verify.size)
    left = element_verify.location['x']
    top = element_verify.location['y']
    right = element_verify.location['x'] + element_verify.size['width']
    bottom = element_verify.location['y'] + element_verify.size['height']
    im = Image.open(img)
    verifycode_image = im.crop((left,top,right,bottom))

    ver = verifycode_image.convert("L")
    ver.save("convert_ver.png")
    get_api()
    #test_webdriver.quit()
    #saveImgLight()

def saveImgLight():
    im = Image.open("code.jpg")
    #plt.imshow(im)
    #plt.show()
    im1 = im.crop((0,0,344,343))
    im2 = im.crop((0,343,115,382))
    im2.save("word.jpg")
    im1.save("pcode.jpg")
    #转灰
    im3 = im1.convert("L")
    im3.save("convert.jpg")
    #二值化
    #im4 = im1.point(lambda p:p * 4)
    #im4.save("point.jpg")
def get_api():
    APP_ID = 'ID'
    API_KEY = 'KEY'
    SECRET_KEY = 'S_KEY'
    client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
    options = {}
    with open("convert_ver.png","rb") as f1:
        p1=f1.read()
    #with open("word.jpg","rb") as f2:
        #p2=f2.read()
    options["language_type"] = "ENG"
    lo1 = client.accurate(p1,options)
    #lo2 = client.accurate(p2,options)
    print(lo1)
    #print(lo2)
main()