爬虫--04:动态网页爬取(ajax)
程序员文章站
2022-05-05 16:15:44
...
Reptilien - 04: Dynamisches Webcrawlen
selenium
一、selenium背景及介绍
- 我们以前爬取的数据大多是一些静态页面,说白了就是这些数据都在网页源码中。直接解析网页源码就可得到想要的数据。
- 除了静态页面,还有一些页面或者网站的数据不在网页源码中,那么这些数据有可能是通过ajax加载出来的。
什么是ajax? - 是前端的技术
- 页面中有我我们想要的数据,但是网页源码中没有我们需要的数据
- 直接分析ajax接口,通过代码来请求接口,获取真实的数据
- 分析数据接口比较麻烦
- 代码编写比较容易
- 通过selenium和chromedriver来模拟浏览器从而获取数据
- 直接通过selenium来模拟人来获取数据的行为
- 代码量大,代码编写困难
- 下载地址:
- 谷歌浏览器:谷歌浏览器
- 直接分析ajax接口,通过代码来请求接口,获取真实的数据
二、Phantomis快速入门
代码演示:
import time
from selenium import webdriver
# 加载驱动
# 如果驱动没有配置到环境变量,你就需要制定这个驱动的路径
# driver = webdriver.PhantomJS(r'C:\Users\王佳欣的windows\Desktop\phantomjs.exe')
driver = webdriver.PhantomJS()
# 加载网页
driver.get('https://www.baidu.com')
driver.find_element_by_id('kw').send_keys('python')
# 找到su并点击
driver.find_element_by_id('su').click()
time.sleep(2)
# print(driver.page_source) # 得到网页源码
print(driver.current_url) # 查看当前请求的url
driver.save_screenshot('baidu.jpg')
三、selenium快速入门
import time
from selenium import webdriver
# 加载驱动
driver=webdriver.Chrome()
# 加载网页
driver.get('https://baidu.com/') #直接打开了网站
driver.maximize_window() # 窗口最大化
time.sleep(3)
driver.close() # 作用是关闭当前窗口
time.sleep(1)
# python提供的驱动退出
driver.quit()# 作用关闭浏览器
四、定位元素
-
find_element_by_id
:根据id来查找某个元素
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 加载驱动
drvier = webdriver.Chrome()
# 加载网页
drvier.get('https://www.baidu.com/')
time.sleep(2)
# find_element_by_id:根据id来查找某个元素
drvier.find_element_by_id('kw').send_keys('王佳欣') # 第一种方法
# drvier.find_element(By.ID, 'kw').send_keys('李蕊') # 第二种方法
-
find_element_by_class_name
:根据类名查找元素
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 加载驱动
drvier = webdriver.Chrome()
# 加载网页
drvier.get('https://www.baidu.com/')
time.sleep(2)
# find_element_by_class_name:根据类名查找元素
drvier.find_element_by_class_name('s_ipt').send_keys('李蕊') # 第一种方法
drvier.find_element(By.CLASS_NAME, 's_ipt').send_keys('李蕊') # 第二种写法
-
find_element_by_name
:根据name属性的值来查找元素
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 加载驱动
drvier = webdriver.Chrome()
# 加载网页
drvier.get('https://www.baidu.com/')
time.sleep(2)
# find_element_by_name:根据name属性的值来查找元素
# drvier.find_element_by_class_name('wd').send_keys('李蕊') # 第一种方法
drvier.find_element(By.NAME, 'wd').send_keys('李蕊') # 第二种方法
-
find_element_by_tag_name
:根据标签名来查找元素
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 加载驱动
drvier = webdriver.Chrome()
# 加载网页
drvier.get('https://www.baidu.com/')
time.sleep(2)
# find_element_by_tag_name:根据标签名来查找元素
head = drvier.find_element_by_tag_name('head')
print(head)
-
find_element_by_xpath
:根据xpath语法来获取元素
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 加载驱动
drvier = webdriver.Chrome()
# 加载网页
drvier.get('https://www.baidu.com/')
time.sleep(2)
# find_element_by_xpath:根据xpath语法来获取元素
drvier.find_element_by_xpath('//input[@id="kw"]').send_keys('景甜')
-
find_elements_by_css_selector
:根据css来定位元素
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 加载驱动
drvier = webdriver.Chrome()
# 加载网页
drvier.get('https://www.baidu.com/')
time.sleep(2)
# find_elements_by_css_selector:根据css来定位元素
drvier.find_elements_by_css_selector('.s_ipt').send_keys('李蕊')
五、操作表单元素
-
send_keys()
设置内容
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
# 加载驱动
drvier = webdriver.Chrome()
# 加载网页
drvier.get('https://www.baidu.com/')
time.sleep(2)
# send_keys()清空内容
input_Tag = drvier.find_element_by_id('kw')
input_Tag.send_keys('李蕊')
-
clear()
清空内容
from selenium import webdriver
import time
drvier = webdriver.Chrome()
drvier.get('https://www.baidu.com/')
# drvier.find_element_by_id('su') # 找到百度一下按钮
# drvier.find_element_by_id('wrapper').send_keys('王佳欣') # 报错,原因是wrapper不是inpmt标签
# send_keys() 设置内容
input_Tag = drvier.find_element_by_id('kw')
input_Tag.send_keys('李蕊')
time.sleep(3)
# clear()清空内容
input_Tag.clear()
-
click()
点击
from selenium import webdriver
import time
drvier = webdriver.Chrome()
drvier.get('https://www.baidu.com/')
# drvier.find_element_by_id('su') # 找到百度一下按钮
# drvier.find_element_by_id('wrapper').send_keys('王佳欣') # 报错,原因是wrapper不是inpmt标签
# send_keys() 设置内容
input_Tag = drvier.find_element_by_id('kw')
input_Tag.send_keys('李蕊')
time.sleep(3)
# clear()清空内容
# input_Tag.clear()
input_tag = drvier.find_element_by_id('su')
input_tag.click()
六、操作select标签(下拉菜单)
- select元素不能直接点击。因为点击后还需要选中元素。这时候selenium就专门为select标签提供了一个类*from* selenium.webdriver.support.ui *import* Select。将获取到的元素当成参数传到这个类中,创建这个对象。以后就可以使用这个对象进行选择了。
- 操作对象网址:下拉菜单操作练习网址
注意:如果在页面中无法获取页面的元素,你要去查看一下这个页面中是否有iftame标签。
iframe标签(是一个HTML标签)的作用是文档中的文档。
如果有iframe标签,并且嵌套了你要找的元素。那你就要切换一下iframe。
引用select类:
from selenium.webdriver.support.ui import Select
select_tag = Select(drvier.find_element_by_class_name('nojs'))
- 操作方式
1、根据值来选择:select_tag.select_by_value('CA')
2、根据下表索引来选择:select_tag.select_by_index(1)
代码演示:
from selenium import webdriver
from selenium.webdriver.support.ui import Select
drvier = webdriver.Chrome()
# 加载网站
drvier.get('https://www.17sucai.com/pins/demo-show?id=5926')
# 切换iframe (switch_to_frame()该方法已经过时,但是还可以使用)
drvier.switch_to_frame(drvier.find_element_by_id('iframe'))
select_tag = Select(drvier.find_element_by_class_name('nojs'))
# select标签的选择方式有两种
# 1、根据值来选择
select_tag.select_by_value('CA')
# 2、根据下标索引来选择
select_tag.select_by_index(1)
七、操作非select菜单
代码演示:
from selenium import webdriver
import time
from selenium.webdriver.support.ui import Select
driver = webdriver.Chrome()
# 加载网站
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
# 切换iframe (switch_to_frame()该方法已经过时,但是还可以使用)
driver.switch_to_frame(driver.find_element_by_id('iframe'))
# 找到下拉菜单标签
divTag = driver.find_element_by_id('dk_container_country-nofake')
divTag.click()
time.sleep(1)
#
driver.find_element_by_xpath('//*[@id="dk_container_country-nofake"]/div/ul/li[5]/a').click()
注意:
1、检查元素标签是否被iframe嵌套
2、这个标签是否需要点击
3、开始操作表单元素
八、豆瓣登录案例实践
代码实现:
from selenium import webdriver
import time
# 导入驱动
driver = webdriver.Chrome()
# 访问网页
driver.get('https://www.douban.com/')
time.sleep(2)
# 查看网页代码显示有ifame,需要转化
'''
错误总结:缺少iframe切换
Message: no such element: Unable to locate element: {"method":"css selector","selector":".account-tab-account"}
(Session info: chrome=89.0.4389.82)
'''
login_frame = driver.find_element_by_xpath('//*[@id="anony-reg-new"]/div/div[1]/iframe')
driver.switch_to.frame(login_frame)
# 切换登陆方式,选择密码登陆
content = driver.find_element_by_class_name('account-tab-account')
content.click() # 点击
time.sleep(1)
# 定位账号和密码并输入内容
# 输入账号
account = driver.find_element_by_id('username').send_keys('15840039263')
time.sleep(0.5)
# 输入密码
password = driver.find_element_by_id('password').send_keys('789463521')
time.sleep(0.5)
# 点击登陆
driver.find_element_by_xpath('/html/body/div[1]/div[2]/div[1]/div[5]/a').click()
九、鼠标行为链
- 有时候在页面中的操作可能要有很多步,那么这时候可以使用鼠标行为链类ActionChains来完成。比如现在要将鼠标移动到某个元素上并执行点击事件
actions = ActionChains(driver)
actions.move_to_element(inputTag)
actions.send_keys_to_element(inputTag,'python')
actions.move_to_element(submitTag)
actions.context_click()
actions.click(submitTag)
actions.perform()
- 还有更多的鼠标相关的操作
-
click_and_hold(element)
:点击但不松开鼠标。 -
context_click(element)
:右键点击。 -
double_click(element)
:双击。
更多方法请参考:鼠标行为链
代码实现:
-
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
# 定位输入框
input_Tag = driver.find_element_by_id('kw')
# 定位百度按钮
button_Tag = driver.find_element_by_id('su')
# 实例化一个对象
actions = ActionChains(driver)
# 移动鼠标至输入框,输入内容
actions.send_keys_to_element(input_Tag, '李蕊')
time.sleep(2)
# 移动鼠标至点击按钮,点击按钮
actions.move_to_element(button_Tag)
actions.click()
# 提交行为链操作
actions.perform()
# button_Tag.click()
# 可以把按钮点击放在鼠标行为链外面做,可以执行,但是不建议
十、selenum获取cookie
- cookie操作
- 获取所有cookie:
cookies = driver.get_cookies()
- 根据cookie的name获取cookie:
value = driver.get_cookie(name)
- 删除某个cookie:
driver.delete_cookie('key')
QQ空间网址:
- 获取所有cookie:
https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https%3A%2F%2Fqzs.qzone.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&pt_qr_app=手机QQ空间&pt_qr_link=http%3A//z.qzone.com/download.html&self_regurl=https%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http%3A//z.qzone.com/download.html&pt_no_auth=0
代码演示:
# cookie的作用
# 1、反反扒
# 2、模拟登陆
import json
import requests
from selenium import webdriver
import time
driver = webdriver.Chrome()
# 获取百度的cookie
# cookies = driver.get_cookies()
# for cookie in cookies:
# print(cookie)
# 模拟登陆QQ空间
driver.get('https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https%3A%2F%2Fqzs.qzone.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&pt_qr_app=%E6%89%8B%E6%9C%BAQQ%E7%A9%BA%E9%97%B4&pt_qr_link=http%3A//z.qzone.com/download.html&self_regurl=https%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http%3A//z.qzone.com/download.html&pt_no_auth=0')
button = driver.find_element_by_class_name('face')
button.click()
time.sleep(3)
listcookies = driver.get_cookies()
# 保存这个没有解析的cookie
# json.loads() 将一个json类型的字符串转换成python的数据类型
# json.dumps()将一个python类型的数据转换成json类型的数据
# print(type(listcookies))
# print('-'*80)
jsonCookie = json.dumps(listcookies)
# print(type(jsonCookie))
# 保存cookie
# with open('qqzone.json', 'w') as file_obj:
# file_obj.write(jsonCookie)
# 解析cookie--列表推导式
cookie = [item['name'] + '=' + item['value'] for item in listcookies]
cookie_str = '; '.join(item for item in cookie)
headers = {
'cookie': cookie_str,
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_3_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36'
}
# 发起请求
url = 'https://user.qzone.qq.com/1550023517'
html = requests.get(url, headers=headers)
time.sleep(1)
with open('qqzone.html', 'w', encoding='utf-8') as file:
file.write(html.text)
十一、页面等待
- 现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以 Selenium 提供了两种等待方式:一种是隐式等待、一种是显式等待
- 隐式等待:调用driver.implicitly_wait。那么在获取不可用的元素之前,会先等待10秒中的时间
driver.implicitly_wait(10)
代码演示:
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
# time.sleep(2) # 一定要等待n秒
# 隐式等待
driver.implicitly_wait(10) # 如果直接找到元素,就不需要等到n秒,会直接加载
driver.find_element_by_id('kw').send_keys('加油')
- 显示等待:显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。
- 显示等待应该使用selenium.webdriver.support.excepted_conditions期望的条件和selenium.webdriver.support.ui.WebDriverWait来配合完成
代码演示:
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
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
# 显示等待(针对隐式等待进行判断)
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
driver = webdriver.Chrome()
driver.get('https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc')
driver.implicitly_wait(5)
driver.find_element_by_id('gb_closeDefaultWarningWindowDialog_id').click()
# 显示等待
# 等待出发地的ID加载出来,在设置出发地
WebDriverWait(driver,100).until(
EC.text_to_be_present_in_element_value((By.ID,'fromStationText'),'北京'))
# 等待目的地
WebDriverWait(driver, 100).until(EC.text_to_be_present_in_element_value((By.ID, 'toStationText'), '长沙'))
- 一些其他的等待条件
-
presence_of_element_located
:某个元素已经加载完毕了。 -
presence_of_all_elements_located
:网页中所有满足条件的元素都加载完毕了。 -
element_to_be_clickable
:某个元素是可以点击了。
更多请参考:http://selenium-python.readthedocs.io/waits.html
-
十二、selenium操作多页面
- 有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到
代码演示:
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
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
# driver.get('https://www.douban.com/')
driver.execute_script('window.open("https://www.douban.com/")')
# driver.close() # 因为只是打开了豆瓣,但是程序执行一直都是在执行百度页面,对豆瓣页面未执行任何操作
# driver.quit() # 关闭全部
# driver.find_element_by_id('kw').send_keys('王佳欣')
print(driver.current_url)
# 切换窗口
# driver.switch_to_window(driver.window_handles[1])
driver.switch_to.window(driver.window_handles[1])
time.sleep(2)
print(driver.current_url)
十三、selenium案例实践:12306
目标:
1、练习selenium所学知识点
2、如何通过selenium来爬取ajax数据
思路:
1、登陆
总结:
1、面向对象来实现,先搭建好整体的框架
2、驱动不要写在类里面,因为垃圾回收机制,类执行完毕就关闭了
3、如何证明登陆成功,显示等待,加载登陆成功的URL证明登陆成功
2、余票查询
弹框,这弹框比较特殊,不能点击确定按钮,需要定位gb_closeDefaultWarningWindowDialog_id按钮
设置出发地、目的地、出发日期
1、定位
2、找到站点代号
3、通过execute_script()去实现代码的设置
execute_script('arguments[0].value="%s"' % from_station_code, from_station_input)
4、点击确定查询按钮(做了设置)
search_btn = driver.find_element_by_id('query_ticket')
driver.execute_script('arguments[0].click();', search_btn)
3、解析车次列表数据
一、分析页面,得出结论。
这些数据大批早tbody里面的tr标签,然后发现,每个车次tr标签是不含有datrain属性
由于是ajax加载的数据,我们做出显示等待,如果页面中的tr标签加载出来,就证明车次列表数据加载出来
WebDriverWait(driver,1000).until( EC.presence_of_element_located((By.XPATH,'//tbody[@id="queryLeftTable"]/tr'))
)
获取tr标签(车次列表数据)
train_trs = driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
for train_tr in train_trs:
# print(train_tr.text)# 返回selenium对象
二、解析数据
替换和拼接的方式把车次信息的数据放在一个列表中
infos = train_tr.text.replace('\n', ' ').split(' ')
在init方法中初始化了一个用户车次以及席位
先获得车次,做出一个判断,判断这个车次是否在数据里面
进行了想要购买车次以及席位的数据解析
number = infos[0] # 车次
if number in self.trains:
seat_types = self.trains[number]
for seat_type in seat_types:
if seat_type == 'O':
count = infos[9] # 二等座
if count.isdigit() or count == '有':
is_searched = True
elif seat_type == 'M':
count = infos[8] # 一等座
if count.isdigit() or count == '有':
is_searched = True
# 点击预定按钮
if is_searched:
self.select_number = number
order_btn = train_tr.find_element_by_xpath('.//a[@class="btn72"]')
order_btn.click()
break
4、确认乘客和席位
首先确认页面是乘客席位的页面
显示等待
WebDriverWait(driver, 100).until(
EC.url_contains(self.confirm_passengers_url)
)
确认乘客信息
不要点击 框框,直接找人名,人名可能是多个elements
确认席位
席位是select标签, 常规的select标签操作
点击提交按钮
5、核对信息
点击确认按钮
这个按钮他无法点击,我们的解决办法是用了一个死循环,就连续不断的点击,知道点击提交订单
代码实现:
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import csv
driver = webdriver.Chrome()
class TrainSpider(object):
# 定义类属性
login_url = 'https://kyfw.12306.cn/otn/resources/login.html' # 登录
personal_url = 'https://kyfw.12306.cn/otn/view/index.html'# 个人中心
left_ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc' # 车次余票
confirm_passengers_url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc' # 确认乘客信息
# 初始化实例对象
def __init__(self, from_station, to_station, train_data, trains, passengers):
self.from_station = from_station # 目的地
self.to_station = to_station # 出发地
self.train_data = train_data # 出发日期
self.trains = trains # 想要购买的车次 {'G485':['m', 'o']}
self.passengers = passengers # 确认成了姓名
self.station_codes = {}
self.init_station_code() # 初始化站点的方法
# 封装方法
def init_station_code(self):
with open('stations.csv', 'r', encoding='utf-8') as file_obj:
reader = csv.DictReader(file_obj)
for line in reader:
name = line['name']
code = line['code']
self.station_codes[name] = code
# 登陆
def login(self):
# 登陆
driver.get(self.login_url)
# 显示等待
WebDriverWait(driver, 100).until(
EC.url_contains(self.personal_url)
)
print('登陆成功!')
# 查找车票
def search_left_ticket(self):
driver.get(self.left_ticket_url)
driver.implicitly_wait(5)
# 设置按钮,取消弹框(点击X)
driver.find_element_by_id('gb_closeDefaultWarningWindowDialog_id').click()
# 设置出发地
from_station_input = driver.find_element_by_id('fromStation')
from_station_code = self.station_codes[self.from_station]
# 这个input标签是一个hidden状态
driver.execute_script('arguments[0].value="%s"' % from_station_code, from_station_input)
# 设置目的地
to_station_input = driver.find_element_by_id('toStation')
to_station_code = self.station_codes[self.to_station]
# 这个input标签是一个hidden状态
driver.execute_script('arguments[0].value="%s"' % to_station_code, to_station_input)
# 设置出发日期
train_data_input = driver.find_element_by_id('train_date')
driver.execute_script('arguments[0].value="%s"' % self.train_data, train_data_input)
driver.implicitly_wait(3)
# 执行查询按钮
search_btn = driver.find_element_by_id('query_ticket')
driver.execute_script('arguments[0].click();', search_btn)
# 解析车次信息
WebDriverWait(driver,1000).until(
EC.presence_of_element_located((By.XPATH,'//tbody[@id="queryLeftTable"]/tr'))
)
# 得到所有tr标签将不需要的(datatran)做出过滤
train_trs = driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
is_searched = False
for train_tr in train_trs:
# print(train_tr.text) # selenium对象
infos = train_tr.text.replace('\n', ' ').split(' ')
number = infos[0] # 车次
if number in self.trains:
seat_types = self.trains[number]
for seat_type in seat_types:
if seat_type == 'O':
count = infos[9] # 二等座
if count.isdigit() or count == '有':
is_searched = True
elif seat_type == 'M':
count = infos[8] # 一等座
if count.isdigit() or count == '有':
is_searched = True
# 点击预定按钮
if is_searched:
self.select_number = number
order_btn = train_tr.find_element_by_xpath('.//a[@class="btn72"]')
order_btn.click()
break
def confirm_passengers(self):
WebDriverWait(driver, 100).until(
EC.url_contains(self.confirm_passengers_url)
)
# 确认需要购票的乘客 不要选中框框 直接定位人名
passenger_labels = driver.find_elements_by_xpath('//ul[@id="normal_passenger_id"]/li/label')
for passenger_label in passenger_labels:
name = passenger_label.text
if name in self.passengers:
passenger_label.click()
# 确认购买的席位
seat_select = Select(driver.find_element_by_id('seatType_1'))
seat_types = self.trains[self.select_number]
for seat_type in seat_types:
try:
seat_select.select_by_value(seat_type)
except NoSuchElementException:
continue
else:
break
# 提交订单
submit_btn = driver.find_element_by_id('submitOrder_id')
submit_btn.click()
WebDriverWait(driver, 100).until(
EC.presence_of_element_located((By.CLASS_NAME, 'dhtmlx_window_active'))
)
# 确认按钮
btn = driver.find_element_by_id('qr_submit_id')
while btn:
try:
btn.click()
btn = driver.find_element_by_id('qr_submit_id')
except:
break
# 封装整个项目的功能
def run(self):
# 1 登录
self.login()
# 2 车次余票查询
self.search_left_ticket()
# 3、确认乘客和车次信息
self.confirm_passengers()
def main():
spider = TrainSpider('北京', '长沙', '2021-03-25', {'G485':['M','O']})
spider.run()
if __name__ == '__main__':
main()
下一篇: 爆囧,生活总是那么的醉人