0


Selenium的使用

Selenium 是一个自动化测试工具,它主要用于自动化网络应用程序的测试。不过,除了测试之外,它也常用于自动执行各种浏览器操作,比如自动填写表单、抓取网页数据、点击、下拉等。同时还可以获取浏览器当前所呈现的页面的源代码,做到可见即可爬,对于一些JavaScript动态渲染的页面来说,非常有效

一 准备工作

谷歌浏览器为例,在开始之前确保已经安装好了浏览器并配置好了ChromeDriver,另外还需要安装python第三方selenium库。

1 安装库

pip install selenium

2 安装驱动

官网:http://chromedriver.storage.googleapis.com/index.html

注意:

    驱动要对应浏览器版本,否则无法驱动

    禁止浏览器更新services.msc找到给禁止

安装细节:

查看浏览器版本:浏览器三个小点--设置--关于谷歌

找到类似的版本的驱动

找一个下载win版本的然后解压,安装

将驱动的.exe文件放在python的安装目录下(或者把路径给配置到环境变量中,可以通过cmd输入chromedriver运行)

禁止更新服务:

win+R - services.msc找到下面的给禁止

如果版本超过114,进入下面的连接下载对应版本(下载win32)

Chrome for Testing availabilityhttps://googlechromelabs.github.io/chrome-for-testing/

二 声明浏览对象

Selenium支持众多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面的浏览器PhantomJS

初始化方式如下:

from selenium import webdriver

browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.Safari()

三 基本使用

打开一个网站然后关闭,具体代码如下

from selenium import webdriver
import time
# 创建一个浏览器对象
browser = webdriver.Chrome()
# 打开指定网页
browser.get('https://www.baidu.com/')
# 停留5秒
time.sleep(5)
# 退出浏览器
browser.quit()

用浏览器搜索指定内容

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
# 提前添加配置信息
options = webdriver.ChromeOptions()
# 设置浏览器不被检测
options.add_argument('--disable-blink-features=AutomationControlled')
# 创建一个浏览器对象
browser = webdriver.Chrome()
# browser = webdriver.Chrome(options = options)
# 打开指定网页
browser.get('https://www.baidu.com/')
# 搜索中国武警
#     定位
browser.find_element(By.ID, 'kw').send_keys('中国武警')
# 点击搜索
browser.find_element(By.ID,'su').click()
# 停留5秒
time.sleep(5)
# 退出浏览器
browser.quit()

(可能会检测出来是非人为操作,通过提前配置浏览器参数解决)

设置屏蔽

options = webdriver.ChromeOptions()
# 设置浏览器不被检测
options.add_argument('--disable-blink-features=AutomationControlled')
# 创建一个浏览器对象
browser = webdriver.Chrome(options = options)

模拟键盘操作

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys #模拟键盘操作
import time
# 提前添加配置信息
options = webdriver.ChromeOptions()
# 设置浏览器不被检测
options.add_argument('--disable-blink-features=AutomationControlled')
# 创建一个浏览器对象
browser = webdriver.Chrome()
# 打开指定网页
browser.get('https://www.baidu.com/')
# 搜索中国武警
#     定位
s = browser.find_element(By.ID, 'kw')
s.send_keys('中国武警')
# 回车搜索
s.send_keys(Keys.ENTER)
time.sleep(10)

四 查找结点

匹配单个节点

find_element()

# 通过 ID 定位元素
find_element(By.ID, "element_id")
# 通过类名定位元素
find_element(By.CLASS_NAME, "element_class")
# 通过名字定位元素
find_element(By.NAME, "element_name")
# 通过 CSS 选择器定位元素
find_element(By.CSS_SELECTOR, "css_selector")
# 通过 XPath 定位元素
find_element(By.XPATH, "xpath_expression")
# 通过链接文本定位超链接
find_element(By.LINK_TEXT, "link_text")
# 通过部分链接文本定位超链接
find_element(By.PARTIAL_LINK_TEXT, "partial_link_text")
# 通过标签名定位元素
find_element(By.TAG_NAME, "tag_name")

多个节点

find_elements()

五 节点交互

Selenium可以驱动浏览器来执行一系列操作,即让浏览器执行一些动作。常见用法:输入文字时用send_keys方法,清空文字用clear方法,点击按钮用click方法。示例如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
s = browser.find_element(By.ID, 'kw')
s.send_keys('李宁')
time.sleep(1)
s.clear()
s.send_keys('耐克')
but = browser.find_element(By.ID,'su')
but.click()
time.sleep(10)

六 动作链

上面例子中,一些交互动作都是针对某个节点执行的,如,对于输入框,用他的输入文字和清空文字方法;对于按钮,调用它的点击方法。另外一种操作,没有特定的执行对象,如鼠标拖拽,键盘按键等,这些动作通过另一种形式来执行,那就是动作链。

比如,现在实现一个节点的拖拽操作,将某个节点从一处拖拽到另一处,可以这样实现:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
browser = webdriver.Chrome()
url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult') #切换到嵌套的网页(frame的为iframeResult的网页)
source = browser.find_element(By.CSS_SELECTOR,'#draggable')
target = browser.find_element(By.CSS_SELECTOR,'#droppable')
action = ActionChains(browser)
action.drag_and_drop(source,target)
action.perform()

首先,打开一个网页的拖曳实例,然后依次选中要拖曳的节点和拖曳后的节点,接着声明ActionChains对象并赋值给action,然后通过调用drag_and_drop()方法,再调用perform()方法执行动作,此时就完成了拖曳操作。

页面滚动

移动元素element元素的顶端与当前窗口的顶部对齐

execute_script(“argument[0].scrollIntoView();”,element)
execute_script(“argument[0].scrollIntoView(True);”,element)

移动元素element对象的底端与当前窗口的底部对齐

execute_script(“argument[0].scrollIntoView(False);”,element)

移动到页面最底部(scrollTo(x,y),x指的是x轴坐标,y指的是y轴坐标)

execute_script("window.scrollTo(0,document.body.scrollHeight)")

移动到指定的坐标(相对当前的坐标)

execute_script("window.scrollBy(0,700)")

结合上面的scrollBy语句,相当于移动到700+800px位置

execute_script("window.scrollBy(0,800)")

移动到窗口绝对位置坐标

execute_script("window.scrollTo(0,700)")

七 执行JS

对于某些操作,Selenium API没有提供,比如,下拉进度条,它可以通过直接模拟运行JavaScript,此时使用execute_script()方法即可以实现,代码如下:

# document.body.scrollHeight   获取页面高度
# 按F12之后在控制台输入document.body.scrollHeight 可以查看页面高度
from selenium import webdriver
import time,random
browser = webdriver.Chrome()
browser.get('https://36kr.com/')
# # 下拉边框,一次性拉到位
# browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
# 慢慢下拉
for i in range(1,9):
    time.sleep(random.randint(100,300)/1000)
    browser.execute_script('window.scrollTo(0,{})'.format(i*1000))
time.sleep(10)

这里利用execute_script()方法将进度条拉到最底部

所以说有了这个方法,基本上API没有提供的所有功能都可以执行JavaScript方式来实现

八 获取节点信息

获取属性

可以使用get_attribute()方法来获取节点的属性,但是其前提是先选中这个节点,示例如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
url = 'https://pic.netbian.com/4Kxinnian/'
browser = webdriver.Chrome()
browser.get(url)
src = browser.find_elements(By.XPATH,'//ul[@class="clearfix"]/li/a/img')
for i in src:
# 获取i中的src属性
    url = i.get_attribute('src')
    print(url)

通过get_attribute()方法,然后传入想要获得的属性名,就可以得到它的值了。

获取ID、位置、标签名、大小

另外,WebElement节点还有一些其他属性,比如id属性可以获取节点id,location属性可以获取该节点在页面中的相对位置,tag_name 属性可以获取标签名称,size属性可以获取节点的大小(宽高),示例如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
# 安装Pillow库
from PIL import Image
from io import BytesIO
url = 'https://pic.netbian.com/4Kxinnian/'
browser = webdriver.Chrome()
browser.get(url)
img = browser.find_element(By.XPATH,'//ul[@class="clearfix"]/li[1]/a/img')
location = img.location
size = img.size
print(location,size)
# top bottom left right 分别代表上边界 下边界 左边界 右边界
top,bottom,left,right = location['y'],location['y']+size['height'],location['x'],location['x']+size['width']
print(top,bottom,left,right)
screen = browser.get_screenshot_as_png()
screen = Image.open(BytesIO(screen))
cap = screen.crop((top,left,right,bottom))
cap.save('1.png')

九 切换Frame

我们知道网页中有一种节点叫做iframe,也就是子Frame,相当于页面的子页面,它的结构和外部网页的结构完全一致。Selenium打开页面后,它默认是在父级Frame里面进行操作的,而此时页面中还有子Frame,它是不能获取到子Frame里面的节点的,这是需要使用switch_to.frame()方法来切换Frame。示例如下:

from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
browser.get('https://www.douban.com')
login_frame = browser.find_element(By.XPATH,'//div[@class="login"]/iframe')
browser.switch_to.frame(login_frame)
s = browser.find_element(By.CLASS_NAME,'account-tab-account')
s.click()
browser.find_element(By.ID,'username').send_keys('123456')

十 延时等待

在Selenium中,get()方法会在网页框架加载结束后结束执行,次数如果获取page_source,可能并不是浏览器完全加载完成的界面,如果某些页面有额外的Ajax请求,我们在页面源代码中也不一定能够获取到。所以,这里需要延时等待一定时间,确保节点已经加载出来,这里等待的方式有两种,显式等待和隐式等待。

隐式等待

当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定的时间后,会抛出找不到节点的异常。换句话说,当查找节点而节点并没有立即出现的时候,隐式等待会等待一段时间再查找DOM,默认时间是0,示例如下:

显式等待

隐式等待效果并没有那么好,因为我们只规定了一个固定的时间,而页面加载受网络等条件的影响。

显示等待方法,它指定要查找的节点,然后指定一个最长的等待时间。如果在规定的时间内加载出来这个节点,就返回查找的节点,如果没有加载出来,则抛出超时异常,示例如下

十一 前进后退

平时使用浏览器都有前进和后退功能,Selenium也可以完成这样的操作,它使用back()方法后退,使用forward()方法前进,示例如下:

from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.get('https://www.douban.com')
browser.get('https://www.jd.com')
browser.back()
time.sleep(1)
browser.forward()
browser.close()

十二 Cookies

使用Selenium,还可以方便的对Cookies进行操作,获取、添加、删除Cookies等

from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.zhihu.com')
print(browser.get_cookies())
browser.add_cookie({'name':'name','domain':'www.zhihu.com','value':'germy'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

十三 选项卡管理

在访问页面的时候,会开启一个个选项卡。在Selenium中,我们也可以对选项卡进行操作

from selenium import webdriver
import time
browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()')
print(browser.window_handles)
browser.switch_to.window(browser.window_handles[1])
browser.get('https://www.taobao.com')
time.sleep(1)
browser.switch_to.window(browser.window_handles[0])
browser.get('https://www.jd.com')

首先访问百度,然后调用execute_script()方法执行window.open()这个JavaScript语句开启一个选项卡。接下来我们想切换到该选项卡。调用window_handles属性获取当前开启的所有选项卡,返回选项卡的代号序列。使用switch_to.window()方法切换选项卡,其中参数一是选项卡的代号,我们将第二个选项卡的代号传入,即跳转到第二个选项卡,然后在第二个选项卡上打开淘宝,然后再切换到第一个选项卡(重新调用switch_to.window()方法),打开京东。

十四 异常处理

在使用Selenium的过程中,难免会遇到一些异常,例如超时、节点未找到等错误,一旦出现此类错误,程序便不会执行。这里使用try expect语句来捕获各种异常。

from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException
from selenium.webdriver.common.by import By
browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('超时!')
try:
    browser.find_element(By.ID,'hello')
except NoSuchElementException:
    print('没有此类节点')
finally:
    browser.close()

十五 绕过检测

无处理:

browser = get('https://www.baidu.com')

设置屏蔽

options = webdriver.ChromeOptions()
options.add_argument('--disable-blink-features=AutomationControlled')
browser = webdriver.Chrome(options = options)
browser.get('https://www.baidu.com')

十六 教学案例

采集义乌购商品网站

完整流程如下图所示:

代码实现:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time,random
from selenium.common.exceptions import NoSuchElementException
import pymysql

class YwShop():
    def __init__(self):
        # 初始化函数,提供配置项,设置屏蔽,防止网站检测出是爬虫
        options = webdriver.ChromeOptions()
        options.add_argument('--disable-blink-features=AutomationControlled')
        self.browser = webdriver.Chrome(options=options)
    def base(self):
        # 访问网站
        self.browser.get('https://www.yiwugo.com/')
        # 获取输入框
        input = self.browser.find_element(By.ID,'inputkey')
        # 发送参数
        input.send_keys('饰品')
        # 点击事件
        self.browser.find_element(By.XPATH,'//div[@class="search-index"]/span[last()]').click()
        print('调用访问网站函数')
    def spider(self):
        # 下拉翻页
        # window.document.documentElement.scrollHeight  在控制台输入查看网页高度
        self.drop_down()
        # 定位数据区域
        li = self.browser.find_elements(By.CLASS_NAME,'pro_list_product_img2')
        for i in li:
            # 定位数据
            title = i.find_element(By.XPATH,'.//li/a[@class="productloc"]')
            price = i.find_element(By.XPATH,'.//li/span[@class="pri-left"]/em')
            info = i.find_elements(By.XPATH,'.//li/span[@class="pri-right"]/span')
            address = i.find_element(By.XPATH,'.//li[@class="shshopname"]')
            texts = ''
            for j in info:
                texts=texts+j.text
            # 构造数据结构
            items = {
                '标题':title.text,
                '价格':price.text,
                '地址':address.text,
                '信息':texts
            }
            # 调用保存逻辑
            self.save_mysql(items)
        # 翻页
        self.page_next()
    def save_mysql(self,data):
        title = data.get('标题')
        price = data.get('价格')
        address = data.get('地址')
        texts = data.get('信息')
        db = pymysql.connect(host='localhost',user='root',password='123456',port=3306,db='test1')
        cursor = db.cursor()
        sql = 'insert into yiwudb(title,price,address,texts) values(%s,%s,%s,%s)'
        try:
            cursor.execute(sql,(title,price,address,texts))
            db.commit()
        except Exception as e :
            print('出错信息:',e)
            db.rollback()
        db.close()

    def page_next(self):
        # 定位翻页
        try:
            next = self.browser.find_element(By.XPATH,'//ul[@class="right"]/a[@class="page_next_yes"]')
            if next:
                next.click()
                self.spider()
            else:
                self.browser.close()
        except Exception as e:
            print(e)
    def drop_down(self):
        # 下拉页面
        for i in range(1,10):
            j = i/10
            js = f'window.scrollTo(0,document.body.scrollHeight * {j})'
            self.browser.execute_script(js)
            time.sleep(random.randint(400,800)/1000)

if __name__ == '__main__':
    f = YwShop()
    f.base()
    f.spider()

本文转载自: https://blog.csdn.net/qq_44709053/article/details/135422122
版权归原作者 在下区区俗物 所有, 如有侵权,请联系我们删除。

“Selenium的使用”的评论:

还没有评论