我们知道爬虫在很多情况下并不是万能的,这时候就需要我们的自动化测试框架了。于是Selenium应运而生。可以说是自动化测试框架中的佼佼者,因为它解决了大部分用于爬取页面的模块的一个永久性痛点,即Ajax异步加载。今天给大家详细讲解一下如何使用Selenium爬取数据,最后附上一个真实案例。1.Selenium简介Selenium是一种用于Web的自动化测试工具。它最初是为网站的自动化测试而开发的。Selenium可以直接在浏览器上运行。支持所有主流浏览器,可以接收指令让浏览器自动加载页面,获取所需的数据,甚至可以对页面进行截图。chromedriver是驱动Chrome浏览器的驱动,只能用来驱动浏览器。当然,不同的浏览器有不同的驱动。下面列出了不同的浏览器及其对应的驱动程序:developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/Safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/安装和配置chromedriver:https://blog.csdn.net/weixin_43901998/article/details/88087832安装Selenium:pipinstallselenium安装好浏览器后,将浏览器驱动放在与浏览器同级目录下,这样前期工作就做好了。注意:不要随意下载浏览器和驱动程序。每个浏览器和驱动的版本一定要一一对应,不能通用。二、快速入门1、与浏览器建立连接#1、加载网页fromseleniumimportwebdriverdriver=webdriver.PhantomJS(executable_path=r'"installationdirectory")#也可以在python文件路径中添加chrome,不写executable_path=r'"安装目录"driver.get("https://www.baidu.com")#请求driver.save_screenshot("baidu.png")#截图#退出driver.quit()2、selenium快速启动自seleniumimportwebdriver#实例化浏览器驱动=webdriver.Chrome()#发送请求driver.get('https://www.baidu.com')#screenshotdriver.save_screenshot("baidu.png")#最大化窗口driver.maximize_window()#退出浏览器driver.quit()3.定位元素find_element_by_id:根据id查找元素。submitTag=driver.find_element_by_id('su')submitTag1=driver.find_element(By.ID,'su')find_element_by_class_name:按类名查找元素。submitTag=driver.find_element_by_class_name('su')submitTag1=driver.find_element(By.CLASS_NAME,'su')find_element_by_name:根据name属性的值查找元素。submitTag=driver.find_element_by_name('email')submitTag1=driver.find_element(By.NAME,'email')find_element_by_tag_name:按标签名称查找元素。submitTag=driver.find_element_by_tag_name('div')submitTag1=driver.find_element(By.TAG_NAME,'div')find_element_by_xpath:根据xpath语法获取元素。submitTag=driver.find_element_by_xpath('//div')submitTag1=driver.find_element(By.XPATH,'//div')注意find_element是获取第一个满足条件的元素。find_elements是获取所有满足条件的元素。4.浏览器操作fromseleniumimportwebdriver#实例化浏览器c=webdriver.Chrome()#发送请求c.get('https://www.baidu.com')1,获取本页URLc.current_url2,获取Logc。log_types#获取当前日志类型c.get_log('browser')#浏览器操作日志c.get_log('driver')#设备日志c.get_log('client')#客户端日志c.get_log('server')#服务器日志##3。窗口操作c.maximize_window()#最大化c.fullscreen_window()#全屏c.minimize_window()#最小化c.get_window_position()#获取窗口坐标c.get_window_rect()#获取窗口的大小和坐标c.get_window_size()#获取窗口大小c.set_window_position(100,200)#设置窗口坐标c.set_window_rect(100,200,32,50)#设置窗口大小和坐标c.set_window_size(400,600)#设置窗口窗口的大小c.current_window_handle#返回当前窗口的句柄c.window_handles#返回当前会话中所有窗口的句柄3.设置延时c.set_script_timeout(5)#设置脚本延时五秒后执行c.set_page_load_timeout(5)#设置页面读取延时五秒4.关闭c.close()#关闭当前标签页c.quit()#关闭浏览器并关闭驱动5.打印源码网页c.page_source6,截图操作c.save_screenshot('1.png')#截图,仅供参考ortsPNG格式c.get_screenshot_as_png()#获取当前窗口的截图为二进制数据c.get_screenshot_as_base64()#获取当前窗口的截图为base64编码字符String8.正向和反向刷新c.forward()#forwardc.back()#backwardc.refresh()#brush新增7.Cookies操作c.get_cookie('BAIDUID')#获取指定key的Cookiessc.get_cookies()#获取所有cookiesforyinc.get_cookies():x=yifx.get('expiry'):x.pop('expiry')c.add_cookie(x)#添加Cookiesc.delete_cookie('BAIDUID')#删除指定key的Cookies内容c.delete_all_cookies()#删除所有cookies五、操作表单元素操作输入框:分两步的第一步:找到这个元素。第二步:使用send_keys(value)填写数据。使用clear方法清空输入框的内容inputTag.clear()来操作checkbox。因为checkbox标签是要选中的,所以在网页上用鼠标点击。因此,如果要选中复选框标签,先选中标签,再执行点击事件。rememberTag=driver.find_element_by_name("rememberMe")rememberTag.click()操作按钮操作按钮的方式有很多种。如单击、右键、双击等,这里介绍最常用的一种。只需点击。直接调用点击函数即可。inputTag=driver.find_element_by_id('su')inputTag.click()选择select元素不能直接点击。因为点击后需要选择元素。这时selenium提供了一个类selenium.webdriver.support.ui.Select专门用于select标签。将获取的元素作为参数传递给该类,创建该对象。然后可以使用此对象进行选择[1]。切换iframe我们知道网页中有一个节点叫做iframe,它是一个子框架,相当于一个页面的子页面,它的结构和外部网页完全一样。Selenium打开页面后,默认在父Frame中操作。此时如果页面中有子Frame,Selenium是无法获取到子Frame中的节点的。这时候就需要使用switch_to.frame方法来切换Frame。接下来通过在豆瓣上模拟登录切换iframe。示例如下:fromseleniumimportwebdriveimporttimeurl='https:www.douban.com'driver=webdriver.Chrome()driver.get(self.url)time.sleep(3)#定位iframe标签login_iframe=self.driver.find_element_by_xpath('//*[@id="anonymous-reg-new"]/div/div[1]/iframe')#切换iframe标签driver.switch_to.frame(login_iframe)6.行为链有时页面上的操作可能会有很多步骤,这时候可以使用鼠标行为链类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):双击。更多方法参考:http://selenium-python.readthedocs.io/api.html豆瓣模拟登录(定位元素、切换iframe、行为链操作)。fromseleniumimportwebdriverimporttimeclass豆瓣():def__init__(self):self.url='https:www.douban.com'self.driver=webdriver.Chrome()deflogin(self):self.driver.get(self.url)time.sleep(3)#定位iframe标签login_iframe=self.driver.find_element_by_xpath('//*[@id="anony-reg-new"]/div/div[1]/iframe')#switchiframetagself.driver.switch_to.frame(login_iframe)#第一张截图(登录前)self.driver.save_screenshot('db1.png')#定位密码输入框self.driver.find_element_by_class_name('account-tab-account').click()#输入手机号码self.driver.find_element_by_id('username').send_keys('156xxxxxx26')#输入密码self.driver.find_element_by_id('password').send_keys('.......')#点击登录按钮self.driver.find_element_by_class_name('btn-account').click()time.sleep(3)#第二个截图(登录后)self.driver.save_screenshot('db2.png')defout(self):'''调用内置的sparse方法,自动调用当程序退出时同理也可以在打开文件时调用close,断开数据库链接'''self.driver.quit()if__name__=='__main__':db=Douban()#实例化db.login()#AfterCall登录方法7.Selenium页面等待Cookie操作获取所有cookiescookies=driver.get_cookies()根据cookie名称获取cookievalue=driver.get_cookie(key)删除一个cookiedriver.delete_cookie('key')页面等待当前页面越来越多的使用了Ajax技术,以至于程序无法确定某个元素何时完全加载。如果实际页面等待时间过长,一个dom元素还没有出来,而你的代码直接使用了这个WebElement,那么就会抛出一个NullPointer异常。解决这个问题。所以Selenium提供了两种等待方式:一种是隐式等待,一种是显式等待。隐式等待:调用driver.implicitly_wait。然后等待10秒,然后再获取不可用的元素。driver.implicitly_wait(10)显示等待:显示等待是指满足一定条件后才进行获取元素的操作。等待的时候也可以指定一个最长时间,超过这个时间就会抛出异常。应使用selenium.webdriver.support.excepted_conditions和selenium.webdriver.support.ui.WebDriverWait的预期条件来完成显示等待。fromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditionsasECdriver=webdriver.Chrome()driver.get("https://www.baidu.com/")try:element=WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"myDynamicElement")))finally:driver.quit()其他一些等待条件presence_of_element_located:一个元素有加载是完全的。presence_of_all_elements_located:网页中所有符合条件的元素都已加载。element_to_be_clickable:一个元素是可点击的。更多情况请参考:http://selenium-python.readthedocs.io/waits.html8.打开多个窗口并切换页面有时一个窗口中有多个子标签页。这个时候,肯定是需要切换的。Selenium提供了一个switch_to_window函数来切换,切换到哪个页面,可以从driver.window_handles中找到。#打开一个新页面driver.execute_script("window.open('url')")print(driver.current_url)#切换到这个新页面driver.switch_to_window(self.driver.window_handles[1])九、企鹅e-运动案例下面以企鹅电竞为例,演示如何使用Selenium爬取数据。1、打开官网首页:通过分析页面我们知道所有的直播信息都存放在ul下的li中(class='livelist-modresize-list-container-280-livelist-live)。但是通过测试我们可以发现,这个页面瀑布流布局,他不需要翻页,而是需要滚动到页面底部才能加载更多的数据。so:dataNum=int(input('请输入目标直播间数量:'))#用户决定爬取多少个直播间信息_single=True#死循环while_single:items=driver.find_elements_by_xpath("//ul[@class='livelist-modresize-list-container-280-livelist-live']/li")#页面的li标签(即一个直播间数据)print(len(items))iflen(items)
