经验总结:
- 字典的操作不太了解
- 老师的代码没有真正理解,就去码了,导致中途一度停止
- 运行前,保证代码没有明显错误(没有红线等)
- 特别注意有许多缩进的地方,(for try if)
- 一开始码的时候,分析页面(具体步骤) 一定要明确
- 预定车票的标准:根据车次,然后是否是二等或一等(二等优先级高)
- 选择席别的标准:二等或一等(二等优先级高)
selenium定位时 (属性 元素)
显式等待那里EC的方法 (url 属性值 元素)
完整代码:
#爬取12306订单
import csv
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
#驱动器须定义在类的外面,因为python的垃圾回收机制
driver=webdriver.Chrome()
class spider(object):
def __init__(self,from_station,to_station,travel_date,train_rank,passengers):#train_rank={'G106':['M','O']}
self.login_url='https://kyfw.12306.cn/otn/resources/login.html'
self.personer_url='https://kyfw.12306.cn/otn/view/index.html'
self.spider_url='https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
self.confirm_url='https://kyfw.12306.cn/otn/confirmPassenger/initDc'
self.to_station=to_station
self.from_station=from_station
self.travel_date=travel_date
self.travel_rank=train_rank
self.passengers=passengers
self.reader_dict={}
self.__init__csv()#一开始码的时候,这行代码没写
self.number=None
#需要在整个class中调用的属性,先在这里声明
#初始化城市代号
def __init__csv(self):
with open('stations.csv','r',encoding='utf-8') as file_obj:
readers=csv.DictReader(file_obj)
for reader in readers:
name=reader['name']
code=reader['code']
self.reader_dict[name]=code
#登录
def login(self):
driver.get(self.login_url)
WebDriverWait(driver,100).until(
EC.url_contains(self.personer_url)
)
print('登录成功!')
def spider_analyse(self):
driver.get(self.spider_url)
driver.implicitly_wait(3)
driver.find_element_by_id('gb_closeDefaultWarningWindowDialog_id').click()
#设置出发地
fromTag=driver.find_element_by_id('fromStation')
code=self.reader_dict[self.from_station]
driver.execute_script('arguments[0].value="%s"'%code,fromTag)
#设置目的地
toTag = driver.find_element_by_id('toStation')
code = self.reader_dict[self.to_station]
driver.execute_script('arguments[0].value="%s"' % code, toTag)
#设置日期
date=driver.find_element_by_id('train_date')
driver.execute_script('arguments[0].value="%s"' % self.travel_date, date)
#点击查询
time.sleep(3)
query=driver.find_element_by_xpath('//*[@id="query_ticket"]')
driver.execute_script('arguments[0].click()',query)
WebDriverWait(driver,10).until(
EC.presence_of_element_located((By.XPATH,'//tbody[@id="queryLeftTable"]/tr'))
)
trains_list=driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')#定位属性不是datatran的tr标签
is_searched=False
for i in trains_list:
try:
train_list=i.text.replace('\n',' ').split(' ')
# print(train_list)
# print('*'*20)
num=train_list[0]
if num in self.travel_rank:#判断车次是否在self.travel_rank中
# for rank in self.travel_rank[num]:
# if rank=='O':
# pd=train_list[10]
# if pd =='有' or pd.isdigit():
# is_searched=True
# break
# if rank=='M':
# pd=train_list[9]
# if pd =='有' or pd.isdigit():
# is_searched=True
# break
#关键就是这里的解析部分,代码出错集中在这里
pd1=train_list[10]
pd2=train_list[9]
if pd1=='有' or pd1.isdigit() or pd2=='有' or pd2.isdigit():
is_searched=True
if is_searched:
time.sleep(2)
self.number=num
order_btn = i.find_element_by_xpath('//*[@id="ticket_5l0000G106B2_01_10"]/td[13]/a')
order_btn.click()
except:
pass
def confirm_information(self):
WebDriverWait(driver,100).until(
EC.url_contains(self.confirm_url)
)
#确认乘客
labels=driver.find_elements_by_xpath('//ul[@id="normal_passenger_id"]/li/label')
for label in labels:
name=label.text
if name in self.passengers:
label.click()
#确认席别
select=Select(driver.find_element_by_id('seatType_1'))
for i in self.travel_rank[self.number]:
try:
select.select_by_value(i)
except NoSuchElementException:#可能select.select_by_value(i)找不到
continue
else:
break
submit_btn = driver.find_element_by_xpath('//*[@id="submitOrder_id"]')
submit_btn.click()
# 封装了基本的功能
def run(self):
# 登录
self.login()
# 车次以及余票查询并解析
self.spider_analyse()
# 确认乘客信息
self.confirm_information()
def main():
result=spider('上海','北京','2021-05-24',{'G106':['O','M']},['name1','name2'])
result.run()
if __name__ == '__main__':
main()
方法(细节)总结:
1.
driver.execute_script(script, *args)#调用js方法,同时执行javascript脚本
运用场景:
- 拖动拖动条
- (‘https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc’)页面中 设置出发地、日期、查询按钮
报错解决
trains_list=driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')#定位属性不是datatran的tr标签
print(trains_list)
is_searched=False
for i in trains_list:
train_list=i.text.replace('\n',' ').split(' ')

selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
问题及解决:
https://www.cnblogs.com/poloyy/p/12772046.html
https://blog.youkuaiyun.com/seanyang_/article/details/106603322
该博客详细介绍了如何利用Python的Selenium库爬取12306网站的火车票信息,并实现预定功能。首先,通过读取stations.csv文件获取车站代码,然后进行登录、设置出发地、目的地和日期,查询车次。在解析查询结果时,遇到StaleElementReferenceException异常,通过解决方案避免了该问题。最后,根据车次和席别选择,确认乘客信息并提交订单。
952

被折叠的 条评论
为什么被折叠?



