持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
前言
今天没有啥特别的,还是在构想吧,今天就先把这个以前写的博文整理一下吧。想想时间真快,这个篇整理的博客还是我高考结束后写的,想想,两年过去了。
Selenium与python爬虫(一)【安装与定位元素】
selenium配置
首先搞清楚selenium是干嘛的。这个东东其实是用来做自动化网页测试的。就是模拟人类行为像鼠标键盘之类的操作,与之前使用requests等的区别在于,这玩意是一个动态获取的行为。不是单纯的一次性的获取网页源代码,可以后不断获取,最简单的在爬虫中的应用就是移动滑块验证。
下载selenium可以直接使用pip下载安装指令。
配置浏览器,下载相应的webdriver版本即可
下面以chrome为例
1.查看chrome版本
2.下载 chromedriver
下载网址
3.将下载好的chromedriver.exe放入文件中
这里有两个选择;1.放置与python的script目录下
或者放置于另一个指定目录内(英文路径内)
验证安装成功
from selenium import webdriver
drive=webdriver.Chrome()
#drive=webdriver.Chrome(executable_path=指定路径)
drive.get('https://www.baidu.com/')
弹出窗口
基础操作
首先要声明的是selenium有些方法是很长的乍一眼看上去很复杂,其实简单的鸭皮。 1.打开一个网页 2.定位一个元素 3.实现简单的点击操作
打开网页
drive.get('https://www.baidu.com/')
定位元素
定位元素的话操作手段就比较多了。 最主要的是先分两大类,一个是获取当个对象,一个是获取多个对象。 比如;
InputTag=drive.find_element_by_name('wd')
获取一个(第一个)
InputTag=drive.find_elements_by_name('wd')
获取全部
在代码中_by_name()的意思就是通过name的值来定位
此外还有很多方法。如图
必要时直接通过xpath语法定位
对象操作
这里要注意一下的是我么只是单纯的通过定位获取到了相应元素, 因此我们可以进行的操作只是点击,发送之类的操作。对于较复杂的操作只能通过鼠标对象操作。比如;单击,双击,右击,拖拽。。。 send_keys()发送相应的值 click()点击 clear()清空
实例操作(演示)
目标在百度页面输入python并且点击搜索
现在我们已经知道了具体的元素定位。
下面分别使用通过name定位和xpath定位
from selenium import webdriver
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
############
InputTag=drive.find_element_by_name('wd')
InputTag.send_keys('python')
############
SubmitBut=drive.find_element_by_xpath('//input[@type="submit" and @value="百度一下"]')
SubmitBut.click()
效果如下
精简写法
像上面那样使用代码较为冗长,这是可以考虑缩减写法,并且此写法在后面会有小惊喜。 区别;也没啥就是再使用了一个方法包装了一下 1.导入
from selenium.webdriver.common.by import By
2.缩减代码
from selenium import webdriver
from selenium.webdriver.common.by import By
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
############
InputTag=drive.find_element(By.NAME,'wd')
InputTag.send_keys('python')
############
SubmitBut=drive.find_element(By.XPATH,'//input[@type="submit" and @value="百度一下"]')
SubmitBut.click()
页面关闭与浏览器
1.只是关闭上一个页面
drive.close()
2关闭浏览器
drive.quit()
selenium与python爬虫(二)【等待与多窗口(目标1)】
目标明确
1.我们的目标首先是打开一个网页 2.定位其中一个元素或者多个执行对应的操作 3.根据需求对该元素进行操作和获取,对获取的数据进行处理 4.之后再根据需求再打开更多的网页重复之前的操作 总体而言,我们的步骤分为这四大步,但是每一步又可以细分为几个小步。那么现在我们就来实现目标一
打开网页(细分一,开网页)
这个在上一篇博客已经有写过。 使用get()方法打开网页
from selenium import webdriver
drive=webdriver.Chrome()
drive.maximize_window()#窗口最大化
drive.get('https://www.baidu.com/')
print(len(drive.page_source))#page_source是返回的网址源码
打开网页(细分二,开分页)
误区演示;当我们使用get()方法时打开的是一个全新的网页 例如;
from selenium import webdriver
drive=webdriver.Chrome()
drive.maximize_window()#窗口最大化
drive.get('https://www.baidu.com/')
drive.get('https://123.sogou.com/')
print(len(drive.page_source))#page_source是返回的网址源码
表面上看打开了两个网页但是实际上最后只有一个网页被打开,相当于关掉了上一个网页,打开了下一个网页。但是在做实际的爬取工作时往往是从一个页面跳转到另一个再跳转回来的。也就是我们希望浏览器呈现这样的状态
再原来的基础上再开一个。
正确姿势
1.使用execute_Script()方法切换网页
2.获取窗口的位置(第几个窗口)
3.使用switc_to_window()切换
代码如下;
from selenium import webdriver
drive=webdriver.Chrome()
drive.maximize_window()#窗口最大化
drive.get('https://www.baidu.com/')
print(len(drive.page_source))#page_source是返回的网址源码
drive.execute_script("window.open('https://123.sogou.com/')")
#drive.window_handles获取窗口通过索引定位窗口
drive.switch_to_window(drive.window_handles[1])
打开网页(细分三,等待加载)【隐式等待】
打开一个网页可以很快但是加载一个网页可不一定。如果说打开一个网页之后还没有加载出来相应的元素就贸然去定位元素是绝对会报错的。 1.所谓隐式等待其实就相当于导入time模块使用sleep()方法。但是比较特殊的是selenium比较复杂(里面各种线程齐飞直接使用sleep()是没有用的,况且他自己本身还要运行加载。) 直接使用方法implicitly_wait() 下面使用上一篇博客的例子
from selenium import webdriver
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
############
drive.implicitly_wait(10)#等待十秒
InputTag=drive.find_element_by_name('wd')
InputTag.send_keys('python')
############
SubmitBut=drive.find_element_by_xpath('//input[@type="submit" and @value="百度一下"]')
SubmitBut.click()
打开网页(细分三,等待加载)【显式等待】
这玩意就稍微智能一点,可以加入判断条件不会死等。当然导入的东东也比较多。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as Ec
#Ec加入判断条件的东东
代码如下;
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as Ec
drive=webdriver.Chrome()
drive.maximize_window()
drive.get('https://www.baidu.com/')
drive.implicitly_wait(10)
print(len(drive.page_source))
try:
InputTag=WebDriverWait(drive,10).until(
Ec.presence_of_element_located((By.ID,'kw'))
)
#等待十秒要是提前出现了就不等了
InputTag.send_keys('python')
except Exception as error:
print(error)
Enter=drive.find_element(By.ID,'su')
Enter.click()
print(len(drive.page_source))
此外判断条件还有很多
相信各位英文都不会太差。
最终演示的代码
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as Ec
drive=webdriver.Chrome()
drive.maximize_window()
drive.get('https://www.baidu.com/')
drive.implicitly_wait(10)
print(len(drive.page_source))
try:
InputTag=WebDriverWait(drive,10).until(
Ec.presence_of_element_located((By.ID,'kw'))
)
InputTag.send_keys('python')
except Exception as error:
print(error)
Enter=drive.find_element(By.ID,'su')
Enter.click()
print(len(drive.page_source))
'''切换网页'''
drive.execute_script("window.open('https://123.sogou.com/')")
drive.switch_to_window(drive.window_handles[1])
此外这里还有一个小细节
这个也就是为什么使用selenium获取Ajax的内容了,当然你直接找到接口破解传入的参数也行。
selenium与python爬虫(三)【定位与操作(目标2)】
selenium的定位(定位书写)
在初始的selenium中介绍过selenium的定位,实际上关于selenium的定位就是那么简单。即通过elemen的属性的值,id等进行定位,甚至可以直接使用xpath而这也是本人最喜欢的方法之一。 关于定位的写法我这里分为两大类
- 简写方式
- 常规方式 二者在效果上一至只是有时候简写模式会让代码看起来更舒适,同时在有些时候只能使用简写模式。 关于二者具体区别,可以查看关于selenium的第一篇博客。 博客地址
常规
from selenium import webdriver
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
############
InputTag=drive.find_element_by_name('wd')
InputTag.send_keys('python')
############
SubmitBut=drive.find_element_by_xpath('//input[@type="submit" and @value="百度一下"]')
SubmitBut.click()
简写
from selenium import webdriver
from selenium.webdriver.common.by import By
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
############
InputTag=drive.find_element(By.NAME,'wd')
InputTag.send_keys('python')
############
SubmitBut=drive.find_element(By.XPATH,'//input[@type="submit" and @value="百度一下"]')
SubmitBut.click()
只能使用简写的情况(示例) 具体可以查看selenium的第二篇博客 博客地址
try:
InputTag=WebDriverWait(drive,10).until(
Ec.presence_of_element_located((By.ID,'kw'))
)
InputTag.send_keys('python')
except Exception as error:
print(error)
selenium的定位(元素类操作)
搜索栏
这玩意是啥就不用多说了,下面以百度为例子。 这玩意可以点击,可以发送内容。
from selenium import webdriver
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
############
InputTag=drive.find_element_by_name('wd')
InputTag.send_keys('python')#发送内容
#InputTag.click()
############
SubmitBut=drive.find_element_by_xpath('//input[@type="submit" and @value="百度一下"]')
SubmitBut.click()#点击
标签,按钮
这类element基本上只有click()点击,如果要使用双击,右键等操作必须使用鼠标操作。 单纯的定位好后所执行的操作就是click()或者send_keys() 上面有例子就不再阐述。
勾选栏
就那玩意。也简单
1.先定位
2.单点击勾选,双点击取消。
下面使用伪代码来演示
choice_click_=drive.find_element_by_xpath('定位')
choic_click_.click()#点击勾选
choic_click_.click()#点击勾选+1取消
多选框(select)
这个没有找到相应的网站来演示,所以使用伪代码来演示。
大概这个样子
1.导入Select 2.定位select 3.将定位好的select放入Select中 4.再次定位选项
from selenium.webdriver.support.ui import Select
''''''
selectbut=drive.find_element(定位)
SelectBut=Select(selectbut)
first_select=SelectBut.select_by_index(0)#通过索引
first_select=SelectBut.select_by_value(值)#通过值
first_select=SelectBut.select_by_text(文本)#通过文本
之后就会自动地去选择到相应地选项(默认点击一次,如果是链接就会自动进去)
取消所有选择(如果是一个点击勾选地话并且那玩意默认已勾选地话)
SelectBut.deselesct_all()
selenium与python爬虫(四)【鼠标行为(目标3)】
selenium的鼠标点击
鼠标地点击可以分为
- 单击 click()
- 双击 double_click()
- 右击 context_click()
- 点击鼠标左键,不松开 click_and_hold() 现在以百度地那个例子为例
from selenium import webdriver
from selenium.webdriver.common.by import By
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
SubmitBut=drive.find_element(By.XPATH,'//input[@type="submit" and @value="百度一下"]')
SubmitBut.click()
现在使用鼠标
1.导入相关库
2.创建鼠标对象
3.实现相关操作
现在我们使用代码实现这么一个功能(右击百度搜索标签)
代码如下
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains#####
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
SubmitBut=drive.find_element(By.XPATH,'//input[@type="submit" and @value="百度一下"]')
action_mouse=ActionChains(drive)######
action_mouse.move_to_element(SubmitBut).context_click().perform()######
搞定
鼠标移动
drag_and_drop(A, B) 将A拖拽到B
drag_and_drop_by_offset(source, x, y) 将A拖拽到某个位置
move_by_offset(x, y) 鼠标从当前位置移动到某个坐标
move_to_element(to_element) 鼠标移动到某个元素
move_to_element_with_offset(A, x, y)移动到距A元素(左上角坐标)多少距离的位置
perform() 执行链中的所有动作
release(on_element=None) 在某个元素位置松开鼠标左键(和clic_and_hold()连用)
send_keys('python') 通过键盘发送’python‘ 可输入字符,模拟按压字母键
send_keys_to_element(At, ‘python') 向A发送’python'
下面举几个例子,其他的操作方法是一样的 (由于找不到相应的网站来举例子,现在使用伪代码来演示,后面再写一个实例。)
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.maximize_window()
driver.get('URL')
dragger = driver.find_element_by_id('dragger') # 被拖拽元素
A = driver.find_element_by_xpath('') # 目标A
B = driver.find_element_by_xpath('') # 目标B
action = ActionChains(driver)
action.drag_and_drop(dragger, A).perform() # 移动dragger到目标A
action.click_and_hold(dragger).release(A).perform() # 效果与上句相同,也能起到移动效果
action.click_and_hold(dragger).move_to_element(A).release().perform() # 效果与上两句相同,也能起到移动的效果
# action.drag_and_drop_by_offset(dragger, 400, 150).perform() # 4.移动到指定坐标
action.click_and_hold(dragger).move_by_offset(400, 150).release().perform() #与上一句相同,移动到指定坐标
常用警醒
1.drag_and_drag_by_offset(A,x,y)一般用于滑块验证啥的 2.move_by_offset(x,y) 的原点坐标是以上一次移动的终点为下一次的原点的,即坐标具有累加效应。
键盘事件
这个和鼠标是一起的,有时候需要使用某些按键比如’空格‘键。 key_down(value, element=None) 按下某个键盘上的键
key_up(value, element=None) 松开某个键
下面是具体的例子。(伪代码)
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.maximize_window()
driver.get('URL')
dragger = driver.find_element_by_id('dragger') # 被拖拽元素
A = driver.find_element_by_xpath('') # 目标A
INPUT = driver.find_element_by_xpath('') # 目标B
action = ActionChains(driver)
action.key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform() # ctrl+a
action.key_down(Keys.CONTROL).send_keys('c').key_up(Keys.CONTROL).perform() # ctrl+c
action.key_down(Keys.CONTROL,INPUT).send_keys('v').key_up(Keys.CONTROL).perform() # ctrl+v
action.move_to_element(INPUT).key_down(Keys.CONTROL).send_keys('v')key_up(Keys.CONTROL).perform()#和上一个一样 ctrl+v
真正的实例
生死狙击登陆实例(不要笑很严肃) 下面演示一下如何获取坐标
代码如下;
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver=webdriver.Chrome()
driver.maximize_window()
enter_url='https://ssjj.4399.com/'
driver.get(enter_url)
actions=ActionChains(driver)
actions.move_by_offset(550,370).click().send_keys('865989840')
actions.move_by_offset(-550,-370)#归位
actions.move_by_offset(550,400).click().send_keys('mima')
actions.move_by_offset(-550,-400)
actions.move_by_offset(530,475).click()
actions.move_by_offset(-530,-475).perform()
actions.move_by_offset(400,350).click().perform()
效果
(顺便签了个到,chrome现在是不支持flash的,如果没有特殊修改的话是没法自动运行flash的,当然你可以修改,搜索一些微信公众号有教程,这楼里就不阐述了。)
selenium与python爬虫(五)【数据处理(目标四)百度翻译实例】
selenium获取网页源代码的区别
这个第一篇博客就已经写过了。但是这里要重申一下的是他的区别
drive=webdriver.Chrome()
drive.get('https://www.baidu.com/')
print(drive.page_source)
page_source是selenium返回的源代码,但是这里和我们通过requests库获取的区别在于。selenium是可以动态获取不断更新的,selenium更像是一个浏览器,她可以像浏览器一下直接获取Ajax里面显示的页面。
比如使用requests时爬取拉钩网
找不到,但是。
我们却可以再element里面找到,这是因为这玩意被加载到浏览器里面了所以selenium自然可以获取到,但时使用requests只是访问了其中一个网址,获取到的自然也就只有一个。关系如图,如果时使用requests访问的只有url_1而内容在url_2
实例
from selenium import webdriver
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as Ec
drive=webdriver.Chrome()
drive.get('https://fanyi.baidu.com/?aldtype=16047#zh/en')
def set_word():
try:
InputTag=WebDriverWait(drive,10).until(
Ec.presence_of_element_located((By.ID,'baidu_translate_input'))
)
InputTag.send_keys('你好')
except Exception as e :
print(e)
set_word()#百度会刷新一次所以要两次
time.sleep(2)
set_word()
print(drive.page_source)
目前结果(返回了Hello)
而对比以前(使用requests)
之后我们将他放在etree里面使用xpath或者直接使用re提取出翻译结果即可
声明
由于时间有限
所以后续的代码就不写了,比较简单。好了基本上selenium需要使用的其实也就那么多。