一、摘要
突发奇想想读取12306的车票信息,最开始想用requests,但是突然又想试试selenium的无界面浏览器。有部分正则没调好,写好就懒得调了。
套用我师傅的话就是:我凭本事写的bug,凭什么要改!
二、方案思路
url = https://kyfw.12306.cn/otn/leftTicket/init
1、模拟用户是怎么查车票信息、然后通过selenium去操作浏览器。
2、最后输出字典。
三、源码
#-*- coding:utf-8 -*-#__anthor__:"Klay Zhu"#date: 2018/9/7import refrom selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditionsfrom selenium.webdriver.common.by import Byfrom time import sleepclass TicketQuery: """ 查询12306车票 """ def __init__(self,**parame): try: self.obj_driver = parame["browser"] except: #无界面浏览器 options = Options() options.add_argument('-headless') # 无头参数 self.obj_driver = webdriver.Chrome(executable_path='chromedriver', chrome_options=options) self.str_from_station = parame["fromStation"] #出发地 self.str_to_station = parame["toStation"] #目的地 self.str_train_date = parame["trainDate"] #出发日 def waitElement(self,value,way=By.ID): """等待忍耐""" if WebDriverWait(self.obj_driver, 10).until(expected_conditions.visibility_of_element_located((way,value))): return True def __jsOperation(self,element_id,value): """通过js操作界面元素""" if self.waitElement(element_id): js_value = 'document.getElementById("{}").value="{}"'.format(element_id,value) self.obj_driver.execute_script(js_value) def __getStation(self,element_id,string): """对input选择框进行选择""" self.obj_driver.find_element_by_id(element_id).clear() self.obj_driver.find_element_by_id(element_id).click() self.obj_driver.find_element_by_id(element_id).send_keys(string) __a = self.obj_driver.find_elements_by_class_name("ralign") for i in __a: if i.text == string: i.click() break #正则没调好 懒得调了 pattern = r"<>]*> <>]*>\s*
四、遇到的问题
1、日期输入,因为控件原因不能直接输入,使用JavaScript对元素进行操作。
from selenium import webdriverdriver = webdriver.Chrome()element_id = "id" #idvalue = "value" #给该标签设定的值 js_value = 'document.getElementById("{}").value="{}"'.format(element_id, value)#拼接成JavaScript代码driver.execute_script(js_value)
2、input选择框,类似百度搜索这种使用ajax异步出来的数据。
from selenium import webdriverelement_id = "fromStationText"string = "北京"driver = webdriver.Chrome()driver.find_element_by_id(element_id).clear() # 清除原有的值driver.find_element_by_id(element_id).click() # 点击,使输入框获取焦点driver.find_element_by_id(element_id).send_keys(string) # 输入值o_InputSelect=driver.find_elements_by_class_name("ralign")# 获取局部刷新的数据,然后循环比对文字for i in o_InputSelect: # 注意:如果不用这种方法,用输入回车来选择会出现 要选北京结果选到北京西 这类的 if i.text == string: i.click() break
3、使用全局(嵌套)变量dict作为append到局部list里面,幸好出现问题就马上反应过来是深浅拷贝的问题,详情请百度!
class demo: dic={ "name":"", "age":"", "data":[], } def f(self): lis = [] for i in range(3): print("dic的地址:",id(f.dic)) self.dic["name"]="name"+str(i) self.dic["age"]="age"+str(i) self.dic["data"].append(i) lis.append(self.dic) return lisif __name__ == '__main__': f = demo() print("最后结果:",f.f()) # dic的地址: 1469349351640 # dic的地址: 1469349351640 # dic的地址: 1469349351640 # 最后结果: [{'name': 'name2', 'age': 'age2', 'data': [0, 1, 2]}, {'name': 'name2', 'age': 'age2', 'data': [0, 1, 2]}, # {'name': 'name2', 'age': 'age2', 'data': [0, 1, 2]}]