一.基础
1.定义
- 自动化测试工具,支持多种浏览器。爬虫中主要用来解决JavaScript渲染的问题
- 便捷地获取网站中动态加载的数据
- 便捷实现模拟登录
2.使用流程
- 环境安装:pip install selenium
- 下载一个浏览器的驱动程序
- 实例化一个浏览器对象:bro = webdriver.Chrome(executable_path='./chromedriver')
- 编写基于浏览器自动化的操作代码
二.常用操作
1.元素定位
获取单个元素
driver.find_element(By.ID,"inputOriginal")
driver.find_element(By.CSS_SELECTOR,"#inputOriginal")
driver.find_element(By.TAG_NAME,"div")
driver.find_element(By.NAME,"username")
driver.find_element(By.LINK_TEXT,"下一页")
获取多个元素
driver.find_elements(By.ID,"inputOriginal")
driver.find_elements(By.CSS_SELECTOR,"#inputOriginal")
driver.find_elements(By.TAG_NAME,"div")
driver.find_elements(By.NAME,"username")
driver.find_elements(By.LINK_TEXT,"下一页")
2.内容获取
- size:返回元素大小
- text:获取元素的文本
- title:获取页面title
- current_url:获取当前页面url
- get_attribute:获取属性值
- is_display():判断元素是否可见
- is_enabled():判断元素是否可用
driver = webdriver.Chrome("./chromedriver.exe")
#加载有道翻译页面
driver.get("https://fanyi.youdao.com/")
print(driver.title)
print(driver.current_url)
#获取输入框
transMachine = driver.find_element(By.ID,"transMachine")
print(transMachine.size)
print(transMachine.text)
print(transMachine.get_attribute("href"))
print(transMachine.is_displayed())
print(transMachine.is_enabled())
3.窗口操作
- maximize_window():最大化 → 模拟浏览器最大化按钮
- set_window_size(100,100):浏览器大小 → 设置浏览器宽,高(像素点)
- set_window_position(300,200):浏览器位置 → 设置浏览器位置
- back():后退 → 模拟浏览器后退按钮
- forward():前进 → 模拟浏览器前进按钮
- refresh():刷新 → 模拟浏览器F5刷新
- close():关闭 → 模拟浏览器关闭按钮(关闭单个窗口)
- quit():关闭 → 关闭所有webDriver启动窗口
4.元素等待
翻页获取每页元素
from selenium import webdriver
from selenium.webdriver.common.by import by
from selenium.webdriver.common.keys import keys
driver = webdriver.Chrome("./chromedriver.exe")
#加载当当网
driver.get("https://www.dangdang.com/")
#获取输入框
key = driver.find_element(By.ID,"key_S")
key.send_keys("科幻")
#获取搜索框,点击搜索
search = driver.find_element(By.CSS_SELECTOR,".search .button")
search.click()
#获取商品标题及价格
for i in range(5):
shoplist = driver.find_elements(By.CSS_SELECTOR,"./shoplist li")
for li in shoplist:
print(li.find_element(By.CSS_SELECTOR,"a").get_attribute("title"))
#获取下一页按钮
next = driver.find_element(By.LINK_TEXT,"下一页")
next.click()
现在的网页越来越多采用了Ajax技术,这样程序便不能确定何时某个元素完全加载出来了,如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常
为了避免这种元素定位困境而且会提高产生ElementNotVisibleException的概率,selenium提供了两种等待方式:显式等待和隐式等待
隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行
显式等待:指定某个条件,然后设置最长等待时间,如果在这个时间还没有找到元素,那么便会抛出异常了
显式等待使用WebDriverWait完成
webDriverWait(driver,timeout,poll_frequency=POLL_FREQUENCY,ignored_exception=None)
- driver:所创建的浏览器driver
- timeout:最长时间长度(默认单位:秒)
- poll_frequency:间隔检测时长,默认0.5秒
- ignored_exception:方法调用中忽略的异常,默认只抛出:找不到元素的异常
until:直到调用的方法返回值为True
until(method,message='')
- method:excepted_conditions库中定义的方法
- message:自定义报错信息
隐式等待:比较简单,就是设置全局元素查找到超时时间
implicity_wait(time_to_wait)
设置的时间单位为秒,例如implicity_wait(30),意思是超过30秒没有定位到一个元素,程序就会报错抛出异常,期间会一直轮询查找定位元素
三.页面操作
1.鼠标操作
- context_click():右击 → 模拟鼠标右键点击效果
- double_click():双击 → 模拟鼠标双击效果
- drag_and_drop():拖动 → 模拟鼠标拖动效果
- move_to_element():悬停 → 模拟鼠标悬停效果
- perform():执行 → 用来执行以上所有的鼠标方法
2.键盘操作
- send_keys(Keys.BACK_SPACE):删除键
- send_keys(Keys.SPACE):空格键
- send_keys(Keys.TAB):制表键
- send_keys(Keys.ESCAPE):回退键
- send_keys(Keys.ENTER):回车键
- send_keys(Keys.CONTROL,'a'):全选
- send_keys(Keys.CONTROL,'c'):复制
3.滚动条
#设置JavaScript脚本控制滚动条(0:左边距; 1000:上边距; 单位像素)
js = "window.scrollTo(0,1000)"
#WebDriver调用js脚本方法
driver.execite_script(js)
4.窗口截图
自动化脚本是由程序去执行的,因此有时候打印的错误信息并不是十分明确。如果在执行出错的时候对当前窗口截图保存,那么通过图片就可以非常直观地看到出错的原因
#截取当前窗口
driver.get_screenshot_as_file("./demo.png")
四.存储数据
1.将数据写入csv文件
#读写csv文件
import csv
#以写入方式打开文件,如果文件不存在则自动创建
f = open("d:/test.csv","w")
#获取csv writer,用于写入csv格式数据
writer = csv.writer(f)
#写入数据
writer.writerow(["张三","男","1.7"])
#关闭文件
f.close()
2.将数据写入MySQL
#安装模块
pip install pymysql
import pymysql
#创建链接
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='',
db='tkql',charset='utf8')
#创建游标
cursor = conn.cursor()
#执行SQL,并返回受影响行数
effect_row = cursor.execute("select * from tb7")
#提交,不然无法保存新建或修改的数据
conn.commit()
#关闭游标
cursor.close()
#关闭链接
conn.close()
五.实战
1.访问有道翻译网站,输入单词,并获取翻译后的内容
from selenium import webdriver
from selenium.webdriver.common.by import by
from selenium.webdriver.common.keys import keys
driver = webdriver.Chrome("./chromedriver.exe")
#加载有道翻译页面
driver.get("https://fanyi.youdao.com/")
#获取输入框
input = driver.find_element(By.ID,"inputOriginal")
#输入内容
input.send_keys("hello")
#获取翻译按钮
tbtn = driver.find_element(By.ID,"transMachine")
#发现页面被遮挡,此时无法点击
#tbtn.click()
#先获取遮挡的广告条,点击关闭按钮
close_btn = driver.find_element(By.CSS_SELECTOR,".guide-con .guide-close")
#点击翻译
tbtn.click()
#获取翻译后的内容
transTarget = driver.find_element(By.ID,"transTarget")
print(transTarget.text)
2.获取代理
from selenium import webdriver
#myLog是自定义模块,也就是后来复制到当前目录的myLog.py文件
from myLog import MyLog as mylog
#这个类的作用是为了方便装载爬虫获取的数据,基本包含了网页的所有项
clas Item(object):
ip = None #代理IP
port = None #代理端口
anonymous = None #是否匿名
type = None #类型
support = None #支持的协议
local = None #物理地址
speed = None #代理速度
#定义一个从kuaidili站点中获取proxy的类,这个类包含了3个类函数
class GetProxy(object):
def __init__(self):
self.startUrl = 'http://www.kuaidaili.com/proxylist/'
self.log = mylog()
self.urls = self.getUrls()
self.proxyList = self.getProxyList(self.urls)
self.fileName = 'proxy.txt'
self.saveFile(self.fileName,self.proxyList)
#该函数用于返回一个列表,这个列表包含了所有有效数据的网页地址
def getUrls(self):
urls = []
for i in xrange(1,11):
url = self.startUrl + str(i)
urls.append(url)
self.log.info('get url %s to urls' %usrl)
return usrls
#该函数用于从网页中获取有效数据,并保存到一个列表中
def getProxyList(self,urls):
browser = webdriver.PhantomJS()
proxyList = []
item = Item()
for url in urls:
browser.get(url)
browser.implicitly_wait(5)
elements = browser.find_elements_by_xpath('//tbody/tr')
for element in elements:
item.ip = element.find_element_by_xpath('/td[1]').text.encode('utf8')
item.port = element.find_element_by_xpath('./td[2]').text.encode('utf8')
item.anonymous = element.find_element_by_xpath('./td[3]').text.encode('utf8')
item.type = element.find_element_by_xpath('./td[4]').text.encode('utf8')
item.support element.find_element_by_xpath('./td[5]').text.encode('utf8')
item.local = element.find_element_by_xpath('./td[6]').text.encode('utf8')
item.speed = element.find_element_by_xpath('./td[7]').text.encode('utf8')
proxyList.append(item)
self.log.info('add proxy %s:$s to list' % (item.ip,item.port))
browser.quit()
return proxyList
#该函数用于将所有列表中的数据保存到文件中
def saveFile(self,fileName,proxyList):
self.log.info('add all proxy to %s' % fileName)
with open(fileName,'w') as fp:
for item in proxyList:
fp.write(item.ip + '\t')
fp.write(item.port + '\t')
fp.write(item.anonymous + '\t')
fp.write(item.type + '\t')
fp.write(item.support + '\t')
fp.write(item.local + '\t')
fp.write(item.speed + '\n')
if __name__ == '__main__':
GP = GetProxy()
3.漫画爬虫
from selenium import webdriver
from mylog import MyLog as mylog
import os
import time
class GetCartoon(object):
def __init__(self):
self.startUrl = u'http://www.1kkk.com/ch1-406302/'
self.log = mylog()
self.browser = self.getBrowser()
self.saveCartoon(self.browser)
#作用是返回一个browser对象
def getBrowser(self):
browser = webdriver.PhantomJS()
try:
browser.get(self.startUrl)
except:
mylog.error('open the %s failed' %self.startUrl)
#作用是设定了智能等待的最长时间
browser.implicitly_wait(20)
return browser
'''
这个函数将从网站中获取图片,并保存到新建立的文件夹中。文件夹的文字是从网页的title中获取的。从网页中获取了这个漫画的总页数,因为这个漫画在最后一页还是有“下一页”的按钮。没办法通过是否存在“下一页”按钮来确定是不是最后一页,所以必须先获取这个漫画的总页数'''
def saveCartoon(self,browser):
cartoonTitle = browser.title.split('_')[0]
self.createDir(cartoonTitle)
sumPage = int(self.browser.find_element_by_xpath('//font[@class="zf40"]/span[2]')
.text)
i = 1
while i <= sumPage:
imgName = str(i) + '.png'
browser.get_screenshot_as_file(imgName)
self.log.info('save img %s' %imgName)
i += 1
NextTag = browser.find_element_by_id('text')
NextTag.click()
browser.implicitly_wait(20)
time.sleep(5)
self.log.info('save img sccess')
exit()
#作用是创建一个目录,为了防止有同名的目录,先在函数内做出判断
def createDir(self,dirName):
if os.path.exists(dirName):
self.log.error('create directory %s failed,have a same name file or directory'
%dirName)
else:
try:
os.makedirs(dirName)
except:
self.log.error('create directory %s failed' %dirName)
else:
self.log.info('create directory %s success' %dirName)
if __name__ == '__main__':
GC = GetCartoon()
版权归原作者 奔跑的蜗牛君666 所有, 如有侵权,请联系我们删除。