之前剛開始做爬蟲的時(shí)候遇到過登錄驗(yàn)證碼問題,看過很多帖子都沒有解決我的問題,發(fā)現(xiàn)大多數(shù)帖子都是治標(biāo)不治本,于是想分享一下自己的解決方案。本次采用的網(wǎng)站是古詩文網(wǎng),使用百度API,因?yàn)榘俣華PI免費(fèi)!免費(fèi)!免費(fèi)!適合自己學(xué)習(xí)的時(shí)候使用。如果還沒有使用過百度API識別驗(yàn)證碼的朋友可以看一下我的這個(gè)帖子。
以下案例采用的時(shí)古詩文網(wǎng):登錄古詩文網(wǎng),
1、selenium處理圖片驗(yàn)證碼
先定位到驗(yàn)證碼圖片,在獲取驗(yàn)證碼圖片在頁面中的位置,使用save_screenshot截取頁面,再根據(jù)圖片的位置去截取驗(yàn)證碼,最后通過接口識別文字獲取驗(yàn)證碼,直接上代碼:
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
|
element = driver.find_element_by_id( 'imgCode' ) # 定位驗(yàn)證碼圖片 # 獲取驗(yàn)證碼圖片在網(wǎng)頁中的位置 left = int (element.location[ 'x' ]) # 獲取圖片左上角坐標(biāo)x top = int (element.location[ 'y' ]) # 獲取圖片左上角y right = int (element.location[ 'x' ] + element.size[ 'width' ]) # 獲取圖片右下角x bottom = int (element.location[ 'y' ] + element.size[ 'height' ]) # 獲取圖片右下角y # 通過Image處理圖像 path = current_dir + str (random.random()) + '.png' # 生成隨機(jī)文件名 driver.save_screenshot(path) # 截取當(dāng)前窗口并保存圖片 im = Image. open (path) # 打開圖片 im = im.crop((left, top, right, bottom)) # 截圖驗(yàn)證碼 im.save(path) # 保存驗(yàn)證碼圖片 # 使用百度API識別驗(yàn)證碼 def get_code(): client = AipOcr(APP_ID, API_KEY, SECRET_KEY) # 百度API文檔中提供的方法識別文字 # 由于我處理的驗(yàn)證碼圖片沒有填多的線條,所以直接采用灰度是驗(yàn)證碼數(shù)字更加清晰,具體的處理方式可根據(jù)驗(yàn)證碼的實(shí)際情況而定 im = Image. open (path) # 轉(zhuǎn)換為灰度圖像 im = im.convert( 'L' ) im.save(path) # 讀取圖片,應(yīng)為百度API中提供的方法參數(shù)只能是字節(jié)流 with open (path, 'rb' )as f: image = f.read() # 使用API中提供的方法識別驗(yàn)證碼并返回驗(yàn)證碼 code = client.basicGeneral(image) print (code[ 'words_result' ][ 0 ][ 'words' ]) # {'words_result': [{'words': '4TBiD ', 'location': {'top': 1, 'left': 6, 'width': 43, 'height': 13}}], 'log_id': 1358288307112378368, 'words_result_num': 1} return code[ 'words_result' ][ 0 ][ 'words' ] |
2、使用requests請求驗(yàn)證碼
這里用到了會話機(jī)制,對于初學(xué)者來說可能不太了解,簡單說一下會話機(jī)制的作用,會話就是用來保存你之前請求的cookie,讓瀏覽器知道你之前就在這里,這樣瀏覽器就不會認(rèn)為你重新來到這里,從而刷新驗(yàn)證碼,這樣就可以帶著我們獲取的驗(yàn)證碼去登錄了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
conn = requests.Sessoin( # 創(chuàng)建會話 resp = conn.get( 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx' ) selector = Selector(text = resp.text) img_url = 'https://so.gushiwen.cn/' + selector.xpath( './/img[@id="imgCode"]/@src' ).get() # 獲取圖片的路由 img = conn.get(img_url) # 保持會話請求 filename = str (random.random()) + '.png' with open (filename, 'wb' )as f: f.write(img.content) # 為了后面的調(diào)用接口識別不報(bào)圖片格式錯(cuò)誤,進(jìn)行一次圖片轉(zhuǎn)換 im = Image. open (filename) im.save(filename) # 使用二進(jìn)制方式讀取圖片 with open (filename, 'rb' )as f: image = f.read() data = client.handwriting(image) # diao'yong # 使用API中提供的方法識別驗(yàn)證碼并返回驗(yàn)證碼 code = client.basicGeneral(image) code = code[ 'words_result' ][ 0 ][ 'words' ] |
selenium源碼
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
|
# -* coding: utf-8 *- import time import random from PIL import Image from aip import AipOcr from selenium.webdriver import Chrome # 百度API參數(shù) APP_ID = '23647800' API_KEY = 'n95KOQgVuOMoAP72qZZo7uoN' SECRET_KEY = '7yhyGglHUsY52DD8kf4w0Qjnxum07hMK' client = AipOcr(APP_ID, API_KEY, SECRET_KEY) # 調(diào)用API接口 def scrapy(username, password): """ :param username: 用戶名 :param password: 密碼 """ driver = Chrome() driver.get( 'https://so.gushiwen.cn/user/login.aspx' ) driver.find_element_by_id( 'email' ).send_keys(username) # 輸入賬號 driver.find_element_by_id( 'pwd' ).send_keys(password) # 輸入密碼 element = driver.find_element_by_id( 'imgCode' ) # 定位驗(yàn)證碼圖片 # 獲取驗(yàn)證碼圖片在網(wǎng)頁中的位置 left = int (element.location[ 'x' ]) # 獲取圖片左上角坐標(biāo)x top = int (element.location[ 'y' ]) # 獲取圖片左上角y right = int (element.location[ 'x' ] + element.size[ 'width' ]) # 獲取圖片右下角x bottom = int (element.location[ 'y' ] + element.size[ 'height' ]) # 獲取圖片右下角y # 通過Image處理圖像 filename = str (random.random()) + '.png' # 生成隨機(jī)文件名 driver.save_screenshot(filename) # 截取當(dāng)前窗口并保存圖片 im = Image. open (filename) # 打開圖片 im = im.crop((left, top, right, bottom)) # 截圖驗(yàn)證碼 im.save(filename) # 保存驗(yàn)證碼圖片 # 由于我處理的驗(yàn)證碼圖片沒有填多的線條,所以直接采用灰度是驗(yàn)證碼數(shù)字更加清晰,具體的處理方式可根據(jù)驗(yàn)證碼的實(shí)際情況而定 im = Image. open (filename) # 轉(zhuǎn)換為灰度圖像 im = im.convert( 'L' ) im.save(filename) # 讀取圖片,應(yīng)為百度API中提供的方法參數(shù)只能是字節(jié)流 with open (filename, 'rb' )as f: image = f.read() # 使用API中提供的方法識別驗(yàn)證碼并返回驗(yàn)證碼 data = client.basicGeneral(image) try : code = data[ 'words_result' ][ 0 ][ 'words' ] except : return data[ 'error_msg' ] driver.find_element_by_id( 'code' ).send_keys(code) # 輸入驗(yàn)證碼 driver.find_element_by_id( 'denglu' ).click() # 點(diǎn)擊登錄 time.sleep( 1000 ) # 為了看清登錄,等待1000秒 if __name__ = = '__main__' : print (scrapy(username, password)) # 傳入你在古詩文網(wǎng)注冊的賬號密碼 |
requests源碼
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
|
# -* coding: utf-8 *- import os import random import re import requests from PIL import Image from aip import AipOcr from scrapy import Selector headers = { 'referer' : 'https://so.gushiwen.cn/user/login.aspx' , 'user-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36' } # 百度API參數(shù) APP_ID = '23647800' API_KEY = 'n95KOQgVuOMoAP72qZZo7uoN' SECRET_KEY = '7yhyGglHUsY52DD8kf4w0Qjnxum07hMK' def scrapy(username, password): """ :param username: 用戶名 :param password: 密碼 """ client = AipOcr(APP_ID, API_KEY, SECRET_KEY) # 調(diào)用API接口 conn = requests.Session() # 創(chuàng)建會話 resp = conn.get( 'https://so.gushiwen.cn/user/login.aspx' , headers = headers) # 獲取登錄頁面 selector = Selector(text = resp.text) __VIEWSTATE = selector.xpath( './/input[@id="__VIEWSTATE"]/@value' ).get() __VIEWSTATEGENERATOR = selector.xpath( './/input[@id="__VIEWSTATEGENERATOR"]/@value' ).get() img_url = 'https://so.gushiwen.cn/' + selector.xpath( './/img[@id="imgCode"]/@src' ).get() # 獲取圖片的路由 img = conn.get(img_url, headers = headers) # 獲取圖片路由 # 保存圖片 filename = str (random.random()) + '.png' # 隨機(jī)生成文件名, 圖片格式不能為jpg,API不支持jpg格式的識別 with open (filename, 'wb' )as f: f.write(img.content) # 由于我處理的驗(yàn)證碼圖片沒有填多的線條,所以直接采用灰度是驗(yàn)證碼數(shù)字更加清晰,具體的處理方式可根據(jù)驗(yàn)證碼的實(shí)際情況而定 im = Image. open (filename) # 轉(zhuǎn)換為灰度圖像 im = im.convert( 'L' ) im.save(filename) # 使用二進(jìn)制方式讀取圖片 with open (filename, 'rb' )as f: image = f.read() # # 標(biāo)準(zhǔn)識別, 每天免費(fèi)50000次 # data = client.basicGeneral(image) # 精確識別,每天免費(fèi)500次 data = client.handwriting(image) # 捕獲一下接口識別當(dāng)中的錯(cuò)誤,可參照文檔查看報(bào)錯(cuò)原因 try : code = data[ 'words_result' ][ 0 ][ 'words' ] except : return data[ 'error_msg' ] form_data = { '__VIEWSTATE' : __VIEWSTATE, '__VIEWSTATEGENERATOR' : __VIEWSTATEGENERATOR, 'from' : '', 'email' : username, 'pwd' : password, 'code' :cod, 'denglu' : '登錄' } # 登錄 html = conn.post( 'https://so.gushiwen.cn/user/login.aspx' , headers = headers, data = form_data).text # 獲取登錄標(biāo)志位 login_flag = re.findall( "alert\('(.*?)'\);" ,html)[ 0 ] if re.findall( "alert\('(.*?)'\);" ,html) else '' if not login_flag: return '登錄成功!' elif '驗(yàn)證碼有誤!' in login_flag: return "驗(yàn)證碼錯(cuò)誤" if __name__ = = '__main__' : print (scrapy(username, password)) |
以上就是python爬蟲如何解決圖片驗(yàn)證碼的詳細(xì)內(nèi)容,更多關(guān)于python 解決圖片驗(yàn)證碼的資料請關(guān)注服務(wù)器之家其它相關(guān)文章!
原文鏈接:https://www.cnblogs.com/yanghui3306/p/14385826.html