seleinum

Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器)。 Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。
Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器。
安装

pip3 install selenium

selenium不自带浏览器,所以我们需要第三方浏览器
驱动下载:

谷歌驱动(chromedriver)下载地址: http://chromedriver.storage.googleapis.com/index.html
火狐驱动下载路径(GeckoDriver):https://github.com/mozilla/geckodriver/releases(2.3.8是最新的,下载的驱动版本一定要支持你当前的浏览器版本)

页面的相关操作:

获取id标签值

element = driver.find_element_by_id("passwd-id")

获取name标签值

element = driver.find_element_by_name("user-name")

获取标签名值

element = driver.find_elements_by_tag_name("input")

也可以通过XPath来匹配

element=driver.find_element_by_xpath("//input[@id='passwd-id']")

页面前进和后退

操作页面的前进和后退功能:
driver.forward() #前进
driver.back() # 后退

添加cookies

driver.add_cookie(cookie_dict)

删除Cookies,用法如下

  • 删除一个特定的cookie
    driver.delete_cookie("CookieName")
  • 删除所有cookie
    driver.delete_all_cookies()

设置无头浏览器

opt = webdriver.ChromeOptions()
opt.set_headless()

设置代理

opt = webdriver.ChromeOptions()
opt.add_argument("--proxy-server=http://118.20.16.82:9999")

代码:

#  pip3 install selenium
# selenium不自带浏览器,必须跟第三方的浏览器配合使用

from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys

#如何设置屋头浏览器
opt = webdriver.ChromeOptions()
#设置为无头浏览器()
# opt.set_headless()
# 设置代理
opt.add_argument("--proxy-server=http://202.20.16.82:10152")

#创建一个浏览器的驱动
chrome_driver = webdriver.Chrome(
    executable_path='/home/ljh/桌面/driver/chromedriver',
)

chrome_driver.get('https://www.baidu.com/')

#chrome_driver.save_screenshot('baidu.png')

#PhantomJS屋头浏览器
# phantom_js = webdriver.PhantomJS(executable_path='/home/ljh/桌面/driver/phantomjs')
#
# phantom_js.get('https://www.baidu.com/')
#
# phantom_js.save_screenshot('baidu2.png')

#获取页面源码(这时候获取的页面源码是经过浏览器渲染之后的结果)
#豆瓣的例子
#chrome_driver.get('https://movie.douban.com/subject_search?search_text=%E7%94%B5%E5%BD%B1&cat=1002')
html_data = chrome_driver.page_source
#获取cookies
cookies = chrome_driver.get_cookies()
print(cookies)
#可以获取当前请求的url
cur_url = chrome_driver.current_url

#模拟用户操作
#以百度为例
#再搜搜兰中输入文字
chrome_driver.find_element_by_id('kw').send_keys('中国我的国')
#点击按钮
chrome_driver.find_element_by_id('su').click()

# time.sleep(3)
# 隐士等待:当我们寻找节点的时候,有时候页面可能没有加载出来,
# 设置隐士等待,没找到的话会等一会继续寻找,如果在设定的时间内还没有找到
# 会出现异常错误
chrome_driver.implicitly_wait(10)

#显示等待

#点击下一页
# chrome_driver.find_element_by_class_name('n').click()
#根据文字寻找
chrome_driver.find_element_by_link_text('下一页>').click()

# with open('page.html','w') as file:
#     file.write(html_data)

chrome_driver.find_element_by_id('kw').clear()
chrome_driver.find_element_by_id('kw').send_keys('我的媳妇是谁')
#Keys.RETURN模拟键盘的回车操作
chrome_driver.find_element_by_id('su').send_keys(Keys.RETURN)

"""
#通关节点的name属性查找对应的节点
chrome_driver.find_element_by_name()
#通过节点的class_name找到对应的节点
chrome_driver.find_element_by_class_name()
#通过css选择器查找对应的节点
chrome_driver.find_element_by_css_selector()
#通过连接所在标签的部分文字找到对应的节点
chrome_driver.find_element_by_partial_link_text()
#通过xpath路径找对对应的节点
chrome_driver.find_element_by_xpath()
.....
"""

#获取节点的属性get_attribute('属性的名称')
print(chrome_driver.find_element_by_id('su').get_attribute('value'))
#获取节点的文本.text
print(chrome_driver.find_element_by_class_name('n').text)

#回退
chrome_driver.back()
#前进
chrome_driver.forward()

#关闭浏览器(只有一个界面会退出浏览器,多个界面时只表示关闭当前界面)
chrome_driver.close()

#退出浏览器
chrome_driver.quit()

页面等待

注意:这是非常重要的一部分!! 现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。 为了避免这种元素定位困难而且会提高产生 ElementNotVisibleException 的概率。所以 Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。
隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。

隐式等待

from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://www.xxxxx.com/loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

显式等待

显式等待指定某个条件,然后设置最长等待时间。如果在这个时间还没有找到元素,那么便会抛出异常了。 程序默认会 0.5s 调用一次来查看元素是否已经生成,如果本来元素就是存在的,那么会立即返回。

from selenium import webdriver
from selenium.webdriver.common.by import By
# WebDriverWait 库,负责循环等待
from selenium.webdriver.support.ui import WebDriverWait
# expected_conditions 类,负责条件出发
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("http://www.xxxxx.com/loading")
try:
    ##### 会在这里等待,如果10秒内 id="myDynamicElement"的标签出现
    则返回,如果不出现则报异常
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(
            (By.ID, "myDynamicElement")
            )
    )
finally:
    driver.quit()

异常处理

请求超时异常处理

from selenium.common.exceptions import TimeoutException

try:
   brower.get(url)
except TimeoutException:
   print('Time out')

找不到标签的异常处理

from selenium.common.exceptions import NoSuchElementException

try:
    brower.find_element_by_id('').click()
    print('有标签')
except NoSuchElementException:
    print('没有这个标签')    

selenium动态页面模拟点击案例:
爬取斗鱼直播平台的所有房间信息:

from selenium import webdriver
import json
import time
class Douyu:
    # 1.发送首页的请求
    def __init__(self):
        self.driver = webdriver.PhantomJS()
        self.driver.get("https://www.douyu.com/directory/all") #请求首页

    #获取没页面内容
    def get_content(self):
        time.sleep(3) #每次发送完请求等待三秒,等待页面加载完成
        li_list = self.driver.find_elements_by_xpath('//ul[@id="live-list-contentbox"]/li')
        contents = []
        for i in li_list: #遍历房间列表
            item = {}
            item["img"] = i.find_element_by_xpath("./a//img").get_attribute("src") #获取房间图片
            item["title"] = i.find_element_by_xpath("./a").get_attribute("title") #获取房间名字
            item["category"] = i.find_element_by_xpath("./a/div[@class='mes']/div/span").text #获取房间分类
            item["name"] = i.find_element_by_xpath("./a/div[@class='mes']/p/span[1]").text #获取主播名字
            item["watch_num"] = i.find_element_by_xpath("./a/div[@class='mes']/p/span[2]").text #获取观看人数
            print(item)
            contents.append(item)
        return contents
    #保存本地
    def save_content(self,contents):
        f = open("douyu.txt","a")
        for content in contents:
            json.dump(content,f,ensure_ascii=False,indent=2)
            f.write("\n")
        f.close()

    def run(self):
        #1.发送首页的请求
        #2.获取第一页的信息
        contents = self.get_content()
            #保存内容
        self.save_content(contents)
        #3.循环  点击下一页按钮,知道下一页对应的class名字不再是"shark-pager-next"
        while self.driver.find_element_by_class_name("shark-pager-next"): #判断有没有下一页
            #点击下一页的按钮
            self.driver.find_element_by_class_name("shark-pager-next").click() #
            # 4.继续获取下一页的内容
            contents = self.get_content()
            #4.1.保存内容
            self.save_content(contents)

if __name__ == "__main__":
    douyu = Douyu()
    douyu.run()

你可能感兴趣的:(seleinum)