Пример #1
0
class Ticket(object):
    def __init__(self, config_file):
        ## config parser setting
        self.config_file = config_file
        self.settings = configparser.ConfigParser()
        self.settings._interpolation = configparser.ExtendedInterpolation()
        self.settings.read(self.config_file,'utf-8')
        ## environment setting
        self.brower='chrome'
        self.b = Browser(driver_name=self.brower) 
        self.station={}
        self.url = "https://kyfw.12306.cn/otn/leftTicket/init"
        # 席别类型(对应列标号)
        self.ticket_index = [
                            '',
                            u'商务座',
                            u'特等座',
                            u'一等座', 
                            u'二等座',
                            u'高级软卧',
                            u'软卧',
                            u'硬卧',
                            u'软座',
                            u'硬座',
                            u'无座'
                            ]
        self.username = ''
        self.password = ''
        self.date_format='%Y-%m-%d'
        self.tolerance = -1
        self.blacklist = {}
        self.date = []
        self.isStudent = False
        self.success = 0
        self.find_ticket = 0
        self.config_parser()
        self.playmusic = False
        self.count = 0

    def ConfigSectionMap(self,section):
            dict1 = {}
            options = self.settings.options(section)
            for option in options:
                try:
                    dict1[option] = self.settings.get(section, option)
                    if dict1[option] == -1:
                        DebugPrint("skip: %s" % option)
                except:
                        print("exception on %s!" % option)
                        dict1[option] = None
            return dict1
    def daterange(self, start_date, end_date):
        for n in range(int ((end_date - start_date).days) + 1):
            yield start_date + timedelta(n) 

    def config_parser(self):
        if self.retrieve_station_dict() == -1:
            sys.exit()
        if self.retrieve_book_options() == -1:
            sys.exit()
        
    def retrieve_station_dict(self):
        dict_helper=self.ConfigSectionMap('STATIONCOOKIE')
        for name, value in dict_helper.iteritems():
            self.station[name]=value

    def retrieve_book_options(self):
        login_info=self.ConfigSectionMap('GLOBAL')
        self.username = login_info['username'].strip() 
        self.password = login_info['password'].strip()
        self.brower = login_info['browser']
        book_settings = self.ConfigSectionMap('TICKET')
        self.fromStation = [ station.strip() for station in book_settings['from_station'].split(',')]
        self.toStation = [ station.strip() for station in book_settings['to_station'].split(',')]
        trains = [ train.strip() for train in book_settings['trains'].split(',')]
        if len(trains) == 1 and trains[0] == '':
            self.trains = []
        else:
            self.trains =  trains
        self.ticket_type =[ _type.strip() for _type in book_settings['ticket_type'].split(',')]
        rangeQuery = book_settings['range_query'].strip()
        if rangeQuery == 'Y':
            date = [ d.strip() for d in book_settings['date'].split(',')]
            if len(date) < 2:
                print "未设置正确的起至时间"
                return -1
            else: 
                start_date = datetime.strptime(date[0],self.date_format) 
                end_date = datetime.strptime(date[1],self.date_format) 
                if end_date < start_date:
                    print "查询截止日期不可大于开始日期!"
                    return -1
                for single_date in self.daterange(start_date, end_date): 
                    self.date.append(single_date.strftime(self.date_format))
        else:
            self.date = [ d.strip() for d in book_settings['date'].split(',')]
        if book_settings['student'].strip() == 'Y':
            self.isStudent = True
        self.tolerance = int(book_settings['tolerance'])
        self.people = [ people.strip() for people in book_settings['people'].split(',') ]
        if book_settings['alarm'].strip() == 'Y':
            self.playmusic = True

    def login(self):
        self.b.visit(self.url)
        self.b.find_by_text(u"登录").click()
        self.b.fill("loginUserDTO.user_name",self.username)
        self.b.fill("userDTO.password",self.password)
        pdb.set_trace()
    
    def page_has_loaded(self):
        page_state = self.b.evaluate_script("document.readyState")
        return page_state == 'complete'

    def switch_to_order_page(self):
        order = []
        while len(order) == 0:
            order = self.b.find_by_text(u"车票预订")
        order[0].click()

    def checkTicket(self, date, fromStation, toStation):
        print 'date: %s, from %s, to %s'%(date, fromStation, toStation)
        self.b.cookies.add({"_jc_save_fromDate":date})
        self.b.cookies.add({"_jc_save_fromStation":self.station[fromStation]})
        self.b.cookies.add({"_jc_save_toStation":self.station[toStation]})
        self.b.cookies.all()
        self.b.reload()
        if self.isStudent:
            self.b.find_by_text(u'学生').click()
        self.b.find_by_text(u"查询").click()
        all_trains = []
        while self.page_has_loaded() == False:
            continue
        while len(all_trains) == 0:
            all_trains = self.b.find_by_id('queryLeftTable').find_by_tag('tr')
        for k, train in enumerate(all_trains):
            tds = train.find_by_tag('td')
            if tds and len(tds) >= 10:
                has_ticket= tds.last.find_by_tag('a')
                if len(has_ticket) != 0:
                    if k + 1 < len(all_trains):
                        this_train = all_trains[k+1]['datatran']
                        if len(self.trains) != 0 and this_train not in self.trains:
                            continue
                        if self.tolerance != -1 and this_train in self.blacklist and self.blacklist[this_train] >= self.tolerance:
                            print u"%s 失败 %d 次, 跳过"%(this_train, self.blacklist[this_train])
                            continue
                    for cat in self.ticket_type:
                        if cat in self.ticket_index:
                            i = self.ticket_index.index(cat)
                        else:
                            print '无效的席别信息'
                            return 0, ''
                        if tds[i].text != u'无' and tds[i].text != '--':
                            if tds[i].text != u'有':
                                print u'%s 的 %s 有余票 %s 张!'%(this_train, cat ,tds[i].text)
                            else:
                                print u'%s 的 %s 有余票若干张!'%(this_train, cat)
                            self.find_ticket = 1
                            tds.last.click()
                            break
            if self.find_ticket:
                break
        return this_train

    def book(self):
        while self.page_has_loaded() == False:
            continue
        if len(self.people) == 0:
            print '没有选择乘车人!'
            return 1
        more = []
        while len(more) == 0:
            more = self.b.find_by_text(u"更多")
        more[0].click()
        person = []
        people = self.people
        while len(person) == 0:
            person=self.b.find_by_xpath('//ul[@id="normal_passenger_id"]/li/label[contains(text(),"%s")]'%people[0])
        for p in people:
            self.b.find_by_xpath('//ul[@id="normal_passenger_id"]/li/label[contains(text(),"%s")]'%p).click()
            if self.b.find_by_xpath('//div[@id="dialog_xsertcj"]').visible:
                self.b.find_by_xpath('//div[@id="dialog_xsertcj"]/div/div/div/a[text()="确认"]').click()
            return 1

    def ring(self):
        pygame.mixer.pre_init(64000, -16, 2, 4096)
        pygame.init()
        pygame.display.init()
        screen=pygame.display.set_mode([300,300])
        #pygame.display.flip()
        pygame.time.delay(1000)#等待1秒让mixer完成初始化
        tracker=pygame.mixer.music.load("media/sound.ogg")
        #track = pygame.mixer.music.load("sound.ogg")
        pygame.mixer.music.play()
        # while pygame.mixer.music.get_busy():
        #pygame.time.Clock().tick(10)
        running = True
        img=pygame.image.load("media/img.jpg")
        while running:
            screen.blit(img,(0,0))
            pygame.display.flip()
            for event in pygame.event.get():
                if event.type==pygame.QUIT:
                    running = False
        pygame.quit ()
        return 1
    def executor(self):
        self.login()
        self.switch_to_order_page()
        while self.success == 0:
            self.find_ticket = 0
            while self.find_ticket == 0:
                for date in self.date:
                    try:
                        self.count += 1
                        print "Try %d times" % self.count
                        for fromStation in self.fromStation:
                            for toStation in self.toStation:
                                this_train = self.checkTicket(date, fromStation, toStation)
                                if self.find_ticket:
                                    break
                            if self.find_ticket:
                                break
                        if self.find_ticket:
                            break
                    except KeyboardInterrupt:
                        self.b.find_by_text(u'退出').click()
                        sys.exit()
                    except:
                        continue
            # book ticket for target people
            self.find_ticket = 0
            while self.find_ticket == 0:
                try:
                    self.find_ticket = self.book() 
                except KeyboardInterrupt:
                    self.b.find_by_text(u'退出').click()
                    sys.exit()
                except:
                    continue
            if self.playmusic:
                self.ring()
            print "订票成功了吗?(Y/N)"
            input_var = ''
            while input_var == '':
                input_var= sys.stdin.read(1)
                if input_var == 'Y' or input_var == 'y':
                    self.success = 1
                elif input_var == 'N' or input_var == 'n':
                    if this_train in self.blacklist:
                        self.blacklist[this_train] += 1
                    else:
                        self.blacklist[this_train] = 1
                    print u"%s 失败 %d 次"%(this_train, self.blacklist[this_train])
                    self.b.back()
                    self.b.reload()
                else:
                    input_var = ''
                    continue
        self.b.find_by_text(u'退出').click()
Пример #2
0
class GetInfo():
    conn = ''
    browser = ''

    def __init__(self, browser, conn=None, to_sql=None):

        # 数据库存储初始化 表名称、登陆用户名
        self.exportSql = to_sql

        if browser:
            self.browser = browser
            self.conn = conn
        else:
            try:
                self.browser = Browser("chrome", headless=False)
                self.browser.driver.set_window_size(1600, 1000)
            except Exception as e:
                self.browser = None

    # 登陆
    def login(self, info):
        # 账号,密码,
        account = info.get('account')
        password = info.get('password')

        if self.browser.url == 'https://17dz.com/manage/index.html':
            if account == self.loginName():
                return '登陆成功'

        self.browser.visit('https://17dz.com/home/login.html')

        # 校验是否为空
        if not all([account, password]):
            return jsonify(errmsg='参数不全')

        with self.browser.get_iframe('loginIframe') as iframe:
            iframe.find_by_css('input[id="id__0"]').first.fill(account)
            iframe.find_by_css('input[id="id__1"]').first.fill(password)
            iframe.find_by_text('登录').first.click()

        time.sleep(2)

        if self.browser.url == 'https://17dz.com/manage/index.html':
            return '登陆成功'
        else:
            return '账号和密码不匹配,请重新输入'

    def loginName(self):
        js = '''getloginName=function(){

                $.ajax({
                    type:'GET',
                    url: 'https://17dz.com/xqy-portal-web/manage/login/getLoginSession?_=1544003601263',
                    contentType:'application/json;charset=utf-8',
                    success: function (result) {
                        if(result.success) {
                            top.Id = result;
                        } else {
                            top.Id = result;
                        }
                    }
                })
            }'''

        self.browser.evaluate_script(js)
        self.browser.evaluate_script('getloginName()')
        i = 1
        loginName = ''
        while True:
            if self.browser.evaluate_script("top.Id"):
                loginName = self.browser.evaluate_script('top.Id').get(
                    'body').get('loginName')
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass
        self.browser.evaluate_script('top.Id=""')

        return loginName

    # 登陆成功后获取账套列表
    def getAllzt(self):

        # self.browser.find_by_text('凭证查看').first.click()
        import datetime
        d = datetime.datetime.now()
        period = datetime.date(d.year - (d.month == 1), d.month - 1 or 12,
                               1).strftime('%Y')

        js = '''getCustomerId=function(){
                var data = {customerName:"", pageNo:1 , pageSize:"500" , searchType:"ALL"}
                $.ajax({
                    type:'POST',
                    url: 'https://17dz.com/xqy-portal-web/manage/customer/queryCustomers',
                    contentType:'application/json;charset=utf-8',
                    data : JSON.stringify(data),
                    success: function (result) {
                        if(result.success) {
                            top.customerId = result;
                        } else {
                            top.customerId = result;
                        }
                    }
                })
            }
            '''

        new_js = '''getCustomerId=function(period){
                    var data = {"pageNo":1,
                                "pageSize":"500",
                                "period":period,
                                "customerNoOrNameLike":"",
                                "accountCloseStatus":"",
                                "sortField":"",
                                "sortDirection":false
                        }
                    $.ajax({
                        type:'POST',
                        url: 'https://17dz.com/xqy-portal-web/manage/finance/queryCustomer',
                        contentType:'application/json;charset=utf-8',
                        data : JSON.stringify(data),
                        success: function (result) {
                            if(result.success) {
                                top.customerId = result;
                            } else {
                                top.customerId = result;
                            }
                        }
                    })
                }'''

        self.browser.evaluate_script(new_js)

        self.browser.evaluate_script('getCustomerId("%s")' % period)
        i = 1
        Id = []
        while True:
            if self.browser.evaluate_script("top.customerId"):
                Id = self.browser.evaluate_script(
                    'top.customerId')['body']['list']
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass
        self.browser.evaluate_script('top.customerId=""')

        customerId = Id[0]['customerId']

        js2 = '''getAllzt=function(customerId){
                var data = {key: "", customerId: customerId}
                $.ajax({
                    type:'POST',
                    url: 'https://17dz.com/xqy-portal-web/manage/workbench/getAccountCustomers',
                    contentType:'application/json;charset=utf-8',
                    data : JSON.stringify(data),
                    success: function (result) {
                        if(result.success) {
                            top.zt_data = result;
                        } else {
                            top.zt_data = result;
                        }
                    }
                })
            }'''

        self.browser.evaluate_script(js2)

        self.browser.evaluate_script('getAllzt("%s")' % customerId)
        i = 1
        ztData = {}
        while True:
            if self.browser.evaluate_script("top.zt_data"):
                ztData = self.browser.evaluate_script('top.zt_data').get(
                    'body', '')
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass
        self.browser.evaluate_script('top.zt_data=""')

        return ztData

    # 切换账套,得到账套的起始和结束日期
    def switchZt(self, params):

        customerId = params['customerId']
        accountSetId = params['accountSetId']
        customerName = params['customerName']
        customerShortName = params['customerShortName']
        # getKhxx('127059881','4320800','上海路卡服装有限公司','上海路卡服装有限公司')
        js = '''getKhxx=function(customerId,accountSetId,customerName,customerShortName){
                $.ajax({
                    type:'PUT',
                    url:'https://17dz.com/xqy-portal-web/finance/account/session/accountSet',
                    data : {customerId:customerId,accountSetId:accountSetId,customerName:customerName,customerShortName:customerShortName,platform:'yqdz'},
                    dataType: 'json',
                    success: function (result) {
                        if(result.success) {
                            top.khxx = result;
                        } else {
                            top.khxx = result;
                        }
                    }
                })
            }'''

        self.browser.evaluate_script(js)

        self.browser.evaluate_script(
            'getKhxx("%s","%s","%s","%s")' %
            (customerId, accountSetId, customerName, customerShortName))
        i = 1
        khxx = {}
        while True:
            if self.browser.evaluate_script("top.khxx"):
                khxx = self.browser.evaluate_script('top.khxx')
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass
        self.browser.evaluate_script('top.khxx=""')
        try:
            startQj = khxx.get('body').get('createPeriod')
            endQj = khxx.get('body').get('lastPeriod')
        except Exception as e:
            return '网络异常,请稍后重试'

        dateStart = datetime.datetime.strptime(startQj, '%Y%m')
        dateEnd = datetime.datetime.strptime(endQj, '%Y%m')

        dates = []
        dates.append(dateStart.strftime('%Y%m'))
        while dateStart <= dateEnd:
            dateStart += datetime.timedelta(weeks=4)
            dates.append(dateStart.strftime('%Y%m'))

        datesList = sorted(list(set(dates)))

        return datesList

    # 凭证
    def voucher(self, QjList, ztID, infoname):

        js = '''get_Voucher=function(kjqj_date){
                var data = {"beginPeriod":kjqj_date,
                            "endPeriod":kjqj_date,
                            "titleCode":"",
                            "beginNumber":"",
                            "endNumber":"",
                            "beginMoney":"",
                            "endMoney":"",
                            "summary":"",
                            "pageSize":"1000",
                            "pageNo":0
                }
                $.ajax({
                    type: "POST",
                    url: 'https://17dz.com/xqy-portal-web/finance/accDocs/list',
                    contentType:'application/json;charset=utf-8',
                    data: JSON.stringify(data),
                    success: function (result) {
                        if(result.success) {
                            top.voucher_data = result;
                        } else {
                            top.voucher_data = result;
                        }
                    }
                })
            }
            '''
        self.browser.evaluate_script(js)
        #创建数据库的infonameID
        infonameID = self.exportSql.init_infoname(infoname).id
        try:
            for Qj in QjList:

                self.browser.evaluate_script('get_Voucher("%s")' % Qj)
                i = 1
                voucher_data = {}
                while True:
                    if self.browser.evaluate_script("top.voucher_data"):
                        data = self.browser.evaluate_script('top.voucher_data')
                        if data:
                            voucher_data = data.get('body')

                        break
                    elif i > 5:
                        break
                    else:
                        time.sleep(0.5)
                        i += 1
                        pass
                self.browser.evaluate_script('top.voucher_data=""')

                voucherString = json.dumps(voucher_data)

                # 保存到数据库
                self.exportSql.insert_new(ztID, Qj, infonameID, voucherString)
        except Exception as e:
            msg = '凭证导出失败:{}'.format(str(e))
        else:
            msg = '凭证导出成功'
        return msg

    # 科目余额表
    def kmsheet(
        self,
        QjList,
        ztID,
        infoname,
    ):

        # 创建数据库的infonameID
        infonameID = self.exportSql.init_infoname(infoname).id
        try:
            for Qj in QjList:
                #获取科目余额
                km_data = self.getKMBody(Qj)
                '''第一版
                # #获取数量金额式
                # slje_data = self.getKMBody(Qj,"B,S")
                # #获取外币金额式
                # wbje_data = self.getKMBody(Qj,"B,W")
                # li = {}
                # li['kmye'] = km_data
                # li['slje'] = slje_data
                # li['wbje'] = wbje_data'''

                # 保存到数据库
                kmString = json.dumps(km_data)
                self.exportSql.insert_new(ztID, Qj, infonameID, kmString)

        except Exception as e:
            msg = '科目余额导出失败:{}'.format(str(e))
        else:
            msg = '科目余额导出成功'
        return msg

    def getKMBody(self, Qj):
        js = '''getKMBody=function(kjqj_date){
                        var data = {
                            "beginPeriod":kjqj_date,
                            "endPeriod":kjqj_date,
                            "beginTitleCode":"",
                            "endTitleCode":"",
                            "pageNo":0,
                            "pageSize":5000,
                            "showYearAccumulated":true,
                            "assistantId":"",
                            "assistantType":"",
                            "showAssistant":true,
                            "titleLevel":6,
                            "showEndBalance0":true,
                            "showQuantity":false,
                            "fcurCode":""
                            }
                        $.ajax({
                            type: "POST",
                            url: 'https://17dz.com/xqy-portal-web/finance/accountBalanceSheet/query',
                            contentType:'application/json;charset=utf-8',
                            data: JSON.stringify(data),
                            success: function (result) {
                                if(result.success) {
                                    top.KMBody = result;
                                } else {
                                    top.KMBody = result;
                                }
                            }
                        })
                    }
                    '''
        self.browser.evaluate_script(js)

        # 获取科目余额
        self.browser.evaluate_script('getKMBody("%s")' % Qj)
        data_km = {}
        i = 1
        while True:
            if self.browser.evaluate_script("top.KMBody"):
                data_km = self.browser.evaluate_script('top.KMBody')['body']
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass
        self.browser.evaluate_script('top.KMBody=""')

        if Qj == "201601":
            print(data_km)

        return data_km

    # 辅助核算余额表  说明:
    def fzhssheet(self, QjList, company):

        js = '''getFzhssheet=function(kjqj_date){
                var data = {
                    "assistantType":"c",
                    "beginCode":"",
                    "endCode":"",
                    "beginPeriod":kjqj_date,
                    "endPeriod":kjqj_date,
                    "assistantId":"",
                    "bwsTypeList":"B",
                    "level":"6",
                    "showEmptyBalance":false,
                    "firstAccountTitle":false,
                    "accumulated":true
                }
                $.ajax({
                    type: "POST",
                    url: 'https://17dz.com/xqy-portal-web/finance/assistantBalanceBook/list',
                    contentType:'application/json;charset=utf-8',
                    data: JSON.stringify(data),
                    success: function (result) {
                        if(result.success) {
                            top.fzhs_data = result;
                        } else {
                            top.fzhs_data = result;
                        }
                    }
                })
            }'''

        self.browser.evaluate_script(js)

        fzhs_dict = {}

        for Qj in QjList:

            self.browser.evaluate_script('getFzhssheet("%s")' % Qj)
            i = 1
            while True:
                if self.browser.evaluate_script("top.fzhs_data"):
                    fzhsye = self.browser.evaluate_script(
                        'top.fzhs_data')['body']
                    break
                elif i > 5:
                    break
                else:
                    time.sleep(0.5)
                    i += 1
                    pass
            self.browser.evaluate_script('top.fzhs_data=""')

            slje = self.getFZBody(Qj, "s", "B,S")
            wbje = self.getFZBody(Qj, "w", "B,W")

            li = {}
            li['fzhsye'] = fzhsye
            li['slje'] = slje
            li['wbje'] = wbje

            fzhs_dict[str(Qj)] = li

        if not fzhs_dict:
            return '获取辅助核算余额表失败'

        # 保存到数据库
        try:
            self.exportSql.update_fzsheet(company, fzhs_dict)
        except Exception as e:
            return '辅助核算余额表保存失败:%s' % e

        return '辅助核算余额表导出成功'

    def getFZBody(self, Qj, balanceType, bwsTypeList):
        js = '''getFZBody=function(kjqj_date,balanceType,bwsTypeList){
                var data = {"beginPeriod":"201811",
                            "endPeriod":"201811",
                            "beginCode":"",
                            "endCode":"",
                            "assistantType":"c",
                            "assistantId":"",
                            "balanceType":balanceType,
                            "ifCondition":false,
                            "bwsTypeList":bwsTypeList,
                            "firstAccountTitle":false,
                            "showEmptyBalance":false,
                            "level":"6",
                            "accumulated":true
                }
                $.ajax({
                    type: "POST",
                    url: 'https://17dz.com/xqy-portal-web/finance/assistantBalanceBook/list',
                    contentType:'application/json;charset=utf-8',
                    data: JSON.stringify(data),
                    success: function (result) {
                        if(result.success) {
                            top.FZBody = result;
                        } else {
                            top.FZBody = result;
                        }
                    }
                })
            }'''

        self.browser.evaluate_script(js)

        # 获取科目余额
        self.browser.evaluate_script('getFZBody("%s","%s","%s")' %
                                     (Qj, balanceType, bwsTypeList))

        i = 1
        km_data = {}
        while True:
            if self.browser.evaluate_script("top.FZBody"):
                km_data = self.browser.evaluate_script('top.FZBody')['body']
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass
        self.browser.evaluate_script('top.FZBody=""')

        return km_data

    #现金流量
    def xjll(self, QjList, ztID, infoname):

        jd_js = '''xjll=function(url){
                $.ajax({
                    type:'GET',
                    url: url,
                    success: function (result) {
                        if(result.success) {
                            top.xjll_data = result;
                        } else {
                            top.xjll_data = result;
                        }
                    }
                })
            }'''

        # self.browser.evaluate_script(xjll_js)

        self.browser.evaluate_script('window.open("about:blank")')
        self.browser.windows.current = self.browser.windows[1]

        #获取起始季度
        jd_url = 'https://17dz.com/xqy-portal-web/finance/cashFlowInitial/queryInitialPeriod?_=1547174631618'
        self.browser.visit(jd_url)
        jd_jsonStr = self.browser.find_by_tag('pre').first.text
        init_jd = json.loads(jd_jsonStr)

        #月报
        # 创建数据库的infonameID
        Y_infonameID = self.exportSql.init_infoname(infoname + '-月报').id
        try:
            for Qj in QjList:
                time.sleep(0.5)
                y_url = 'https://17dz.com/xqy-portal-web/finance/cashFlowSheet?accountPeriod={}&sheetType=2&_=1543301545878'.format(
                    Qj)
                self.browser.visit(y_url)
                Y_jsonStr = self.browser.find_by_tag('pre').first.text

                #月报存库
                self.exportSql.insert_new(ztID, Qj, Y_infonameID, Y_jsonStr)
        except Exception as e:
            msg = '现金流量月报导出失败:{}'.format(str(e))
        else:
            msg = '现金流量月报导出成功'

        #季报
        # 创建数据库的infonameID
        J_infonameID = self.exportSql.init_infoname(infoname + '-季报').id
        try:
            for Qj in QjList:
                year = Qj[:4]
                if Qj[4:] in ['01', '02', '03']:
                    jd = '1'
                elif Qj[4:] in ['04', '05', '06']:
                    jd = '2'
                elif Qj[4:] in ['07', '08', '09']:
                    jd = '3'
                elif Qj[4:] in ['10', '11', '12']:
                    jd = '4'
                time.sleep(0.5)
                j_url = 'https://17dz.com/xqy-portal-web/finance/cashFlowSheet/quarterlyReport?year={}&season={}&_=1543301545880'.format(
                    year, jd)
                self.browser.visit(j_url)
                J_jsonStr = self.browser.find_by_tag('pre').first.text
                qj = '%s-%s' % (year, jd)
                # 季报存库
                self.exportSql.insert_new(ztID, qj, J_infonameID, J_jsonStr)
        except Exception as e:
            msg = '现金流量季报导出失败:{}'.format(str(e))
        else:
            msg = '现金流量季报导出成功'

        self.browser.windows.current.close()
        self.browser.windows.current = self.browser.windows[0]

        return msg

    # 基础设置
    def settings(self, customerId, ztID, accountSetId, QjList, infoname):
        set_js = '''getSettings=function(url){
                        $.ajax({
                            type:'GET',
                            url: url,
                            success: function (result) {
                                if(result.success) {
                                    top.load_data = result;
                                } else {
                                    top.load_data = result;
                                }
                            }
                        })
                    }'''
        self.browser.evaluate_script(set_js)

        #科目
        # 创建数据库的infonameID
        kmID = self.exportSql.init_infoname(infoname + '-科目').id
        km_dict = {}
        # 获取资产,负债,权益,成本,损益对应的编码
        code_url = 'https://17dz.com/xqy-portal-web/finance/accountTitle/types?systemAccountId=1&_=1542955356592'
        AllCodes = self.get_settings(code_url).get('body', [])
        for i in AllCodes:
            code = i['code']
            name = i['name']
            km_url = 'https://17dz.com/xqy-portal-web/finance/customerAccountTitles/' \
                  'listByType?customerId={}&subjectType={}&_=1542955356593'.format(customerId,code)
            res = self.get_settings(km_url)
            km_dict[name] = res

        #辅助核算
        # 创建数据库的infonameID
        fzID = self.exportSql.init_infoname(infoname + '-辅助核算').id
        fz_dict = {}
        Base_url = 'https://17dz.com/xqy-portal-web/finance/{}/list' \
                '/page?key=&accountSetId={}&customerId={}&pageNo=0&pageSize=10000'

        FZ_List = ['clients', 'suppliers', 'inventories', 'projects']

        for name in FZ_List:
            newUrl = Base_url.format(name, accountSetId, customerId)
            data = self.get_settings(newUrl).get('body')
            fz_dict[name] = data

        # 币别
        # 创建数据库的infonameID
        bbID = self.exportSql.init_infoname(infoname + '-币别').id
        url = 'https://17dz.com/xqy-portal-web/finance/exchangeRates/all?accountPeriod={}&_=1542955356686'
        for Qj in QjList:
            newurl = url.format(Qj)
            B = self.get_settings(newurl)
            # 将币别存库
            self.exportSql.insert_new(ztID, Qj, bbID, json.dumps(B))

        try:
            # 将科目存库
            self.exportSql.insert_new(ztID, '', kmID, json.dumps(km_dict))
            # 辅助核算保存入库
            self.exportSql.insert_new(ztID, '', fzID, json.dumps(fz_dict))

        except Exception as e:
            return '基础设置导出成功保存失败:{}'.format(str(e))

        return '基础设置导出成功'

    def get_settings(self, url):

        try:

            self.browser.evaluate_script('getSettings("%s")' % url)

        except Exception as e:
            print(e)
        i = 1
        settings_data = {}
        while True:
            if self.browser.evaluate_script("top.load_data"):
                settings_data = self.browser.evaluate_script('top.load_data')
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass

        self.browser.evaluate_script('top.load_data=""')

        return settings_data

    #获取现金流量
    def get_xjll(self, url):

        try:
            self.browser.evaluate_script('xjll("%s")' % url)
            time.sleep(5.5)
        except Exception as e:
            print(e)
        i = 1
        xjll_data = {}
        while True:
            if self.browser.evaluate_script("top.xjll_data"):
                xjll_data = self.browser.evaluate_script('top.xjll_data')
                break
            elif i > 5:
                break
            else:
                time.sleep(0.5)
                i += 1
                pass

        self.browser.evaluate_script('top.xjll_data=""')

        return xjll_data
Пример #3
0
browser = Browser('chrome', **executable_path)
#browser = Browser('chrome')

#Login
browser.visit('https://kyfw.12306.cn/otn/login/init')

loginBtn = browser.find_by_id('loginSub')
browser.fill('loginUserDTO.user_name', 'username')
browser.fill('userDTO.password', 'password')
loginBtn.click()

#Search ticket
#browser.visit('https://kyfw.12306.cn/otn/leftTicket/init')
time.sleep(4)
browser.find_by_xpath('//li[@id="selectYuding"]/a').click()
browser.evaluate_script(
    'document.getElementById("fromStation").setAttribute("type","visiable")')
browser.evaluate_script(
    'document.getElementById("toStation").setAttribute("type","visiable")')
browser.evaluate_script('document.getElementById("train_date").readOnly=false')
browser.fill('leftTicketDTO.from_station', 'TJP')
browser.fill('leftTicketDTO.to_station', 'MHL')
browser.fill('leftTicketDTO.train_date', '2017-11-30')
browser.evaluate_script(
    'document.getElementsByClassName("cal-wrap")[0].style.display="none"')
#browser.find_by_text('查询').click()
time.sleep(2)
browser.find_by_text('查询').click()
#browser.reload()
#browser.find_by_text('预订')[3].click()
time.sleep(2)
Пример #4
0
class Ticket(object):
    def __init__(self, config_file):
        ## config parser setting
        self.config_file = config_file
        self.settings = configparser.ConfigParser()
        self.settings._interpolation = configparser.ExtendedInterpolation()
        self.settings.read(self.config_file)
        ## environment setting
        self.brower='chrome'
        self.b = Browser(driver_name=self.brower) 
        self.station={}
        self.url = "https://kyfw.12306.cn/otn/leftTicket/init"
        # 席别类型(对应列标号)
        self.ticket_index = [
                            '',
                            u'商务座',
                            u'特等座',
                            u'一等座', 
                            u'二等座',
                            u'高级软卧',
                            u'软卧',
                            u'硬卧',
                            u'软座',
                            u'硬座',
                            u'无座'
                            ]
        self.username = ''
        self.password = ''
        self.date_format='%Y-%m-%d'
        self.tolerance = -1
        self.blacklist = {}
        self.date = []
        self.isStudent = False
        self.success = 0
        self.find_ticket = 0
        self.config_parser()
        self.playmusic = False
        self.count = 0

    def ConfigSectionMap(self,section):
            dict1 = {}
            options = self.settings.options(section)
            for option in options:
                try:
                    dict1[option] = self.settings.get(section, option)
                    if dict1[option] == -1:
                        DebugPrint("skip: %s" % option)
                except:
                        print("exception on %s!" % option)
                        dict1[option] = None
            return dict1
    def daterange(self, start_date, end_date):
        for n in range(int ((end_date - start_date).days) + 1):
            yield start_date + timedelta(n) 

    def config_parser(self):
        if self.retrieve_station_dict() == -1:
            sys.exit()
        if self.retrieve_book_options() == -1:
            sys.exit()
        
    def retrieve_station_dict(self):
        dict_helper=self.ConfigSectionMap('STATIONCOOKIE')
        for name, value in dict_helper.iteritems():
            self.station[name]=value

    def retrieve_book_options(self):
        login_info=self.ConfigSectionMap('GLOBAL')
        self.username = login_info['username'].strip() 
        self.password = login_info['password'].strip()
        self.brower = login_info['browser']
        book_settings = self.ConfigSectionMap('TICKET')
        self.fromStation = [ station.strip() for station in book_settings['from_station'].split(',')]
        self.toStation = [ station.strip() for station in book_settings['to_station'].split(',')]
        trains = [ train.strip() for train in book_settings['trains'].split(',')]
        if len(trains) == 1 and trains[0] == '':
            self.trains = []
        else:
            self.trains =  trains
        self.ticket_type =[ _type.strip() for _type in book_settings['ticket_type'].split(',')]
        rangeQuery = book_settings['range_query'].strip()
        if rangeQuery == 'Y':
            date = [ d.strip() for d in book_settings['date'].split(',')]
            if len(date) < 2:
                print "未设置正确的起至时间"
                return -1
            else: 
                start_date = datetime.strptime(date[0],self.date_format) 
                end_date = datetime.strptime(date[1],self.date_format) 
                if end_date < start_date:
                    print "查询截止日期不可大于开始日期!"
                    return -1
                for single_date in self.daterange(start_date, end_date): 
                    self.date.append(single_date.strftime(self.date_format))
        else:
            self.date = [ d.strip() for d in book_settings['date'].split(',')]
        if book_settings['student'].strip() == 'Y':
            self.isStudent = True
        self.tolerance = int(book_settings['tolerance'])
        self.people = [ people.strip() for people in book_settings['people'].split(',') ]
        if book_settings['alarm'].strip() == 'Y':
            self.playmusic = True

    def login(self):
        self.b.visit(self.url)
        self.b.find_by_text(u"登录").click()
        self.b.fill("loginUserDTO.user_name",self.username)
        self.b.fill("userDTO.password",self.password)
        pdb.set_trace()
    
    def page_has_loaded(self):
        page_state = self.b.evaluate_script("document.readyState")
        return page_state == 'complete'

    def switch_to_order_page(self):
        order = []
        while len(order) == 0:
            order = self.b.find_by_text(u"车票预订")
        order[0].click()

    def checkTicket(self, date, fromStation, toStation):
        print 'date: %s, from %s, to %s'%(date, fromStation, toStation)
        self.b.cookies.add({"_jc_save_fromDate":date})
        self.b.cookies.add({"_jc_save_fromStation":self.station[fromStation]})
        self.b.cookies.add({"_jc_save_toStation":self.station[toStation]})
        self.b.cookies.all()
        self.b.reload()
        if self.isStudent:
            self.b.find_by_text(u'学生').click()
        self.b.find_by_text(u"查询").click()
        all_trains = []
        while self.page_has_loaded() == False:
            continue
        while len(all_trains) == 0:
            all_trains = self.b.find_by_id('queryLeftTable').find_by_tag('tr')
        for k, train in enumerate(all_trains):
            tds = train.find_by_tag('td')
            if tds and len(tds) >= 10:
                has_ticket= tds.last.find_by_tag('a')
                if len(has_ticket) != 0:
                    if k + 1 < len(all_trains):
                        this_train = all_trains[k+1]['datatran']
                        if len(self.trains) != 0 and this_train not in self.trains:
                            continue
                        if self.tolerance != -1 and this_train in self.blacklist and self.blacklist[this_train] >= self.tolerance:
                            print u"%s 失败 %d 次, 跳过"%(this_train, self.blacklist[this_train])
                            continue
                    for cat in self.ticket_type:
                        if cat in self.ticket_index:
                            i = self.ticket_index.index(cat)
                        else:
                            print '无效的席别信息'
                            return 0, ''
                        if tds[i].text != u'无' and tds[i].text != '--':
                            if tds[i].text != u'有':
                                print u'%s 的 %s 有余票 %s 张!'%(this_train, cat ,tds[i].text)
                            else:
                                print u'%s 的 %s 有余票若干张!'%(this_train, cat)
                            self.find_ticket = 1
                            tds.last.click()
                            break
            if self.find_ticket:
                break
        return this_train

    def book(self):
        while self.page_has_loaded() == False:
            continue
        if len(self.people) == 0:
            print '没有选择乘车人!'
            return 1
        more = []
        while len(more) == 0:
            more = self.b.find_by_text(u"更多")
        more[0].click()
        person = []
        people = self.people
        while len(person) == 0:
            person=self.b.find_by_xpath('//ul[@id="normal_passenger_id"]/li/label[contains(text(),"%s")]'%people[0])
        for p in people:
            self.b.find_by_xpath('//ul[@id="normal_passenger_id"]/li/label[contains(text(),"%s")]'%p).click()
            if self.b.find_by_xpath('//div[@id="dialog_xsertcj"]').visible:
                self.b.find_by_xpath('//div[@id="dialog_xsertcj"]/div/div/div/a[text()="确认"]').click()
            return 1

    def ring(self):
        pygame.mixer.pre_init(64000, -16, 2, 4096)
        pygame.init()
        pygame.display.init()
        screen=pygame.display.set_mode([300,300])
        #pygame.display.flip()
        pygame.time.delay(1000)#等待1秒让mixer完成初始化
        tracker=pygame.mixer.music.load("media/sound.ogg")
        #track = pygame.mixer.music.load("sound.ogg")
        pygame.mixer.music.play()
        # while pygame.mixer.music.get_busy():
        #pygame.time.Clock().tick(10)
        running = True
        img=pygame.image.load("media/img.jpg")
        while running:
            screen.blit(img,(0,0))
            pygame.display.flip()
            for event in pygame.event.get():
                if event.type==pygame.QUIT:
                    running = False
        pygame.quit ()
        return 1
    def executor(self):
        self.login()
        self.switch_to_order_page()
        while self.success == 0:
            self.find_ticket = 0
            while self.find_ticket == 0:
                for date in self.date:
                    try:
                        self.count += 1
                        print "Try %d times" % self.count
                        for fromStation in self.fromStation:
                            for toStation in self.toStation:
                                this_train = self.checkTicket(date, fromStation, toStation)
                                if self.find_ticket:
                                    break
                            if self.find_ticket:
                                break
                        if self.find_ticket:
                            break
                    except KeyboardInterrupt:
                        self.b.find_by_text(u'退出').click()
                        sys.exit()
                    except:
                        continue
            # book ticket for target people
            self.find_ticket = 0
            while self.find_ticket == 0:
                try:
                    self.find_ticket = self.book() 
                except KeyboardInterrupt:
                    self.b.find_by_text(u'退出').click()
                    sys.exit()
                except:
                    continue
            if self.playmusic:
                self.ring()
            print "订票成功了吗?(Y/N)"
            input_var = ''
            while input_var == '':
                input_var= sys.stdin.read(1)
                if input_var == 'Y' or input_var == 'y':
                    self.success = 1
                elif input_var == 'N' or input_var == 'n':
                    if this_train in self.blacklist:
                        self.blacklist[this_train] += 1
                    else:
                        self.blacklist[this_train] = 1
                    print u"%s 失败 %d 次"%(this_train, self.blacklist[this_train])
                    self.b.back()
                    self.b.reload()
                else:
                    input_var = ''
                    continue
        self.b.find_by_text(u'退出').click()
class halfAutoGetTicket():
    def __init__(self):
        self.driver_name = 'chrome'
        self.executable_path = '/usr/local/lib/python3.6/chromedriver'
        # # self.driver = webdriver.Chrome(executable_path='/usr/local/lib/python3.6/chromedriver')
        # self.driver.implicitly_wait(10)
        self.driver = Browser(driver_name=self.driver_name,
                              executable_path=self.executable_path)
        self.driver.driver.set_window_size(1400, 1000)
        self.username = '******'
        self.passwd = 'yangmeng123'
        self.train_date = '2018-12-29'
        self.from_station = '%u90D1%u5DDE%2CZZF'
        self.to_station = '%u5317%u4EAC%2CBJP'

        self.order = 0
        self.users = ''

    def login(self):

        self.driver.visit(login_url)
        # 填充密码
        self.driver.fill("loginUserDTO.user_name", self.username)
        # sleep(1)
        self.driver.fill("userDTO.password", self.passwd)
        print(u"等待验证码,自行输入...")
        while True:
            if self.driver.url != initmy_url:
                print('--------')
                sleep(1)
            else:
                print('+++++++++')
                break

    def getTickets(self):

        # self.driver=Browser(driver_name=self.driver_name,executable_path=self.executable_path)
        # self.driver.driver.set_window_size(1400, 1000)
        # self.driver.visit("file:///Users/iyunshu/Desktop/1111.htm")

        # soup = BeautifulSoup(tempHtml, 'html.parser')
        html = self.driver.html  #获取网页的html数据
        soup = BeautifulSoup(html, 'html.parser')
        table = soup.find(id="queryLeftTable")

        while len(table.findAll('tr')) == 0:
            html = self.driver.html  #获取网页的html数据
            soup = BeautifulSoup(html, 'html.parser')
            # soup = BeautifulSoup(tempHtml, 'html.parser')
            table = soup.find(id="queryLeftTable")

        name = []

        tickets = []

        tableTitle = soup.find(id='t-list')

        aaa = tableTitle.table.tbody

        coutn = 0

        for tr in aaa.findAll('tr'):
            ticketinfo = {}
            id = tr.get('id')
            train_id = id.split('_')[1]

            if len(tr.findAll('td')) == 13:
                id = 'train_num_%d' % coutn
                coutn += 1
                nameTd = tr.findAll('td')[0]

                div1 = nameTd.find(id=id)
                tempsoup = BeautifulSoup(str(div1), 'html.parser')
                div2 = tempsoup.find_all('div', class_='train')
                name = div2[0].div.a.get_text()

                ticketinfo["车次"] = name
                erdengTD = tr.findAll('td')[3]

                yingzuoTD = tr.findAll('td')[9]

                erdeng = 'ZE_' + train_id
                if erdengTD.get('id') == erdeng:
                    if yingzuoTD.div:
                        ticketinfo["二等"] = erdengTD.div.get_text()
                    else:
                        ticketinfo["二等"] = erdengTD.get_text()

                yingzuo = 'YZ_' + train_id
                if yingzuoTD.get('id') == yingzuo:
                    if yingzuoTD.div:
                        ticketinfo["硬座"] = yingzuoTD.div.get_text()
                    else:
                        ticketinfo["硬座"] = yingzuoTD.get_text()

                yuedingTD = tr.findAll('td')[12].a
                print(yuedingTD)
                if ticketinfo["二等"] != '--' or ticketinfo["硬座"] != '--':
                    if ticketinfo["二等"] != '无' or ticketinfo["硬座"] != '无':
                        self.driver.evaluate_script(yuedingTD.onclick)

            tickets.append(ticketinfo)

        print(tickets)

    def start(self):
        self.login()
        self.driver.visit(ticket_url)
        try:
            print("购票页面开始...")
            # sleep(1)
            # 加载查询信息

            self.driver.cookies.add(
                {"_jc_save_fromStation": self.from_station})
            self.driver.cookies.add({"_jc_save_toStation": self.to_station})
            self.driver.cookies.add({"_jc_save_fromDate": self.train_date})

            self.driver.reload()

            count = 0
            if self.order != 0:
                while self.driver.url == ticket_url:
                    self.driver.find_by_text(u"查询").click()
                    count += 1
                    print("循环点击查询... 第 %s 次" % count)

                    # sleep(1)
                    # try:
                    #     self.driver.find_by_text(u"预订")[self.order - 1].click()
                    # except Exception as e:
                    #     print (e)
                    #     print ("还没开始预订")
                    #     continue
            else:
                while self.driver.url == ticket_url:
                    self.driver.find_by_text(u"查询").click()
                    count += 1
                    print("循环点击查询... 第 %s 次" % count)
                    self.getTickets()
                    # sleep(0.8)
                    # try:
                    #     for i in self.driver.find_by_text(u"预订"):
                    #         i.click()
                    #         sleep(1)
                    # except Exception as e:
                    #     print (e)
                    #     print ("还没开始预订 %s" %count)
                    #     continue
            print("开始预订...")
            # sleep(3)
            # self.driver.reload()
            sleep(1)
            print('开始选择用户...')
            for user in self.users:
                self.driver.find_by_text(user).last.click()

            print("提交订单...")
            sleep(1)
            # self.driver.find_by_text(self.pz).click()
            # self.driver.find_by_id('').select(self.pz)
            # # sleep(1)
            # self.driver.find_by_text(self.xb).click()
            # sleep(1)
            self.driver.find_by_id('submitOrder_id').click()
            # print u"开始选座..."
            # self.driver.find_by_id('1D').last.click()
            # self.driver.find_by_id('1F').last.click()

            sleep(1.5)
            print("确认选座...")
            self.driver.find_by_id('qr_submit_id').click()

        except Exception as e:
            print(e)
javascript_advanced_and_organized_code.py
"""
from splinter.browser import Browser

browser = Browser('chrome')
# Visit URL
url = "http://splinter.cobrateam.info/"
browser.visit(url)
# 1 - Send code to webpage to be executed
# you can execute a simple javascript code
browser.execute_script('alert("Hello World")')
# assign variable
javascript_code = 'message = "After this alert, the body tag will disappear";'
javascript_code += 'alert(message);'
browser.execute_script(javascript_code)
# you just can execute any javascript code, like,
# for example, manupulate dom
# javascript snippet to hidden the body
browser.execute_script('document.getElementsByTagName("body")[0].style.display = "none"')
# 2 - Getting data returned from javascript code execution
# getting value of the 'display' attribute from the body tag
value_of_display = browser.evaluate_script('document.getElementsByTagName("body")[0].style.display')
browser.execute_script('alert("As you could see, the body disappeared, so the display is set as: %s");' % value_of_display)
browser.execute_script('alert("..but now");')
# back to the normal, that is, display:block
browser.execute_script('document.getElementsByTagName("body")[0].style.display = "block"')

value_of_display = browser.evaluate_script('document.getElementsByTagName("body")[0].style.display')
browser.execute_script('alert("back to the normal! And display is set as: %s");' % value_of_display)
# NOTE: you can use the jQuery, or any snippet of any
# javascript framework, you simply include it before execute
Пример #7
0
class Tickets():
    """
    one object "Tickets" means one person's snatching tickets
    """
    def __init__(self, username, pwd):
        """
        Input your username and password to this function to create a object
        
        @para: username,pwd are str
        @return: None
        """
        self.username = username
        self.password = pwd
        self.ticket_url = "https://kyfw.12306.cn/otn/leftTicket/init"
        self.login_page_url = "https://kyfw.12306.cn/otn/login/init"
        self.my_homepage_url = "https://kyfw.12306.cn/otn/index/initMy12306"
        self.browser = Browser(
            driver_name='chrome',
            user_agent=
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
        )
        self.captcha_path = 'info/captcha.jpg'
        self.query_logs = []
        self.passengers_list = []

    def _captcha_identify(self):
        """
# =============================================================================
#         This function will identify the captcha of 12306.
#         The captcha problem in this site is identifying the objects
#         in the given picture then clicking the ones the prompt suggests.
#         On the other hand, this function will get the image by relative path
#         'info/captcha.jpg', identify the corresponding characters and get to 
#         know what to find to click, and identify the eight small pictures in 
#         the overall picture and choose the ones that are conformed to the 
#         desired ones.Then it returns the answer, each two being a pair, meaning
#         the click position
# =============================================================================
        This function will show the users the captcha and format it and return
        the answer.
        @return: str
        """
        answer = ''
        pos_dict = {
            1: "36,47,",
            2: "110,43,",
            3: "182,45,",
            4: "260,44,",
            5: "36,115,",
            6: "115,113,",
            7: "184,113,",
            8: "264,113,"
        }
        with PIL.Image.open(self.captcha_path) as img:
            print('Please input the numbers of the pictures in the captcha ' +
                  'you want to choose\n(number ranges in [1~8] ' +
                  'and please separate them with " "):')
            img.show()
            numbers = input()
            for number in numbers.split(' '):
                answer += pos_dict[int(number)]
        return answer[:-1]

    def log_in(self):
        """
        This function helps you log in your account in "kyfw.12306.cn",
        it is based on the private functions below:
            (1)_captcha_identify
            (2)_get_passengers
            
        @return: bool, showing whether it succeeds
        """
        self.browser.visit(self.login_page_url)
        s = requests.session()
        headers = {
            'user-agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
        }
        captcha_page = ''
        #deal with captcha-check
        while ('4' not in captcha_page):
            s.cookies.clear_session_cookies()
            captcha_get_url = "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.9670588224384102"
            r = s.get(captcha_get_url)
            with open(self.captcha_path, 'wb') as f:
                f.write(r.content)
            captcha = self._captcha_identify()
            captcha_data = {
                'answer': captcha,
                'login_site': 'E',
                'rand': 'sjrand'
            }
            captcha_check_url = 'https://kyfw.12306.cn/passport/captcha/captcha-check'
            captcha_page = s.post(captcha_check_url,
                                  data=captcha_data,
                                  headers=headers,
                                  verify=False)
            captcha_page = captcha_page.text
            print(captcha_page)
        print('captcha success')
        #deal with username password
        login_data = {
            'username': self.username,
            'password': self.password,
            'appid': 'otn'
        }
        login_url = "https://kyfw.12306.cn/passport/web/login"
        r = s.post(login_url, data=login_data, headers=headers, verify=False)
        j = json.loads(r.text)
        if (j["result_message"] != "登录成功"):
            return False
        #if successful, it continues to get cookies
        print("username and password are both right")
        url1 = "https://kyfw.12306.cn/otn/login/userLogin"
        r = s.post(url1, data={'_json_att': ''}, headers=headers, verify=False)
        #print(r.text)
        url2 = "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin"
        r = s.get(url2, headers=headers, verify=False)
        #print(r.text)
        url3 = "https://kyfw.12306.cn/passport/web/auth/uamtk"
        r = s.post(url3, data={'appid': 'otn'}, headers=headers, verify=False)
        #print(r.text)
        j = json.loads(r.text)
        url4 = "https://kyfw.12306.cn/otn/uamauthclient"
        r = s.post(url4,
                   data={'tk': j['newapptk']},
                   headers=headers,
                   verify=False)
        #print(r.text)
        url5 = url1
        r = s.get(url5, headers=headers, verify=False)
        #print(r.text)
        r = s.get(self.my_homepage_url, headers=headers, verify=False)
        #print(r.text)
        #submit the cookies to the chromedriver
        self.browser._cookie_manager.add(s.cookies)
        self.browser.visit(self.my_homepage_url)
        sleep(1)
        if (self.browser.url != self.my_homepage_url):
            raise Exception("The process of getting cookies gets wrong.")
        print('log in successfully')
        return True

    def reset_info(self, new_username, new_pwd):
        """
        This function allows you to reset the information of the users.
        It aims to deal with the circumstances such as:
            (1)The user inputs the wrong information and can't log in the site
            (2)...
        @para: new_username, new_pwd are str
        @return: None
        """
        #So far it is only suitable before you log in
        self.username = new_username
        self.password = new_pwd

    # self.query_logs = []

    def _get_passengers(self):
        """
        This function get the list of the names of the contacts of the user,
        and the names contain brackets and "学生" when he/her is a student
        @return: list(str)
        """
        self.browser.visit("https://kyfw.12306.cn/otn/passengers/init")
        soup = bs(self.browser.html, "html.parser")
        tr_list = soup.find("tbody", id="passengerAllTable").find_all("tr")
        passengers_list = []
        for tr in tr_list:
            td_list = tr.find_all("td")
            for i in range(len(td_list)):
                if (i % 8 == 1):
                    name = str(td_list[i].string)
                elif (i % 8 == 5):
                    if ("学生" in td_list[i]):
                        name = name + "(学生)"
                    passengers_list.append(name)
        return passengers_list

    def _query(self, from_station, to_station, date):
        """
        This function queries the site of the information belows:
            where do you start? (it can be city name or station name)
            where is your destination? (it can be city name or station name)
            what date is it for you to depart? (eg. 2018-01-28)
        And it makes the browser, Chrome, loads the query page and returns the
        correspoding html of the page
        Note: the date format must be corrected before being the the argument, 
        and the date should never be out of the bookable time bound. If the date
        is out of the bookable time bound, it will return a default page given
        by the site as the one when we input the out-bound date by hand. Often 
        it's the tickets page whose date is the lower bound of the bookable 
        bound.
        
        @para: from_station, to_station, date are str
        @return: str
        """
        self.browser.visit(self.ticket_url)
        try:
            #initiate the date
            self.browser.cookies.add({'_jc_save_fromDate': date})
            self.browser.reload()
            #cope with exception from the input format error
            from_station_abbr = getAbbr(from_station)
            to_station_abbr = getAbbr(to_station)
            if (from_station_abbr == ''):
                raise Exception("The from_station doesn't exist")
            if (to_station_abbr == ''):
                raise Exception("The to_station doesn't exist")
            #initiate the from_station
            self.browser.evaluate_script(
                'document.getElementById("fromStation").value="' +
                from_station_abbr + '"')
            #initiate the to_station
            self.browser.evaluate_script(
                'document.getElementById("toStation").value="' +
                to_station_abbr + '"')
            #query with clicking the button
            self.browser.find_link_by_text('查询').click()
            sleep(3)
            return self.browser.html

    # =============================================================================
    #             query_url = "https://kyfw.12306.cn/otn/leftTicket/query?"
    #             + "leftTicketDTO.train_date=" + date
    #             + "&leftTicketDTO.from_station=" + from_station_abbr
    #             + "&leftTicketDTO.to_station=" + to_station_abbr
    #             + "&purpose_codes=ADULT"
    # =============================================================================
        except:
            print("Error. The browser will quit soon.")
            self.browser.screenshot(name='error_of_fun_query')
            self.browser.quit()
            raise

    def _prettify_html(self, html):
        '''
        This function get the information of the train out of the html
        
        @para: html is str
        @return: list(dict()), attention: it's [{}] when no thing is found,
        and the structure of dict() is as follows:
            tickets_dict = {
                'trainNumber':'',
                'fromStation':'',
                'toStation':'',
                'departTime':'',
                'arriveTime':'',
                'period':'',
                'specialSeat':'',
                'oneClassSeat':'',
                'twoClassSeat':'',
                'advancedSoftSleeper':'',
                'softSleeper':'',
                'hardSleeper':'',
                'motionSleeper':'',
                'softSeat':'',
                'hardSeat':'',
                'noSeat':'',
                'bookable':False,
                'book_btn':None 
                 #if it's unbookable, it'll be None
                }
        '''
        if (html == ''):
            return [{}]
        tickets_list = []
        book_btn_list = self.browser.find_link_by_text('预订')
        book_btn_list_ptr = 0
        soup = bs(html, 'html.parser')
        tr_list = soup.find('tbody', id='queryLeftTable').find_all('tr')
        #there are no tickets at all
        if (tr_list == []):
            return [{}]
        for tr in tr_list:
            td_table = tr.find_all('td')
            #when <tr> has <td>
            if (td_table != []):
                tickets_dict = {
                    'trainNumber': '',
                    'fromStation': '',
                    'toStation': '',
                    'departTime': '',
                    'arriveTime': '',
                    'period': '',
                    'specialSeat': '',
                    'oneClassSeat': '',
                    'twoClassSeat': '',
                    'advancedSoftSleeper': '',
                    'softSleeper': '',
                    'hardSleeper': '',
                    'motionSleeper': '',
                    'softSeat': '',
                    'hardSeat': '',
                    'noSeat': '',
                    'bookable': False,
                    'book_btn': None  #if it's unbookable, it'll be None
                }
                #update the tickets_dict
                #the first <td>
                info_list = [td for td in td_table[0].strings]
                if (' ' in info_list):
                    info_list.remove(' ')
                info_list.remove('查看票价')
                del info_list[len(info_list) - 1]  #delete "当/次日到达"
                tickets_dict['trainNumber'] = info_list[0]
                tickets_dict['fromStation'] = info_list[1]
                tickets_dict['toStation'] = info_list[2]
                tickets_dict['departTime'] = info_list[3]
                tickets_dict['arriveTime'] = info_list[4]
                tickets_dict['period'] = info_list[5]
                #the following <td>s except the last one
                tickets_dict['specialSeat'] = td_table[1].string
                tickets_dict['oneClassSeat'] = td_table[2].string
                tickets_dict['twoClassSeat'] = td_table[3].string
                tickets_dict['advancedSoftSleeper'] = td_table[4].string
                tickets_dict['softSleeper'] = td_table[5].string
                tickets_dict['hardSleeper'] = td_table[6].string
                tickets_dict['motionSleeper'] = td_table[7].string
                tickets_dict['softSeat'] = td_table[8].string
                tickets_dict['hardSeat'] = td_table[9].string
                tickets_dict['noSeat'] = td_table[10].string
                if (td_table[12].find('a') != None):
                    tickets_dict['bookable'] = True
                    tickets_dict['book_btn'] = book_btn_list[book_btn_list_ptr]
                    book_btn_list_ptr = book_btn_list_ptr + 1
                else:
                    tickets_dict['bookable'] = False
                    tickets_dict['book_btn'] = None
                tickets_list.append(tickets_dict)
                del tickets_dict
        return tickets_list

    def _book(self, button, passengers_list):
        """
        This function will book the ticket which the button belongs to for the
        passengers in the passengers_list. If it succeeds, it returns True
        
        @para: button is <splinter.driver.webdriver.WebDriverElement>
               and passengers_list is list(str)
        @return: bool
        """
        try:
            button.click()
            #book_url = "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
            #if (self.browser.url != book_url):
            #    raise Exception("The button fails.")
            #we have entered the booking page
            #and we click all the passengers
            for passenger in passengers_list:
                #we click the last according to the structure of the webpage
                print(passenger)
                #print(self.browser.html)
                while (self.browser.is_element_not_present_by_text(passenger)):
                    pass
                self.browser.find_by_text(passenger).last.click()
                #consider the case where the passenger is a student
                #and a window will alert, we need to cope with it
                if ("学生" in passenger):
                    self.browser.find_by_id("dialog_xsertcj_ok").last.click()
            self.browser.find_link_by_text("提交订单").first.click()
            #cope with window alert again
            while (self.browser.is_element_not_visible_by_xpath(
                    '//*[@id="qr_submit_id"]')):
                pass
            self.browser.find_by_id("qr_submit_id").first.click()
            # =============================================================================
            #             success_url_text = "https://kyfw.12306.cn/otn//payOrder/init"
            #             if (success_url_text in self.browser.url):
            #                 print("book the ticket(s) successfully!")
            #                 return True
            #             else:
            #                 raise Exception("Browser fails to load into the paying page.")
            # =============================================================================
            print("book the ticket(s) successfully!")
            return True
        except:
            print("Exception is raised in the booking process.")
            self.browser.screenshot(name="error_of_fun_book")
            raise
            return False

    def get_tickets_info(self,
                         from_station,
                         to_station,
                         date,
                         is_future=False):
        """
        This function is based on the private function:
            (1)_query
            (2)_prettify_html
        This function will log what the user query and the parameter date is
        able to be out of bookable time bound with only one day, so we set a
        new boolean parameter is_future to show whether the date is out of 
        the bookable time bound
        
        @para: from_station,to_station,date are str, is_future is bool
        @return: list(dict())
        """
        d = datetime.datetime(int(date.split('-')[0]), int(date.split('-')[1]),
                              int(date.split('-')[2]))
        #information goes into the query_logs
        self.query_logs.append({
            'from_station': from_station,
            'to_station': to_station,
            'date': date,
            'is_future': is_future,
            'query_time': str(d.today())
        })
        if (is_future):
            #we get the date minus one day
            d -= datetime.timedelta(days=1)
            date = str(d).split(' ')[0]
        html = self._query(from_station, to_station, date)
        tickets_list = self._prettify_html(html)
        #remember to set all tickets unbookable if it's in future
        if (is_future):
            for ticket in tickets_list:
                ticket['bookable'] = False
                ticket['book_btn'] = None
        return tickets_list

    def book_tickets_on_sale(self, tickets_dict, date, passengers_list):
        """
        This function is based on the private function below:
            (1)_book
        This function aims to book the tickets that are in the BOOKABLE time
        bound, which means that the page for the tickets is shown on the site. 
        If the tickets are not on sale or sold out, then we repeat reloading the 
        page and let this function watch over the page until the it finds the
        tickets available again, so when someone else refunds the tickets
        we can book the tickets at once. And if the tickets have remainders,
        we can book it at once, too.
        
        @para: tickets_dict is dict, passengers_list is list(str),date is str
            the structure of the dict is as follows:
            tickets_dict = {
                'trainNumber':'',
                'fromStation':'',
                'toStation':'',
                'departTime':'',
                'arriveTime':'',
                'period':'',
                'specialSeat':'',
                'oneClassSeat':'',
                'twoClassSeat':'',
                'advancedSoftSleeper':'',
                'softSleeper':'',
                'hardSleeper':'',
                'motionSleeper':'',
                'softSeat':'',
                'hardSeat':'',
                'noSeat':'',
                'bookable':False,
                'book_btn':None 
                 #if it's unbookable, it'll be None
                }
        @return: bool, showing whether it succeeds booking the tickets
        """
        if (tickets_dict["bookable"] == True):
            #now it has remainders
            self._book(tickets_dict["book_btn"], passengers_list)
            return True
        else:
            #it is sold out now, we query again to see whether it's available
            html = self._query(tickets_dict["fromStation"],
                               tickets_dict["toStation"], date)
            tickets_list = self._prettify_html(html)
            trial_times = 0
            while (True):
                #only when it's available we break out of the loop
                #every loop means one times to query
                book_btn = None
                trial_times += 1
                print(str(trial_times) + "th tries.")
                for ticket in tickets_list:
                    if (ticket["trainNumber"] == tickets_dict["trainNumber"]
                            and ticket["departTime"]
                            == tickets_dict["departTime"]
                            and ticket["bookable"] == True):
                        book_btn = ticket["book_btn"]
                        break
                #if we find it bookable
                if (book_btn != None):
                    self._book(book_btn, passengers_list)
                    break
                #else we query again, but before query we need to sleep
                sleep(3)
                self.browser.find_link_by_text("查询").first.click()
                sleep(1)
                tickets_list = self._prettify_html(self.browser.html)
            return True

    def book_tickets_in_future(self,
                               tickets_dict,
                               date,
                               passegers_list,
                               hour=8,
                               minute=0):
        """
        This function is based on the private function below:
            (1)_book
            (2)book_tickets_on_sale
        This function aims to book the tickets that are in the UNBOOKABLE time
        bound, and the date only exceeds the bound by one day. So we calculate
        the duration between now and the time user wants us to begin snatching
        (tomorrow hour:minute:00 we will wake up and start checking and snatching),
        and we let it sleep until the time is up. Then we query the site to see 
        whether the tickets are offered. And if they're offered, we can use the
        private function (2)book_tickets_on_sale to get the tickets!
        
        @para: tickets_dict is dict, passengers_list is list(str),date is str
               hour and minute are int
            the structure of the dict is as follows:
            tickets_dict = {
                'trainNumber':'',
                'fromStation':'',
                'toStation':'',
                'departTime':'',
                'arriveTime':'',
                'period':'',
                'specialSeat':'',
                'oneClassSeat':'',
                'twoClassSeat':'',
                'advancedSoftSleeper':'',
                'softSleeper':'',
                'hardSleeper':'',
                'motionSleeper':'',
                'softSeat':'',
                'hardSeat':'',
                'noSeat':'',
                'bookable':False,
                'book_btn':None 
                 #if it's unbookable, it'll be None
                }
        @return: bool, showing whether it succeeds booking the tickets
        """
        #wait until the tickets are available
        snatch_time = datetime.datetime(int(date.split('-')[0]),
                                        int(date.split('-')[1]),
                                        int(date.split('-')[2]), hour, minute,
                                        0)
        #the duration between now and the snatch-time(default tomorrow 8:00)
        duration = snatch_time - snatch_time.today()
        sleep(int(duration.total_seconds()) + 1)
        #time seems to be up
        #then we need to check whether the tickets are available
        date_in_Chinese_format = (date.split('-')[1] + '月' +
                                  date.split('-')[2] + '日')
        trial_times = 0
        while (True):
            html = self._query(tickets_dict['fromStation'],
                               tickets_dict['toStation'], date)
            trial_times += 1
            print(str(trial_times) + 'th tries.')
            soup = bs(html, 'html.parser')
            if (date_in_Chinese_format
                    in str(soup.find('div', id="sear-result"))):
                print("The tickets page is available now! we'll buy it now!")
                break
            sleep(5)  #after 5s we check again
        #since the tickets are available, we can buy it
        self.book_tickets_on_sale(tickets_dict, date, passegers_list)
        return True

    def __del__(self):
        """
        Remember to quit the browser
        
        @return: None
        """
        self.browser.quit()
Пример #8
0
class Scrapy12306():

    def __init__(self):

        config = ConfigParser.ConfigParser()
        config.readfp(codecs.open("12306.conf", "r", "utf-8"))
        self.url = config.get("config","url")
        self.username = config.get("config","username")
        self.password = config.get("config","password")
        self.bType = config.get("config","browser")
        #self._from = config.get("config","_from")
        #self._to = config.get("config","_to")
        self._from = u'北京'
        self._to = u'邯郸'
        self.date = config.get("config","date")
        
        print "browser :%s url:%s" % (self.bType,self.url)
        self.browser = Browser(self.bType)
        self.browser.visit(self.url)

    def login(self):
        if self.username=="" or self.password=="":
            print "error:username and password must not be empty"
            self.browser.quit()
            sys.exit(-1)
        self.browser.fill("loginUserDTO.user_name",self.username)
        self.browser.fill("userDTO.password",self.password)
        time.sleep(10)
        self.browser.find_by_id("loginSub").click()
        loginFlag = self.browser.find_by_id("link_4_myTicket")
        return not loginFlag.is_empty()


    def getTicket(self):
        self.browser.find_by_xpath("//a[@href='/otn/leftTicket/init']")[0].click()
        #self.browser.fill("leftTicketDTO.from_station_name",self._from)
        #self.browser.fill("leftTicketDTO.to_station_name",self._to)
        self.browser.cookies.add({"_jc_save_fromStation":"%u5317%u4EAC%2CBJP"})
        self.browser.cookies.add({'_jc_save_toStation':'%u90AF%u90F8%2CHDP'})
        #self.browser.fill("leftTicketDTO.train_date",self.date)
        self.browser.cookies.add({"_jc_save_fromDate":self.date})
        isload = False
        while not isload:
            self.browser.reload()
            isload = self.browser.is_element_present_by_id("query_ticket",wait_time=10)
            if not isload:
                time.sleep(30)
                continue

            qt = self.browser.find_by_id("query_ticket")
            qt.click()

        print self.browser.cookies.all()
        flag = False
        while not flag:
            try:
                stations = self.browser.find_by_text(u"预订")
                station = []
                for i in range(11,21):

                    station = stations[i]
                    flag =station.has_class("btn72")
                     
                    if flag:
                        break

                if not flag:
                    qt = self.browser.find_by_id("query_ticket").click()
                    time.sleep(2)
                    continue
                station.click()
                time.sleep(1)
            except Exception as e:
                print  e.message
                
                flag = False

        p1 = self.browser.find_by_xpath("//label[@for='normalPassenger_0']")
        p2 = self.browser.find_by_xpath("//label[@for='normalPassenger_3']")
        print 'p1,p2:%s %s' % (p1,p2)

        if p1.is_empty():
            p1 = self.browser.find_by_id("normalPassenger_0")[0].click()
        else :
            p1[0].click()

        if p2.is_empty():
            p2 = self.browser.find_by_id("normalPassenger_3")[0].click()
        else :
            p2[0].click()
        self.browser.evaluate_script("confirm('抢到票了帅哥,订票吗')")
        time.sleep(15)
        self.browser.find_by_id("submitOrder_id").click()