zoukankan      html  css  js  c++  java
  • 重新写了一个东南大学体育场馆的定时预约脚本,使用selenium和chromedriver实现,tesseract识别验证码

    上次写的半成品用的是urllib库直接提交post表单,但是现在不可用了,主要是post请求的字段里,新添了几个不知道的值,而且密码采用的加密是ase128,我是懒的去实现。
    正好试一下selenium,selenium是一个很好的用于自动化测试的模块,可以直接调动浏览器,模拟人的输入点击等操作,而且非常简单易用,但是效率相对而言就低一些,因为很多操作要等页面元素加载出来才可以找到。

    这次不仅写了脚本,还搭建了一个网站,接受预定,并且写入数据库,每天早上08:01执行预约脚本,有兴趣的或者需要的同学可以看这里,http://116.62.5.101:8000,
    后面会再写一篇文章,介绍如何在服务器上部署基于flask网站,数据库,selenium、tesseract4.0、无界面的chrome浏览器和chromdriver。



    selenium最核心的使用方法就是使用选择器找到页面的相应的元素作为对象,例如:
    bro是一个selenium中webdriver的一个浏览器对象,可以使用find_element_by的方法,通过name,id,class找到元素,
    如果这些都没有的元素,可以使用xpath,xpath有兴趣的小伙伴可以去详细了解一下,不过最简单的方法就是F12打开开发者模式之后,右键响应的元素就可以copy它的Xpath。

    tesseract 是一个识别引擎,用于识别验证码





    import pymongo
    import schedule
    import time
    import pytesseract
    from PIL import Image
    from multiprocessing import Pool
    from bson import ObjectId
    from selenium import webdriver
    import datetime
    import random
    import os


    def addmates(matesid,framenum,bro):

    button_addmates = bro.find_element_by_id("handle-add")
    button_addmates.click()
    bro.switch_to.frame("xubox_iframe"+str(framenum))
    input_matesid = bro.find_element_by_id("cardNo")
    input_matesid.send_keys(matesid)
    button_findmate = bro.find_element_by_class_name("search-id")
    button_findmate.click()
    input_existmates = bro.find_elements_by_class_name("user")
    oldcontacts = []
    for input_existmate in input_existmates:
    # print(input_existmate.get_attribute("textContent"))
    oldcontacts.append(input_existmate.get_attribute("textContent").strip())

    time.sleep(1)
    # print(bro.page_source)
    input_newcontact = bro.find_element_by_id("contact")
    # print(input_newcontact.get_attribute("textContent"))
    newcontact = input_newcontact.get_attribute("textContent")

    if newcontact not in oldcontacts:
    button_addtocontacts = bro.find_element_by_class_name("add-user")
    button_addtocontacts.click()
    time.sleep(1)
    else:
    for input_existmate in input_existmates:
    if input_existmate.get_attribute("textContent").strip() == newcontact:
    checkbox = input_existmate.find_element_by_name("user")
    checkbox.click()
    time.sleep(1)
    button_submitaddmates = bro.find_element_by_class_name("del-all-users")
    button_submitaddmates.click()
    break


    # ssl._create_default_https_context = ssl._create_unverified_context
    def main(reserverdic,orderid):

    #隐藏浏览器界面
    option = webdriver.ChromeOptions()
    option.add_argument('headless')
    option.add_argument('--no-sandbox')
    bro = webdriver.Chrome(options=option)
    # bro = webdriver.Chrome()
    print("Chrome 已启动")
    url = 'https://newids.seu.edu.cn/authserver/login?goto=http://my.seu.edu.cn/index.portal'


    bro.get(url)
    # print(bro.page_source)
    #bro.save_screenshot("ddd.png")
    #print("saved")
    # 登录预约系统
    id=reserverdic["idpwd"]["ssid"]
    pwd=reserverdic["idpwd"]["pwd"]
    time.sleep(3)
    input_username = bro.find_element_by_id("username")
    input_password = bro.find_element_by_id("password")
    input_username.send_keys(id)
    input_password.send_keys(pwd)
    # print(input_username)
    # print(input_password)

    # 多个class 要用下面的形式 不能直接find_element_by_class
    botton_login = bro.find_element_by_css_selector("[class='auth_login_btn primary full_width']")
    botton_login.click()

    # url3="http://yuyue.seu.edu.cn/eduplus/order/initOrderIndex.do?sclId=1"
    # bro.get(url3)
    #打开预约界面
    info = reserverdic["info"]
    # info = {
    # 'dayInfo': "2018-11-23",
    # 'itemId': 7,
    # 'time': "12:00-13:00"
    # }
    # infourl = urllib.parse.urlencode(info)
    """
    'itemId':7, 九龙湖乒乓,1-3人
    'itemId':8, 九龙湖篮球,全场9-14,半场5-8人
    'itemId':9, 九龙湖排球,4-15人
    'itemId':10, 九龙湖羽毛球,1-5人
    'itemId':11, 九龙湖舞蹈,非必选
    'itemId':12, 九龙湖健身,非必选
    'itemId':13, 九龙湖武术,非必选
    'itemId':14, 九龙湖跆拳道,非必选
    'itemId':15, 四牌楼羽毛球,1-3人
    'itemId':16, 四牌楼乒乓,1-3人
    'itemId':17, 四牌楼网球,1-3人
    """

    url2 = "http://yuyue.seu.edu.cn/eduplus/order/initEditOrder.do?sclId=1&dayInfo="+info['dayInfo']+"&itemId="+info['itemId']+"&time="+info["time"]
    # print(url2)
    # bro.execute_script("window.open()")
    # bro.switch_to.window(bro.window_handles[1])
    bro.get(url2)

    #处理篮球半场全场
    basketball=reserverdic["phonemate"]["halffull"]
    if basketball == 2:
    buttonhalffull = bro.find_elements_by_name("orderVO.useMode")
    buttonhalffull[1].click()
    #添加电话
    phonenumber = reserverdic["phonemate"]["phone"]
    input_phone = bro.find_element_by_id("phone")
    input_phone.clear()
    input_phone.send_keys(phonenumber)

    #添加好友
    framenum=0
    for eachmate in reserverdic["phonemate"]["mateid"]:
    framenum+=1
    addmates(eachmate,framenum,bro)
    time.sleep(1)



    #处理验证码
    screenshot = str(random.randint(1,100000))+'screenshot.png'
    validcodeshot = str(random.randint(1,100000))+'validateimage.png'
    bro.get_screenshot_as_file(screenshot)
    img = bro.find_element_by_xpath('//*[@id="fm"]/table/tbody/tr[6]/td[2]/img')
    left = int(img.location['x'])
    top = int(img.location['y'])
    right = int(img.location['x'] + img.size['width'])
    bottom = int(img.location['y'] + img.size['height'])

    # 通过Image处理图像
    im = Image.open(screenshot)
    im = im.crop((left, top, right, bottom))
    im.save(validcodeshot)

    img = Image.open(validcodeshot)
    validcode = pytesseract.image_to_string(img)
    # print(validcode)

    input_validcode = bro.find_element_by_id("validateCode")
    input_validcode.send_keys(validcode)
    button_reserve = bro.find_element_by_id("do-submit")
    button_reserve.click()

    os.remove(screenshot)
    os.remove(validcodeshot)
    time.sleep(1)



    try:
    alertcontent=bro.find_element_by_css_selector("[class='xubox_msg xubox_text']")
    if alertcontent.get_attribute("textContent"):
    updatestatus(orderid, alertcontent.get_attribute("textContent")+",预约失败")
    print(alertcontent.get_attribute("textContent"), "预约失败")
    bro.quit()
    return 0
    except Exception:
    bro.quit()
    updatestatus(orderid,"预约成功")
    print("预约成功")
    return 1


    def mmain():
    # 测试用例
    # reserverdic1 = {
    # "idpwd": {
    # 'ssid': 220187988,
    # 'pwd': "mima"
    # },
    # "info": {
    # 'dayInfo': "2019-09-02",
    # 'itemId': "7",
    # 'time': '12:00-13:00'
    # },
    # "phonemate": {
    # "phone": 1885187965558,
    # "mateid": [220184346], # list 所有好友id
    # "halffull": 1 # 1表示全场,2表示半场,非蓝球默认位1,或者空
    # }
    # }
    # reserverdic2 = {
    # "idpwd": {
    # 'ssid': 220175358,
    # 'pwd': "mima"
    # },
    # "info": {
    # 'dayInfo': "2019-09-08",
    # 'itemId': "7",
    # 'time': '17:00-18:00'
    # },
    # "phonemate": {
    # "phone": 18851879658,
    # "mateid": [220184348], # list 所有好友id
    # "halffull": 1 # 1表示全场,2表示半场,非蓝球默认位1,或者空
    # }
    # }
    # groups=[reserverdic1,reserverdic2]


    orderlist = getorderlist()
    if not orderlist:
    print(str(datetime.date.today()),"没有订单")

    pool = Pool()
    pool.map(doorder,orderlist)

    # pool.map(main, groups)


    def doorder(order):
    try:
    print("process order", order)
    main(order[0], order[1])
    except Exception:
    newstutas = "预约失败,检查提交信息是否出错"
    updatestatus(order[1], newstutas)
    print(newstutas)


    def getorderlist():


    today=datetime.date.today()
    myclient = pymongo.MongoClient("mongodb://localhost:27017/")
    mydb = myclient["order"]
    mycol = mydb["order"]
    findresult = mycol.find({'date': str(today)}, {"reservedic": 1,"_id":1})
    orderlist=[]
    for x in findresult:
    orderlist.append([x["reservedic"],x["_id"]])

    return orderlist


    def updatestatus(orderid, newinfo):
    myclient = pymongo.MongoClient("mongodb://localhost:27017/")
    mydb = myclient["order"]
    mycol = mydb["order"]
    mycol.update_one({ "_id" : ObjectId(orderid)},{ "$set": { "status": newinfo } })


    if __name__ == '__main__':
    # mmain()

    mmain()


    # schedule.every().day.at('08:00').do(mmain)
    # while True:
    # schedule.run_pending()
  • 相关阅读:
    Android数据适配器(Adapter)优化:高效ViewHolder
    touch-css-margintop问题
    抽奖
    scroll03-节日两侧的渲染
    scroll02-滚动时显示当前主题菜单状态
    浏览器背景色半透明效果。
    scroll01-滚动到一定高度时,显示导航栏
    layout01-在布局ul时,给li设置margin-right的时候,每行的最后一个li有margin-right 导致ul 看上去不居中的问题
    placehoder兼容
    day03
  • 原文地址:https://www.cnblogs.com/CooperXia-847550730/p/11479752.html
Copyright © 2011-2022 走看看