本篇博客主要是记录一下使用Python的selenium库的过程,以及识别验证码时遇到的小坑。我先来列举几个可供学习的文档,主要分为两类。
一类是学习selenium自动化访问网站:
Selenium with Python
Selenium Python 文档
Selenium Documentation
一类是识别验证码相关:
tesseract
目标站点是YunFile网盘,我想要自动普通下载给出的某个文件,比如这个url:http://tadown.com/fs/1q8q3_d3a51081cBEFF986/
代码如下:
from PIL import Image, ImageEnhance
import pytesseract
import re
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
CHROME_DRIVER_PATH = './chromedriver'
# 获取验证码
def get_code_from_image(code_image_path):
code_img = Image.open(code_image_path)
# numbers为配置文件,内容为:tessedit_char_whitelist 0123456789
code_text = pytesseract.image_to_string(code_img, config='--psm 7 numbers').strip()
# 去掉非数字字符
code_text = re.sub("\D", "", code_text)
return code_text
def main():
# 配置Chrome浏览器,profile.default_content_settings.popups=0表示禁止弹出窗口
chrome_options = webdriver.ChromeOptions()
preferences = {'profile.default_content_settings.popups': 0, }
chrome_options.add_experimental_option('prefs', preferences)
driver = webdriver.Chrome(executable_path=CHROME_DRIVER_PATH, options=chrome_options)
driver.maximize_window()
driver.implicitly_wait(10)
driver.set_page_load_timeout(10)
driver.set_script_timeout(10)
url = 'http://tadown.com/fs/1q8q3_d3a51081cBEFF986/'
try:
driver.get(url)
useless_element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, 'slow_button'))
)
download_element = driver.find_elements_by_class_name('slow_button')[1]
download_element.click()
dialog_close_element = driver.find_elements_by_class_name('ui_dialog_close')[1]
dialog_close_element.click()
driver.save_screenshot('screenshot1.png')
# 获取验证码图片,处理并保存
code_image_element = driver.find_element_by_id('cvimg2')
# 获取验证码图片的大小
imgSize = code_image_element.size
# 获取验证码元素坐标
imgLocation = code_image_element.location
# 计算验证码整体坐标
rangle_normal = (int(imgLocation['x']), int(imgLocation['y']),
int(imgLocation['x'] + imgSize['width']), int(imgLocation['y'] + imgSize['height']))
# 实验发现,截图得到的位置是原始位置的两倍,原因未知!!!
rangle = (rangle_normal[0] * 2, rangle_normal[1] * 2, rangle_normal[2] * 2, rangle_normal[3] * 2)
code_image = Image.open('screenshot1.png').crop(rangle)
code_image.save('code.png')
# 转化为灰度图
code_grey_image = code_image.convert('L')
code_grey_image.save('code_grey.png')
# 增加对比度
code_sharp_image = ImageEnhance.Contrast(code_image).enhance(2.0)
code_sharp_image.save('code_sharp.png')
# 转化为二值化图片
code_bin_image = code_image.convert('1')
code_bin_image.save('code_bin.png')
# 得到验证码 code,必须是4位长度
code = get_code_from_image('code.png')
print('code:', code)
if len(code) != 4:
code = get_code_from_image('code_grey.png')
print('code_grey:', code)
if len(code) != 4:
code = get_code_from_image('code_sharp.png')
print('code_sharp:', code)
if len(code) != 4:
code = get_code_from_image('code_bin.png')
print('code_bin:', code)
if len(code) != 4:
print('Can not identify the verification code correctly!!!')
return
code_input_element = driver.find_element_by_id('vcode')
code_input_element.clear()
code_input_element.send_keys(code)
code_input_element.send_keys(Keys.RETURN)
time.sleep(32)
driver.save_screenshot('screenshot2.png')
import pdb
pdb.set_trace()
finally:
driver.quit()
if __name__ == '__main__':
main()
其中的代码大多是从网上找的,只有一个地方和网上不同,我认为这是个小坑,那就是通过网站验证码元素而获取的验证码元素坐标与截图中验证码的坐标位置不同,还好让我发现是二倍的关系,原因的话还不清楚。