0
点赞
收藏
分享

微信扫一扫

selenium&selenium-wire使用

凉夜lrs 2022-12-14 阅读 81

1. 为什么使用selenium

  前面爬虫大多使用的是urllib 库, 另外还有requests 库。urllib 可以解决好多问题,包括代理、自定义请求体、cookie 设置等。 这些库都是模拟浏览器进行访问,毕竟是模拟,有些网站针对反爬会造成爬取的数据不准确。

  这时候就需要引入selenium, selenuim 是真实的驱动浏览器,然后模拟人工操作去进行一系列的操作。

​  举个简单的例子: 首页,如果通过网页访问我们能拿到秒杀模块; 如果是通过urllib 访问拿到首页源码,发现没有该模块。该模块所在区域的xpath 选择器是: //*[@id='J_seckill']

2. selenium 安装以及简单测试

1. 下载浏览器驱动

selenium 是驱动浏览器,然后去进行一系列的操作,所以我们需要下载对应的驱动。

​ chrome 驱动: ​​http://chromedriver.storage.googleapis.com/index.html​​ 根据自己的chrome 版本下载对应的驱动, 大版本一致即可,windows 安装包32 位也可以的。

驱动下载完成后将解压后的exe驱动程序拷贝到运行程序同级目录,或者就放到python 目录然后加入到path 换变量中也可以。需要程序能找到该exe。

2. pycharm 安装selenium

File→Settings→Project:项目名称→python Interpreter->添加selenium

pycharm 安装完成后可以到项目的venv\lib 目录查看现有的模块

3. 本地安装selenium

如果是想python 跑对应脚本,需要本地安装selenium

pip install selenium

测试可以在python 窗口输入:

from selenium import webdriver

4. 简单测试

from selenium import webdriver

browser = webdriver.Chrome("chromedriver.exe")
browser.get("https://www.jd.com/")

# 获取网页源码
content = browser.page_source
print(content)
# 打印url
print(browser.current_url)

# 保存为图片(注意这里只能保存为png,不支持jpg)
browser.save_screenshot("jd.png")

# 打印title
print(browser.title)
# 窗口最大化
browser.maximize_window()

# 关闭
browser.close()

会自动打开浏览器,然后访问京东的首页。然后打印网页源码(从源码可以搜索到id 为 J_seckill 的div)。最后将网页保存为图片后关闭浏览器。

3. selenium 解析以及获取

  1. 获取元素

获取元素主要有下面六个API:当然返回的元素还可以继续调用find_element 元素向下查找。

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome("chromedriver.exe")
browser.get("https://www.baidu.com/")

# 获取网页源码
# content = browser.page_source
# print(content)

'''
元素定位(改版后主要有两个方法)。
两个方法参数一样
第一个指定模式: 参考 selenium.webdriver.common.by.By;
class By:
"""
Set of supported locator strategies.
"""

ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
第二个指定属性的值
find_element(by=By.ID, value=None) 查找单个元素,WebElement。 内部调用查找集合方法,然后返回第一个元素
find_elements(by=By.ID, value=None) 查找集合, WebElement 集合
'''

# 根据ID查找 (百度首页的百度一下按钮)
# button = browser.find_element(by=By.ID, value="su")
# print(button)

# 根据name属性查找 (查找百度首页的输入框)
# input = browser.find_element(by=By.NAME, value="wd")
# print(input)

# 根据xpath 语法查找 (查找百度首页的输入框)
# input = browser.find_element(by=By.XPATH, value="//input[@name='wd']")
# print(input)

# 根据标签的名字查找
# inputs = browser.find_elements(by=By.TAG_NAME, value="input")
# print(len(inputs))

# 根据link 内容查找 也就是根据<a>测试</a> 内部的text 属性查找
# a = browser.find_element(by=By.LINK_TEXT, value="新闻")
# print(a.text)

# css 选择器查找(找百度首页输入框)
a = browser.find_element(by=By.CSS_SELECTOR, value="#kw")
print(a.get_attribute("name"))

# 关闭
browser.close()

  1. 访问元素信息

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome("chromedriver.exe")
browser.get("https://www.baidu.com/")

# 根据link 内容查找 也就是根据<a>测试</a> 内部的text 属性查找
a = browser.find_element(by=By.LINK_TEXT, value="新闻")
# 获取属性
print(a.get_attribute("href"))
# 获取text
print(a.text)
# 获取tag
print(a.tag_name)

# 关闭
browser.close()

  1. 交互

点击: click()
输入: send_keys()
清空输入: clear()
后退:browser.back()
快进:browser.forward()
模拟JS滚动: js = 'document.body.scrollTop=100000'
js = 'document.documentElement.scrollTop=100000'
browser.execute_script(js) # 执行JS代码
获取网页源码: browser.page_source

4. selenium 爬取百度

一个简单的例子,过程如下:

1.打开百度首页,睡眠2s

2.输入java,睡眠2s

3.点击百度一下按钮,睡眠5s

4.滚动到底部,睡眠5s

5.翻到第二页,睡眠5s

6.点击后退回退到第一页,睡眠5s

7.点击前进再回去第二页, 睡眠5s

8.结束

代码:

import time

from selenium import webdriver
# 1.打开百度首页,睡眠2s
from selenium.webdriver.common.by import By

browser = webdriver.Chrome("chromedriver.exe")
browser.get("https://www.baidu.com/")
time.sleep(2)

# 2.输入java,睡眠2s
input = browser.find_element(value="kw")
input.send_keys("java")
time.sleep(2)

# 3.点击百度一下按钮,睡眠5s
button = browser.find_element(value="su")
button.click()
time.sleep(5)

# 4.滚动到底部,睡眠5s
js = 'document.body.scrollTop=100000'
browser.execute_script(js)
time.sleep(5)

# 5.翻到第二页,睡眠5s
nextBtn = browser.find_element(by=By.XPATH, value="//a[@class='n']")
nextBtn.click()
time.sleep(5)

# 6. 点击后退回退到第一页,睡眠5s
browser.back()
time.sleep(5)

# 7. 点击前进再回去第二页, 睡眠5s
browser.forward()
time.sleep(5)

# 8. 关闭
browser.close()

5. selenium 不启动浏览器模式

打开浏览器再启动会浪费时间,对爬虫的性能也是个影响,还有一种就是不打开浏览器。

如下参数是针对chrome 的全局参数,不能自定义参数。

from selenium import webdriver

# 还有一些其他的参数
'''
# 添加UA
options.add_argument('user-agent="MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"')

# 设置代理
options.add_argument("--proxy-server=http://110.52.235.176:9999") # 设置代理,请求头等,以列表的形式传入多个参数

# 设置编码格式
options.add_argument('lang=zh_CN.UTF-8') # 设置编码格式

# 启动时最大化窗口
options.add_argument('--start-maximized')

# 指定浏览器分辨率
options.add_argument('window-size=1920x3000')

# 谷歌文档提到需要加上这个属性来规避bug
options.add_argument('--disable-gpu')

# 隐藏滚动条, 应对一些特殊页面
options.add_argument('--hide-scrollbars')

# 不加载图片, 提升速度
options.add_argument('blink-settings=imagesEnabled=false')

# 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
options.add_argument('--headless')

# 以最高权限运行
options.add_argument('--no-sandbox')

# 手动指定使用的浏览器位置
options.binary_location = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"

#添加crx插件
option.add_extension('d:\crx\AdBlock_v2.17.crx')

# 禁用JavaScript
option.add_argument("--disable-javascript")

# 设置开发者模式启动,该模式下webdriver属性为正常值
options.add_experimental_option('excludeSwitches', ['enable-automation'])

# 禁用浏览器弹窗
prefs = {
'profile.default_content_setting_values' : {
'notifications' : 2
}
}
options.add_experimental_option('prefs',prefs)
'''

option = webdriver.ChromeOptions()
# 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
option.add_argument("--headless")
# 谷歌文档提到需要加上这个属性来规避bug
option.add_argument('--disable-gpu')
browser = webdriver.Chrome(executable_path="chromedriver.exe", options=option)
browser.get("https://www.jd.com/")

# 获取网页源码
print(browser.title)

# 关闭
browser.close()

6. 以不打开浏览器的方式设置代理获取当前的IP信息

from selenium import webdriver
from selenium.webdriver.common.by import By

option = webdriver.ChromeOptions()
# 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
option.add_argument("--headless")
# 谷歌文档提到需要加上这个属性来规避bug
option.add_argument('--disable-gpu')
# 添加代理
option.add_argument("--proxy-server=http://221.11.233.111:4315") # 设置代理,请求头等,以列表的形式传入多个参数

browser = webdriver.Chrome(executable_path="chromedriver.exe", options=option)
browser.get("http://www.ipdizhichaxun.com/")

# 获取网页源码
result = browser.find_element(by=By.XPATH, value='//*[@class="result"]')
print(result.text)

# 关闭
browser.close()

结果:

IP地址查询结果:221.11.233.111,IP地址位置:宁夏石嘴山市(联通)

7. 传cookie

import time

from selenium import webdriver

browser = webdriver.Chrome(executable_path="chromedriver.exe")
# 删除原来的cookie
browser.delete_all_cookies()
# 注意需要访问一次才能添加cookie。 selenium的默认域名为data,cookie中带域名,在设置cookie时发现当前域名不包含在cookie中,所以设置失败,一直都是data的这个页面
browser.get("http://127.0.0.1:8088/inner/t4")
# 携带cookie打开
browser.add_cookie({'name': 'ABC', 'value': 'DEF'})
browser.get("http://127.0.0.1:8088/inner/t4")
browser.refresh()

browser.close()
time.sleep(10)

8. 设置等待时间

如果不设置等待时间,find_element会立即查找元素,找不到就会立即报错。一般会设置下时间,让JS渲染完成再找元素。

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome("chromedriver.exe")
# 设置等待时间,最长等待20 s。 不设置等待事件, find_element 找不到元素会抛出异常,设置完成之后不会报异常,会阻塞直到拿取到对应的元素或者达到指定时间
browser.implicitly_wait(20)
browser.get("http://baidu.com")
print(browser.find_element(by=By.XPATH, value='//div[@class="content"]//img'))

# 关闭
browser.close()

继续改进,找不到元素返回None 或者其他处理:

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = webdriver.Chrome("chromedriver.exe")
# 设置等待时间,最长等待20 s。 不设置等待事件, find_element 找不到元素会抛出异常,设置完成之后不会报异常,会阻塞直到拿取到对应的元素或者达到指定时间
browser.implicitly_wait(20)
browser.get("http://baidu.com")

try:
print(browser.find_element(by=By.XPATH, value='//div[@class="content"]//img'))
except Exception as e:
# ignore
print("没有元素")

# 关闭
browser.close()

9. selenuim 双击等事件

可以用ActionChains, 最后调用其perform() 方法就是提交事件

# 找到第一个节点然后扩展
node1 = browser.find_element(by=By.XPATH,value=' //*[name()="svg"]//*[name()="g"]/*[@class="node"][1]')
# 调用ActionChains方法,生成一个动作
# 创建一个ActionChains, 然后可以进行一系列事件、包括右键、双击、单击、拖拽、键盘按下、键盘抬起等事件
action = ActionChains(browser)
# 单击
action.click(node1)
# 双击
# action.double_click(node1)
# 右击
action.context_click(node1)
action.perform()

补充: 测试过程中发现browser 关闭之后,驱动程序不会关系,需要自己cmd 关闭下:

taskkill -im chromedriver.exe -f

在自己的测试过程中发现,selenium不支持动态修改header , 而且好像不能自定义header 进行请求。可以通过插件或者其他机制实现。

=selenium-wire 简单使用=

官网: ​​https://github.com/wkeeling/selenium-wire​​ 强烈建议直接使用这个库

selenium-wire 对selenium 做了扩展,让程序有能力拿到requests 对象,然后获取请求和响应信息,并且可以修改请求头(包括自定义的头)、修改请求参数(包括param和请求体中的JSON数据)、获取修改响应头等信息。

下面演示增加自己的header:(请求拦截器与响应拦截器用法)

from seleniumwire import webdriver


# 拦截request
def interceptor_request(request):
del request.headers['mykey'] # Remember to delete the header first
request.headers['mykey'] = 'mykey-value' # Spoof the referer


# 拦截response
def interceptor_response(request, response):
if request.url == 'http://localhost:8088/inner/t4':
response.headers['New-Header'] = 'Some Value'


browser = webdriver.Chrome("chromedriver.exe")
browser.request_interceptor = interceptor_request
browser.response_interceptor = interceptor_response
browser.get("http://localhost:8088/inner/t4")

for request in browser.requests:
if request.response:
print(
request.url,
request.response.status_code,
request.response.headers
)

需要注意,进程结束之后browser 也是close 状态的,无法进行后续页面刷新或请求数据。

【当你用心写完每一篇博客之后,你会发现它比你用代码实现功能更有成就感!】



举报

相关推荐

0 条评论