车票 时间是2019年的哈 (记笔记)"/>
12306预售车票 时间是2019年的哈 (记笔记)
先说明一下哈,这个是从视频上面我搬运的哈,视频时间2019的,代码应该没用
我只是单纯的做笔记哈,写一哈自己的感受哈
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdrivermon.by import By
from selenium.webdriver.support.select import Select
from seleniummon.exceptions import NoSuchElementException,ElementNotVisibleException #这是导入一个异常哦
import csvdriver=webdriver.Chrome() #将driver 设置为全局变量 是因为 如果放在里面 driver会随着 对象的销毁 而 被销毁class TrainSpider(object):login_url='登陆界面url' #定义在这里 可以随时 改变 urlpresonal_url='这里是登陆后跳转的url 来判断是否登陆成功'left_ticket_url='车次余票url'confirm_passengner_url='确认乘客页面的url'def __init__(self,from_station,to_station,train_date,trains,passengers):''':param from_station: 起始站:param to_station: 目的站:param train_date: 出发目标:param trains: 需要购买车次 是一个字典 传入实例:{'G529':['M','O'],'G403':{'M','O'}}:param passengers: 乘客的姓名 是一个列表 传入实例: ['乘客名','乘客名','乘客名',]'''self.from_station=from_stationself.to_station=to_stationself.train_date=train_dateself.trains=trainsself.passengers=passengers #将 传过来的 变量 保存在对象上self.selected_seat=Noneself.selected_number=None #自己定义类中全局变量 定义了 车号 和 席位#self.driver=webdriver.Chrome() 放在里面可以方便 输出 有联想self.station_codes={} #定义(在外面而非 函数里里面) 变量 因为 车票 查询 需要self.init_station_code() #初始化站点所对应的代号 一开始自动运行函数def init_station_code(self): #这个是得到站点的代号 为了输入车票的起始点with open('z stations.csv', 'r', encoding='utf-8') as fp:reader = csv.DictReader(fp)for line in reader:name = line['name']code = line['code']self.station_codes[name] = codedef login(self):driver.get(self.login_url)#等待url 是否变为个人中心的url 来判断 是否登陆成功 (设置显示等待)WebDriverWait(driver,1000).until(#判断条件#EC.url_to_be(self.presonal_url) 变成这个urlEC.url_contains(self.presonal_url) #包含这个url)print('登陆成功!')def search_left_ticket(self):driver.get(self.left_ticket_url)#1.起始站代号设置from_station_input = driver.find_element_by_id("fromStation")from_station_code=self.station_codes[self.from_station]'''self.station_codes[name] = code 因为这个 所以可以 返回 地点 代号'''driver.execute_script(f"arguments[0].value='{from_station_code}'" , from_station_input) #设置值到框框#这种josnscript 设置值 一切情况 都 适用'''因为type 是 hidden 被隐藏 所以需要采用josnscript代码来实现arguments 代表 你给函数 传的参数 是一个列表"arguments[0].value='%s'" % from_code 是 json代码from_station_input 传的参数 如果有其他的参数 都 放在 arguments中'''#2.终点站代号设置to_station_input = driver.find_element_by_id("toStation")to_station_code = self.station_codes[self.to_station]driver.execute_script(f"arguments[0].value='{to_station_code}'", to_station_input)#3.设置时间train_date_input = driver.find_element_by_id("train_date")driver.execute_script(f'arguments[0].value={self.train_date}',train_date_input)#4.执行查询操作search_btn=driver.find_element_by_id('query_ticket')search_btn.click()#5.解析车次信息WebDriverWait(driver,1000).until(EC.presence_of_element_located((By.XPATH,"//tbody[@id='queryLeftTable']/tr")))train_trs=driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')#tr[not(@datatran)] 可以排除 含有 datatran 条件的 tris_searched=Falsewhile True: #这个 死循环 是为了多次查询 因为有些票时间没到 还在准备预售 之前不加这个 就只查询一次就没了for train_tr in train_trs:#print(train_tr.text)infos=train_tr.text.repalce('\n',' ').split(' ')#print(infos)number=infos[0]if number in self.trains: #判断key(车号)是否在 字典 trainsseat_types=self.trains[number] #如果有key(车号) 获得车号需要的 seat_typesfor seat_type in seat_types: #遍历这个车号的所有 信息#是否有二等座if seat_type == 'O': #遍历是否有 座位为二等座的 就可以进行下面的判断二等座是否有count=infos[9]if count.isdigit() or count == '有':is_searched=Truebreak#是否有一等座elif seat_type == 'M':count=infos[8]if count.isdigit() or count == '有':is_searched=Truebreakif is_searched:self.selected_number=numberorder_btn = train_tr.find_element_by_xpath('.//a[@class="btn72"]')order_btn.click()returndef confirm_passengers(self):#1.判断是否变为确认乘客的url页面 和 等待 确认购买乘客信息的出现WebDriverWait(driver,1000).until(EC.url_contains(self.confirm_passengner_url))#先等待乘客标签显示出来WebDriverWait(driver,1000).until(EC.presence_of_element_located((By.XPATH,'//ul[@id="normal_passenger_id"]/li/label')))#2.确认需要购买车票的乘客passenger_labels=driver.find_elements_by_xpath('//ul[@id="normal_passenger_id"]/li/label')for passenger_label in passenger_labels:name=passenger_label.textif name in self.passengers:passenger_label.click()#3.确认需要购买的席位信息seat_select=Select(driver.find_element_by_id('seatType_1'))seat_types=self.trains[self.selected_number] #是一个列表'''self.trains[self.selected_number] 因为传过来的trains 是一个字典 所以可以通过key索引'''for seat_type in seat_types:try:self.selected_seat =seat_typeseat_select.select_by_value(seat_type)except NoSuchElementException: #捕捉异常continue #continue 就是 下次循环下一个座次else:break #如果第一次就找到啦 就退出循环#等待 提交订单按钮可以被点击WebDriverWait(driver,1000).until(EC.element_to_be_clickable((By.ID,'submintOrder_id')))submit_btn=driver.find_element_by_id('submintOrder_id')submit_btn.click()#等待 模拟对话框出现 和 确认按钮可以点击WebDriverWait(driver,1000).until(EC.presence_of_element_located((By.CLASS_NAME,'dhtmlx_window_active')))#确认按钮可以点击WebDriverWait(driver,1000).until(EC.element_to_be_clickable((By.ID,"qr_submit_id")))submit_btn=driver.find_element_by_id("qr_submit_id")#submit_btn.click() #有可能 点击一次并不会出来 所以采用下面的 暴力循环点击while submit_btn:try:submit_btn.click()submit_btn = driver.find_element_by_id("qr_submit_id")except ElementNotVisibleException:# 会报这个错 ElementNotVisibleException 说明页面已经换了 即代表成功了 就可以退出循环breakprint(f"恭喜!成功抢{self.selected_number}次列车{self.selected_seat}席位,请在30分钟内完成付款!" )def run(self): # 一切相关的就放在这 相当于总控制者#1.登录 () 定义一个 函数一个self.login()#2.车次余票查询self.search_left_ticket()#3.确认乘客和车次信息self.confirm_passengers()def main():# 9:商务座,M:一等座,O:二等座,3:硬卧,4:软卧,1:硬座from_station=input('请输入出发地:')to_station=input('请输入目的地:')train_date=str(input('请输入出发时间(请按照如下格式输入时间: 2020-13-14):'))train_number=input('你准备乘坐的车号(车号实例:G520):')train_seat=input ("请输入座位级别(输入实例:m o):").split()train={train_number:train_seat}passenger_names=input ("输入名字(输入实例:小明 小红):").split()spider=TrainSpider(from_station,to_station,train_date,train,passenger_names)spider.run()if __name__ == '__main__':main()
- 这里对 类中的 参数的传入和设置 有了新的 理解 之前没么怎么使用过类
对参数的 传入 和 设置
传入 我自己的理解 就相当于 c语言中 对函数传值一样那种 只不过在类中使用 需要初始化(self.from_station=from_station
我也不知道这个是不是叫初始化)
设置嘛 就是平时一样的 就使用的时候 加个self
def __init__(self,from_station,to_station,train_date,trains,passengers):''':param from_station: 起始站:param to_station: 目的站:param train_date: 出发目标:param trains: 需要购买车次 是一个字典 传入实例:{'G529':['M','O'],'G403':{'M','O'}}:param passengers: 乘客的姓名 是一个列表 传入实例: ['乘客名','乘客名','乘客名',]'''self.from_station=from_stationself.to_station=to_stationself.train_date=train_dateself.trains=trainsself.passengers=passengers #将 传过来的 变量 保存在对象上self.selected_seat=Noneself.selected_number=None #自己定义类中全局变量 定义了 车号 和 席位#self.driver=webdriver.Chrome() 放在里面可以方便 输出 有联想self.station_codes={} #定义(在外面而非 函数里里面) 变量 因为 车票 查询 需要self.init_station_code() #初始化站点所对应的代号 一开始自动运行函数
对于 driver.execute_script(f"arguments[0].value='{from_station_code}'" , from_station_input)
这个认识
driver.execute_script(f"arguments[0].value='{from_station_code}'" , from_station_input) #设置值到框框#这种josnscript 设置值 一切情况 都 适用'''因为type 是 hidden 被隐藏 所以需要采用josnscript代码来实现arguments 代表 你给函数 传的参数 是一个列表"arguments[0].value='%s'" % from_code 是 json代码from_station_input 传的参数 如果有其他的参数 都 放在 arguments中'''
3.以及 处处都需要显示等待的条件 思维
#1.判断是否变为确认乘客的url页面 和 等待 确认购买乘客信息的出现WebDriverWait(driver,1000).until(EC.url_contains(self.confirm_passengner_url))#先等待乘客标签显示出来WebDriverWait(driver,1000).until(EC.presence_of_element_located((By.XPATH,'//ul[@id="normal_passenger_id"]/li/label')))
4.以及输出列表的方式
passenger_names=input ("输入名字(输入实例:小明 小红):").split()
更多推荐
12306预售车票 时间是2019年的哈 (记笔记)
发布评论