解析登录网址 首先我们要定位到登录的网址以便driver访问。
将浏览器打开到登录页面,可以看到对应的网址为
1 https://jaccount.sjtu.edu.cn/jaccount/jalogin?sid=jaoauth220160718&client=CAzoSoajfvlBJKYW7q11rIlS5ucaE%2FIWcLi2eNuNEJDa&returl=CPDcg4bZMUVfWbZWFi2BIAB%2BzZprZ2JnKxq%2Bd6MsjeS0nMw73qkvsCxG47FeRZmpnkzSb7Gf%2FCPIbwa%2BNH267zBN%2BexUD2RL%2BhgfQzpYNJ96UJUYoajLq%2Fqgx6g%2BL2Ol6i3p5RWYYIcKoV28CmbnNbPia3K1RfdgUgktPh4yNrgYsIciWlBvtMDF%2FLrJfK4rGV9Z%2BbdiXK6EFaQJId4mZXj45XlS2pmQtR5P6qOeSj3nvLDaxZ6bablX7cNO5IhPAmaj%2BMOH%2Fx5F7YpIbYoZg3R01iV6Rd7oO8pSmHFTFkvhJFWPTWI1C01nBDaKato1IDv%2BP0%2FF8C6e%2BTDf6MOGmge0SAXgweU0o4I2v06Xb5nDWAGGTAtyB2Vm0qxD7RB6C74n77jiGIGju4y13a%2Fi10RO4pmfPcik9st2unhTWfVMqDtYd%2BJ9jCjl8UOoel8G99qS7ET%2FVN%2FbP%2BfUkBJb7I8%3D&se=CBZz3nk3K70uQiJvss5rVxhD4A5GYffm65sDqZ6Zh2PbEFVqISnzjU2JVjCO1VYIYuNZMv%2F8W6s3
很明显这是拼接了随机数的网址而不是真正应该访问的,为了得到真正的登录页面的网址,需要动态解析。
打开一开始的登录选项,要点击校内用户登录才会加载出真正的登录页面,因此可以猜测这是一个动态加载的页面。所以我们打开页面控制台,点击Network 选项,一开始是空白的,等待新加载的信息。
然后点击登录按钮,会跳转到登录页面。左边的控制台已经加载了许多信息,要在这些信息中找到加载网址的信息,一般来说我们查看第一条条目即可。
选中第一条,可以看到请求的url,这就是真正的登录页面的网址,这里可以复制这个地址打开看看是不是正确的,如果不是就继续找。
模拟登录 得到网址后,可以进行登录。登录一般来说有两种方式,一种是用requests库的post请求,一种是用selenium的driver直接进行网页模拟登录。这里选择用driver的方式主要基于以下两个方面:
目的上看,我们想要自动登录后还能够操纵我们的网页干其他事情,用driver的话刚刚好
从可行性的角度上看,登录过程我们需要验证码识别,如果用requests库抓取,前面提到抓取下来的验证码是不一样的,每次抓取都会改变内容。因此我能想到的解决方法就是用driver的页面进行静态的截图,实际上这符合我们人眼识别的过程。
因此,我们对于验证码的识别就是根据截图来进行的。同样,这里使用我们之前训练的模型,因此要把模型先放到model.py里面。下面给出处理验证码的代码文件。首先定义验证码信息参数,如长度、大小等。然后我们要把模型初始化,加载参数的过程会比较慢(推理很快),我们不想浪费这段时间,由于用driver打开网页也需要一段时间,因此就可以开一个线程来加载参数,与此同时打开网页,可以节省一些时间。
然后定义了截图操作,先截全屏再截下验证码。这里验证码的位置信息通过网页源代码(html)的信息获取,用xpath、class、id定位都行,在webdriver都定义了相关的操作。需要注意的是scaling_ratio 这一变量,要截下正确的验证码位置与我们屏幕的缩放比例有关。可以在桌面上右键点击显示设置,然后查看屏幕的缩放与布局,根据缩放的比例设置变量。
最后还有一个验证码解码的方法,实际上这跟前面predict.py的操作类似。所有代码如下:
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 from model import CNN_sjtuimport torch.nnimport torchfrom PIL import Imagefrom torchvision.transforms import Compose, ToTensor, Resize,Normalizeimport timefrom selenium.webdriver.common.by import Byfrom threading import Threadimport warningswarnings.filterwarnings("ignore" ) numchar = 4 alphabet = 'abcdefghijklmnopqrstuvwxyz' width = 100 height = 40 model_net = CNN_sjtu(num_class=len (alphabet), num_char=int (numchar), width=width, height=height) model_net = model_net.cuda() model_net.eval () def load_net (): global model_net print ("load net......" ) model_net.load_state_dict(torch.load(r'C:\Users\14242\PycharmProjects' r'\DL\Pytorch_project\captcha-CNN-验证码识别\weights/model_sjtu_4.path' )) thread_load= Thread(target=load_net) thread_load.start() def decode_captcha (img_path ): global model_net with torch.no_grad(): img=Image.open (img_path) img = img.convert('RGB' ) transforms = Compose([Resize((height, width)), ToTensor(), Normalize(0 , 1 )]) img = transforms(img) img = img.view(1 , 3 , height, width).cuda() output = model_net(img) output = output.view(-1 , len (alphabet)) output = torch.nn.functional.softmax(output, dim=1 ) output = torch.argmax(output, dim=1 ) output = output.view(-1 , numchar)[0 ] return '' .join([alphabet[i] for i in output.cpu().detach().numpy()]) def get_snap (driver ): driver.save_screenshot('full_snap.png' ) page_snap_obj=Image.open ('full_snap.png' ) return page_snap_obj def get_image (driver ): scaling_ratio=1 img = driver.find_element(By.XPATH, '//*[@id="captcha-img"]' ) time.sleep(0.10 ) location = img.location size = img.size left = location['x' ]*scaling_ratio top = location['y' ]*scaling_ratio right = left + size['width' ]*scaling_ratio bottom = top + size['height' ]*scaling_ratio page_snap_obj = get_snap(driver) image_obj = page_snap_obj.crop((left, top, right, bottom)) image_obj.save('captcha.png' )
下面是我们登录的主程序,注意这种方式要先下载对应于谷歌浏览器版本号的chromedriver.exe放到当前的目录下。
通过send_keys()
方法填入用户名、密码、验证码;接着通过click()
方法自动点击登录按钮即可,注意操作网页的过程一定要适当地等待加载(sleep)。
由于验证码可能识别错误,因此要循环判断是否成功登录,直到成功再停止。我的方法是判断当前页面的title 是否发生了改变,这是一个比较简单方便的方式。
最后,由于一开始我们生成了两个截图,可以用os.remove()
将其删除。
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 from captcha import decode_captcha as decode_cfrom captcha import get_imagefrom selenium import webdriverimport timeimport osfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.common.by import Byoptions = Options() driver = webdriver.Chrome(options=options) driver.maximize_window() captcha_path='./captcha.png' snap_path='./full_snap.png' url = 'https://i.sjtu.edu.cn/jaccountlogin' url ='https://oc.sjtu.edu.cn/login/openid_connect' driver.get(url) cur_title=driver.title while (driver.title==cur_title): time.sleep(0.10 ) get_image(driver) print ("推理验证码......" ) captcha_res=decode_c(captcha_path) driver.find_element(By.NAME, 'user' ).send_keys('username' ) driver.find_element(By.NAME, 'pass' ).send_keys('password' ) driver.find_element(By.NAME,'captcha' ).send_keys(captcha_res) driver.find_element(By.ID,"submit-button" ).click() os.remove(captcha_path) os.remove(snap_path) print ("ending......" )