国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

【Python爬蟲7】驗證碼處理

2019-11-08 03:19:17
字體:
來源:轉載
供稿:網友

獲得驗證碼圖片光學字符識別驗證碼用API處理復雜驗證碼1 9kw打碼平臺11 提交驗證碼12 請求已提交驗證碼結果12與注冊功能集成

驗證碼(CAPTCHA)全稱為全自動區分計算機和人類的公開圖靈測試(Completely Automated Public Turing test to tell Computersand Humans Apart)。從其全稱可以看出,驗證碼用于測試用戶是真實的人類還是計算機機器人。

1.獲得驗證碼圖片

每次加載注冊網頁都會顯示不同的驗證驗圖像,為了了解表單需要哪些參數,我們可以復用上一章編寫的parse_form()函數。

>>> import cookielib,urllib2,pPRint>>> import form>>> REGISTER_URL = 'http://127.0.0.1:8000/places/default/user/register'>>> cj=cookielib.CookieJar()>>> opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))>>> html=opener.open(REGISTER_URL).read()>>> form=form.parse_form(html)>>> pprint.pprint(form){'_formkey': 'a67cbc84-f291-4ecd-9c2c-93937faca2e2', '_formname': 'register', '_next': '/places/default/index', 'email': '', 'first_name': '', 'last_name': '', 'passWord': '', 'password_two': '', 'recaptcha_response_field': None}>>>

上面recaptcha_response_field是存儲驗證碼的值,其值可以用Pillow從驗證碼圖像獲取出來。先安裝pip install Pillow,其它安裝Pillow的方法可以參考http://pillow.readthedocs.org/installation.html 。Pillow提價了一個便捷的Image類,其中包含了很多用于處理驗證碼圖像的高級方法。下面的函數使用注冊頁的HTML作為輸入參數,返回包含驗證碼圖像的Image對象。

>>> import lxml.html>>> from io import BytesIO>>> from PIL import Image>>> tree=lxml.html.fromstring(html)>>> print tree<Element html at 0x7f8b006ba890>>>> img_data_all=tree.CSSselect('div#recaptcha img')[0].get('src')>>> print img_data_alldata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABgCAIAAAB9kzvfAACAtklEQVR4nO29Z5gcZ5ku3F2dc865...rkJggg==>>> img_data=img_data_all.partition(',')[2]>>> print img_dataiVBORw0KGgoAAAANSUhEUgAAAQAAAABgCAIAAAB9kzvfAACAtklEQVR4nO29Z5gcZ5ku3F2dc865...rkJggg==>>> >>> binary_img_data=img_data.decode('base64')>>> file_like=BytesIO(binary_img_data)>>> print file_like<_io.BytesIO object at 0x7f8aff6736b0>>>> img=Image.open(file_like)>>> print img<PIL.PngImagePlugin.PngImageFile image mode=RGB size=256x96 at 0x7F8AFF5FAC90>>>>

在本例中,這是一張進行了Base64編碼的PNG圖像,這種格式會使用ASCII編碼表示二進制數據。我們可以通過在第一個逗號處分割的方法移除該前綴。然后,使用Base64解碼圖像數據,回到最初的二進制格式。要想加載圖像,PIL需要一個類似文件的接口,所以在傳給Image類之前,我們以使用了BytesIO對這個二進制數據進行了封裝。 完整代碼:

# -*- coding: utf-8 -*-form.pyimport urllibimport urllib2import cookielibfrom io import BytesIOimport lxml.htmlfrom PIL import ImageREGISTER_URL = 'http://127.0.0.1:8000/places/default/user/register'#REGISTER_URL = 'http://example.webscraping.com/user/register'def extract_image(html): tree = lxml.html.fromstring(html) img_data = tree.cssselect('div#recaptcha img')[0].get('src') # remove data:image/png;base64, header img_data = img_data.partition(',')[-1] #open('test_.png', 'wb').write(data.decode('base64')) binary_img_data = img_data.decode('base64') file_like = BytesIO(binary_img_data) img = Image.open(file_like) #img.save('test.png') return imgdef parse_form(html): """extract all input properties from the form """ tree = lxml.html.fromstring(html) data = {} for e in tree.cssselect('form input'): if e.get('name'): data[e.get('name')] = e.get('value') return datadef register(first_name, last_name, email, password, captcha_fn): cj = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) html = opener.open(REGISTER_URL).read() form = parse_form(html) form['first_name'] = first_name form['last_name'] = last_name form['email'] = email form['password'] = form['password_two'] = password img = extract_image(html)# captcha = captcha_fn(img)# form['recaptcha_response_field'] = captcha encoded_data = urllib.urlencode(form) request = urllib2.Request(REGISTER_URL, encoded_data) response = opener.open(request) success = '/user/register' not in response.geturl() #success = '/places/default/user/register' not in response.geturl() return success

2.光學字符識別驗證碼

光學字符識別(Optical Character Recognition, OCR)用于圖像中抽取文本。本節中,我們將使用開源的Tesseract OCR引擎,該引擎最初由惠普公司開發的,目前由Google主導。Tesseract的安裝說明可以從http://code.google.com/p/tesseract-ocr/wiki/ReadMe 獲取。然后可以使用pip安裝其Python封裝版本pytesseractpip install pytesseract。 下面我們用光學字符識別圖像驗證碼:

>>> import pytesseract>>> import form>>> img=form.extract_image(html)>>> pytesseract.image_to_string(img)''>>>

如果直接把驗證碼原始圖像傳給pytesseract,一般不能解析出來。這是因為Tesseract是抽取更加典型的文本,比如背景統一的書頁。下面我們進行去除背景噪音,只保留文本部分。驗證碼文本一般都是黑色的,背景則會更加明亮,所以我們可以通過檢查是否為黑色將文本分離出來,該處理過程又被稱為閾值化

>>> >>> img.save('2captcha_1original.png')>>> gray=img.convert('L')>>> gray.save('2captcha_2gray.png')>>> bw=gray.point(lambda x:0 if x<1 else 255,'1')>>> bw.save('2captcha_3thresholded.png')>>>

這里只有閾值小于1的像素(全黑)都會保留下來,分別得到三張圖像:原始驗證碼圖像、轉換后的灰度圖和閾值化處理后的黑白圖像。最后我們將閾值化處理后黑白圖像再進行Tesseract處理,驗證碼中的文字已經被成功抽取出來了。

>>> pytesseract.image_to_string(bw)'language'>>> >>> import Image,pytesseract>>> img=Image.open('2captcha_3thresholded.png')>>> pytesseract.image_to_string(img)'language'>>>

我們通過示例樣本測試,100張驗證碼能正確識別出90張。

>>> import ocr>>> ocr.test_samples()Accuracy: 90/100>>>

下面是注冊賬號完整代碼:

# -*- coding: utf-8 -*-import csvimport stringfrom PIL import Imageimport pytesseractfrom form import registerdef main(): print register('Wu1', 'Being1', 'Wu_Being001@QQ.com', 'example', ocr)def ocr(img): # threshold the image to ignore background and keep text gray = img.convert('L') #gray.save('captcha_greyscale.png') bw = gray.point(lambda x: 0 if x < 1 else 255, '1') #bw.save('captcha_threshold.png') word = pytesseract.image_to_string(bw) ascii_word = ''.join(c for c in word if c in string.letters).lower() return ascii_wordif __name__ == '__main__': main()

我們可以進一步改善OCR性能: - 實驗不同閾值 - 腐蝕閾值文本,突出字符形狀 - 調整圖像大小 - 根據驗證碼字體訓練ORC工具 - 限制結果為字典單詞

3.用API處理復雜驗證碼

為了處理更加復雜的圖像,我們將使用驗證處理服務,也叫打碼平臺

3.1 9kw打碼平臺

先到9kw打碼平臺注冊一個個人賬號https://www.9kw.eu/register.html 登錄后,定位到https://www.9kw.eu/usercaptcha.html 手工處理其他用戶驗證碼獲得積分創建API key https://www.9kw.eu/index.cgi?action=userapinew&source=api

3.1.1 提交驗證碼

提交驗證碼參數: - URL: https://www.9kw.eu/index.cgi(POST) - action:POST必須設為:’usercaptchaupload’ - apikey:個人的API key - file-upload-01:需要處理的圖像(文件、url 或字符串) - base64:如果輸入的是Base64編碼,則設為“1” - maxtimeout:等待處理的最長時間(60~3999) - selfsolve:如果自己處理該驗證碼,則設為“1”

返回值: - 該驗證碼的ID

API_URL: https://www.9kw.eu/index.cgi def send(self, img_data): """Send CAPTCHA for solving """ print 'Submitting CAPTCHA' data = { 'action': 'usercaptchaupload', 'apikey': self.api_key, 'file-upload-01': img_data.encode('base64'), 'base64': '1', 'selfsolve': '1', 'maxtimeout': str(self.timeout) } encoded_data = urllib.urlencode(data) request = urllib2.Request(API_URL, encoded_data) response = urllib2.urlopen(request) return response.read()

API文檔地址https://www.9kw.eu/api.html#apisubmit-tab

3.1.2 請求已提交驗證碼結果

請求結果的參數: - URL: https://www.9kw.eu/index.cgi(GET) - action:GET必須設為:’usercaptchacorrectdata’ - apikey:個人的API key - id:要檢查的驗證碼ID - info:若設為“1”,沒有得到結果時返回“NO DATA”(默認返回空)

返回值: - 要處理的驗證碼文本或錯誤碼

錯誤碼: - 0001:API key不存在 - 0002:沒有找到API key - 0003:沒有找到激活的API key …… - 0031:賬號被系統禁用24小時 - 0032:賬號沒有足夠的權限 - 0033:需要升級插件

def get(self, captcha_id): """Get result of solved CAPTCHA """ data = { 'action': 'usercaptchacorrectdata', 'id': captcha_id, 'apikey': self.api_key, 'info': '1' } encoded_data = urllib.urlencode(data) response = urllib2.urlopen(self.url + '?' + encoded_data) return response.read()

3.1.2與注冊功能集成

# -*- coding: utf-8 -*-import sysimport reimport urllib2import urllibimport timefrom io import BytesIOfrom PIL import Imagefrom form import registerdef main(api_key, filename): captcha = CaptchaAPI(api_key) print register('wu101', 'being101', 'wu_being101@qq.com', 'password.com', captcha.solve)class CaptchaError(Exception): passclass CaptchaAPI: def __init__(self, api_key, timeout=60): self.api_key = api_key self.timeout = timeout self.url = 'https://www.9kw.eu/index.cgi' def solve(self, img): """Submit CAPTCHA and return result when ready """ img_buffer = BytesIO() img.save(img_buffer, format="PNG") img_data = img_buffer.getvalue() captcha_id = self.send(img_data) start_time = time.time() while time.time() < start_time + self.timeout: try: text = self.get(captcha_id) except CaptchaError: pass # CAPTCHA still not ready else: if text != 'NO DATA': if text == 'ERROR NO USER': raise CaptchaError('Error: no user available to solve CAPTCHA') else: print 'CAPTCHA solved!' return text print 'Waiting for CAPTCHA ...' raise CaptchaError('Error: API timeout') def send(self, img_data): """Send CAPTCHA for solving """ print 'Submitting CAPTCHA' data = { 'action': 'usercaptchaupload', 'apikey': self.api_key, 'file-upload-01': img_data.encode('base64'), 'base64': '1', 'selfsolve': '1', 'maxtimeout': str(self.timeout) } encoded_data = urllib.urlencode(data) request = urllib2.Request(self.url, encoded_data) response = urllib2.urlopen(request) result = response.read() self.check(result) return result def get(self, captcha_id): """Get result of solved CAPTCHA """ data = { 'action': 'usercaptchacorrectdata', 'id': captcha_id, 'apikey': self.api_key, 'info': '1' } encoded_data = urllib.urlencode(data) response = urllib2.urlopen(self.url + '?' + encoded_data) result = response.read() self.check(result) return result def check(self, result): """Check result of API and raise error if error code detected """ if re.match('00/d/d /w+', result): raise CaptchaError('API error: ' + result)if __name__ == '__main__': try: api_key = sys.argv[1] filename = sys.argv[2] except IndexError: print 'Usage: %s <API key> <Image filename>' % sys.argv[0] else: main(api_key, filename)

Wu_Being 博客聲明:本人博客歡迎轉載,請標明博客原文和原鏈接!謝謝! 【Python爬蟲系列】《【Python爬蟲7】驗證碼處理》http://blog.csdn.net/u014134180/article/details/55508229 Python爬蟲系列的GitHub代碼文件:https://github.com/1040003585/WebScrapingWithPython


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 石景山区| 连山| 牙克石市| 梁山县| 肥西县| 宁蒗| 石狮市| 静乐县| 黄骅市| 仙居县| 灵丘县| 灌南县| 邹城市| 大竹县| 靖宇县| 滦南县| 兴国县| 宝应县| 平利县| 郴州市| 鄂州市| 伊金霍洛旗| 铜陵市| 洪江市| 辰溪县| 饶平县| 新巴尔虎右旗| 盐山县| 当雄县| 米脂县| 墨玉县| 正蓝旗| 枣强县| 禄劝| 三原县| 沅江市| 宁强县| 正定县| 嘉善县| 庆元县| 灌南县|