实战项目,干货满满
import requests
from hashlib import md5
#实现规避检测
from selenium.webdriver import FirefoxOptions
from selenium.webdriver import ChromeOptions
#规避检测,'excludeSwitches', ['enable-automation']开发者模式
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
#超级鹰打码平台
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
#使用selenium打开登录页面
from selenium import webdriver
import time
from PIL import Image
from selenium.webdriver import ActionChains
from selenium.webdriver.support import expected_conditions as EC, wait
#创建对象
#executable_path=path:下载好的驱动程序的路径
bro = webdriver.Chrome(executable_path='chromedriver.exe',options=option)
#12306的登录网址
bro.get('https://kyfw.12306.cn/otn/resources/login.html')
bro.execute_script('Object.defineProperties(navigator, {webdriver:{get:()=>undefined}})')
#窗口最大化
bro.maximize_window()
#点击账号登录
bro.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click()
time.sleep(1)
while True:
try:
#save_screenshot就是将当前页面进行截图且保存
bro.save_screenshot('aa.png')
#确定验证码图片对应的左上角和右下角的坐标(裁剪的区域就确定)
code_img_ele = bro.find_element_by_xpath('//*[@id="J-loginImg"]')
location = code_img_ele.location # 验证码图片左上角的坐标 x,y
#print('location:',location)
size = code_img_ele.size #验证码标签对应的长和宽
#print('size:',size)
#左上角和右下角坐标
rangle = (
int(location['x']), int(location['y']), int(location['x'] + size['width']), int(location['y'] + size['height']))
#至此验证码图片区域就确定下来了
i = Image.open('./aa.png')
code_img_name = './code.png'
#crop根据指定区域进行图片裁剪
frame = i.crop(rangle)
frame.save(code_img_name)
#将验证码图片提交给超级鹰进行识别
chaojiying = Chaojiying_Client('超级鹰帐号', '超级鹰密码', '超级鹰软件iD') #用户账号>>密码>>软件ID
im = open('code.png', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
id=chaojiying.PostPic(im, 9004)['pic_id'] #截取的验证码照片以及验证码的类别代号
result = chaojiying.PostPic(im, 9004)['pic_str'] #识别结果
all_list = [] #要存储即将被点击的点的坐标 [[x1,y1],[x2,y2]]
#识别错误后,返回题分
chaojiying.ReportError(id)
if '|' in result:
list_1 = result.split('|')
print(list_1)
count_1 = len(list_1)
for i in range(count_1):
xy_list = []
x = int(list_1[i].split(',')[0])
y = int(list_1[i].split(',')[1])
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
else:
x = int(result.split(',')[0])
y = int(result.split(',')[1])
xy_list = []
xy_list.append(x)
xy_list.append(y)
all_list.append(xy_list)
#遍历列表,使用动作链对每一个列表元素对应的x,y指定的位置进行点击操作
for l in all_list:
x = l[0]
y = l[1]
ActionChains(bro).move_to_element_with_offset(code_img_ele, x, y).click().perform()
time.sleep(0.5)
#输入账号和密码
put1=bro.find_element_by_id('J-userName')
#当验证码识别错误后,需要清空账号重新输入
put1.clear()
put1.send_keys('帐号') #你的账号
time.sleep(1)
put2=bro.find_element_by_id('J-password')
put2.clear()
put2.send_keys('密码') #你的密码
time.sleep(1)
bro.find_element_by_id('J-login').click()
#处理提示框
time.sleep(3)
span=bro.find_element_by_xpath('//*[@id="nc_1_n1z"]')
action = ActionChains(bro)
#点击长按指定的标签
action.click_and_hold(span).perform()
action.drag_and_drop_by_offset(span,400,0).perform()
time.sleep(8)
while True:
try:
info=bro.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span').text
print(info)
if info=='哎呀,出错了,点击刷新再来一次':
bro.find_element_by_xpath('//*[@id="J-slide-passcode"]/div/span/a').click()
time.sleep(0.2)
span = bro.find_element_by_xpath('//*[@id="nc_1_n1z"]')
action = ActionChains(bro)
# 点击长按指定的标签
action.click_and_hold(span).perform()
action.drag_and_drop_by_offset(span, 400, 0).perform()
time.sleep(7)
except:
print('ok!')
break
#释放动作链
action.release()
break
except:
time.sleep(3)
#关闭浏览器
bro.quit()
options配置属性:
- options.add_argument(‘headless’) # 无头模式
- options.add_argument(‘window-size={}x{}’.format(width, height)) # 直接配置大小和set_window_size一样
- options.add_argument(‘disable-gpu’) # 禁用GPU加速
- options.add_argument(‘proxy-server={}’.format(self.proxy_server)) # 配置代理
- options.add_argument(’–no-sandbox’) # 沙盒模式运行
- options.add_argument(’–disable-setuid-sandbox’) # 禁用沙盒
- options.add_argument(’–disable-dev-shm-usage’) # 大量渲染时候写入/tmp而非/dev/shm
- options.add_argument(’–user-data-dir={profile_path}’.format(profile_path)) # 用户数据存入指定文件
- options.add_argument('no-default-browser-check) # 不做浏览器默认检查
- options.add_argument("–disable-popup-blocking") # 允许弹窗
- options.add_argument("–disable-extensions") # 禁用扩展
- options.add_argument("–ignore-certificate-errors") # 忽略不信任证书
- options.add_argument("–no-first-run") # 初始化时为空白页面
- options.add_argument(’–start-maximized’) # 最大化启动
- options.add_argument(’–disable-notifications’) # 禁用通知警告
- options.add_argument(’–enable-automation’) # 通知(通知用户其浏览器正由自动化测试控制)
- options.add_argument(’–disable-xss-auditor’) # 禁止xss防护
- options.add_argument(’–disable-web-security’) # 关闭安全策略
- options.add_argument(’–allow-running-insecure-content’) # 允许运行不安全的内容
- options.add_argument(’–disable-webgl’) # 禁用webgl
- options.add_argument(’–homedir={}’) # 指定主目录存放位置
- options.add_argument(’–disk-cache-dir={临时文件目录}’) # 指定临时文件目录
- options.add_argument(‘disable-cache’) # 禁用缓存
- options.add_argument(‘excludeSwitches’, [‘enable-automation’]) # 开发者模式