操作多窗口与页面切换
-
有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to.window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到。
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
import time# 加载驱动
driver = webdriver.Chrome()# 拿到目标url # 这个时候发现同时拿到两个url 不能够打开两个窗口
# 访问百度
driver.get("https://www.baidu.com")
# driver.get("https://www.douban.com")
time.sleep(2)# 访问豆瓣
driver.execute_script("window.open('https://www.douban.com')")
time.sleep(2)# driver.close() # 此时发现百度被关闭了
# 检测当前驱动执行的url
print(driver.current_url)
# # 那这个时候我们操作多窗口防护变了没有了意义 因为我们只能操作第一个百度 那这个时候我就可以切换一下界面
# # 切换界面
driver.switch_to.window(driver.window_handles[1])
# # [1] 0代表的第一个最开始打开的那个 1代表的第二个 -1切换到最新打开的窗口 -2 倒数第二个打开的窗口
print(driver.current_url) # 检测看是否切换到豆瓣的url了
time.sleep(1)
# driver.switch_to.window(driver.window_handles[0])
# time.sleep(1)
# # 检测看是否能对百度进行操作
# driver.find_element(By.ID,"kw").send_keys("python")# 切换iframe
login_iframe = driver.find_element(By.XPATH,'//*[@id="anony-reg-new"]/div/div[1]/iframe')
driver.switch_to.frame(login_iframe)
time.sleep(2)
# 1 切换登录方式 定位到 密码登录(但是在这一步操作之前 要确实是否要切换iframe)
driver.find_element(By.CLASS_NAME,"tab-start").click()
time.sleep(2)
# 2 输入账号和密码
user_input = driver.find_element(By.ID,"username").send_keys("123456789")
time.sleep(2)
pwd_input = driver.find_element(By.ID,"password").send_keys("123456789")
time.sleep(2)
# 3 点击登录豆瓣
# 定位登录按钮点击 我们在定位元素的时候 如果属性出现空格的状态 形如:btn btn-account
# 解决方式 第一种我们选择属性当中的一部分(需要测试)
driver.find_element(By.CLASS_NAME,'btn-account').click()
time.sleep(3)
Selenium执行js语法
有时候selenium提供的方法会出现一些问题,或者执行起来非常麻烦,我们就可以考虑通过selenium执行javascript来实现,使复杂的操作简单化。 selenium执行js脚本的方法:
execute_script(script, *args) 描述:用来执行js语句 参数: script:待执行的js语句,如果有多个js语句,使用英文分号;连接
常见selenium下执行js代码
1 滚动页面:您可以使用 JavaScript 滚动网页以将元素显示在视图中或在页面上移动
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')2 js点击:
button = driver.find_element(By.CLASS_NAME),'my-button')
driver.execute_script("arguments[0].click();", button)3 等待元素出现:有时候,您需要等待一个元素出现或变为可见状态后再与它进行交互。
您可以使用JavaScript等待元素出现或变为可见状态后再进行交互。
# 等待元素在页面上可见
element = driver.find_element(By.CSS_SELECTOR,'#my-element')
driver.execute_script("""
var wait = setInterval(function() {
if (arguments[0].offsetParent !== null) {
clearInterval(wait);
// 元素现在可见,可以对其进行操作
}
}, 100);
""", element)4 执行自定义JavaScript:使用execute_script方法可以执行您编写的任何自定义 JavaScript 代码,
以完成测试或自动化任务。
driver.execute_script("console.log('Hello, world!');")5 打开多窗口
driver.execute_script("window.open('https://www.douban.com')")
** 这一块的只是示例 不用同学们进行记忆 但是我们可以积累 **
Selenium高级语法
-
page_source (elements源代码)
-
find() (在网页源码中寻找某个字符串是否存在)
-
find_element(By.LINK_TEXT) (根据链接文本获取 一般处理翻页)
-
node.get_attribute (node 代表的是节点名 get_attribute代表的是获取属性名)
-
node.text() (获取节点的文本内容 包含子节点和后代节点)
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
import time# 加载驱动
driver = webdriver.Chrome()# 访问百度
# driver.get('https://www.baidu.com/')"""
1拿到百度的数据结构源码 page_source
这个指的不是网页源代码而是我们前端页面最终渲染的结果也就是我们element中的数据
"""
# html = driver.page_source
# print(html)"""
2 find() 在html源码中查找某个字符是否存在
如果存在则会返回一段数字 如果不存在 不会报错 但是会返回-1
find应用场景 比如翻页爬取
"""
# print(html.find("kw"))
# print(html.find("kwwwwwwwwwwwwwwwwwww"))""" 3 find_element_by_link_text("链接文本")
# driver.get('https://www.gushiwen.cn/')
# time.sleep(3)
# # 根据链接文本内容定位按钮
# driver.find_element(By.LINK_TEXT,'下一页').click() # 点击豆瓣第一页的下一页
# # 画面会跳转到第二页 打印的是第二页的源码
# time.sleep(3)
# print(driver.page_source)"""4 node.get_attribute("属性名") node代表的是你想获取的节点 """
# url = 'https://movie.douban.com/top250'
# driver.get(url)
# a_tag = driver.find_element(By.XPATH,'//div[@class="item"]/div[@class="pic"]/a')
# print(a_tag.get_attribute('href'))""" 5 node.text 获取节点的文本内容 包含子节点和后代节点 """
# driver.get('https://movie.douban.com/top250')
# time.sleep(2)
# div_tag = driver.find_element(By.XPATH,'//div[@class="hd"]')
# print(div_tag.text)
Selenium设置无界面模式
绝大多数服务器是没有界面的,selenium控制谷歌浏览器也是存在无界面模式的(又称之为无头模式) 开启无界面模式的方法
-
实例化配置对象
options = webdriver.ChromeOptions()
-
配置对象添加开启无界面模式的命令
options.add_argument("--headless")
-
配置对象添加禁用gpu的命令
options.add_argument("--disable-gpu")
-
实例化带有配置对象的driver对象
driver = webdriver.Chrome(chrome_options=options)
from selenium import webdriver
# 创建一个配置对象
options = webdriver.ChromeOptions()
# 开启无界面模式
options.add_argument('--headless')
# 实例化带有配置的driver对象
driver = webdriver.Chrome(options=options)driver.get('http://www.baidu.com/')
html = driver.page_source
print(html)
driver.quit()
Selenium被识别问题解决方案
selenium做爬虫能解决很多反爬问题,但是selenium也有很多特征可以被识别,比如用selenium驱动浏览器后window.navigator.webdriver值是true,而正常运行浏览器该值是未定义的(undefined)
import time
from selenium import webdriver
# 使用chrome开发者模式
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])# 禁用启用Blink运行时的功能
options.add_argument("--disable-blink-features=AutomationControlled")# Selenium执行cdp命令 再次覆盖window.navigator.webdriver的值
driver = webdriver.Chrome(options=options)
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
driver.get('https://www.baidu.com/')time.sleep(3)
Selenium综合案例之当当网书籍信息爬取
import csv
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
"""
爬取当当网python爬虫书籍信息并保存到csv文件中
"""class DDspider:
# 初始化方法
def __init__(self):
# 加载驱动
self.driver = webdriver.Chrome()# 发起请求
self.driver.get('http://www.dangdang.com/')# 窗口最大化
# self.driver.maximize_window()# 定位输入框
ipt_tag = self.driver.find_element(By.ID, 'key_S')
ipt_tag.send_keys('python爬虫')
time.sleep(1)# 定位搜索框
serach_ipt = self.driver.find_element(By.CLASS_NAME, 'button')
serach_ipt.click()
time.sleep(1)# 解析目标数据
def Getitem(self):
# 将滚轮拉到底部为的是让全部的source进行加载完全
"""想办法把滚轮拖动到最后"""
# window.scrollTo 拖动滚轮 第一个参数0 表示从起始位置开始拉 第二个参数表示的是整个窗口的高度
self.driver.execute_script(
'window.scrollTo(0,document.body.scrollHeight)' # 这一点属于js代码 不需要死记 但是需要积累
)
time.sleep(1)lilist = self.driver.find_elements(By.XPATH, '//ul[@id="component_59"]/li')
print(len(lilist))# 定义列表用于存放一页中所有书的信息
books = []
for i, item in enumerate(lilist):
try:
# 定义字典用于存放每一本书的信息
book = {}
# 书图
if i == 0:
book['img'] = item.find_element(By.XPATH, './a/img').get_attribute('src')
else:
book['img'] = 'https:' + item.find_element(By.XPATH, './a/img').get_attribute('data-original')# 书名
book['name'] = item.find_element(By.XPATH, './p[@class="name"]/a').get_attribute('title')# 价格
book['price'] = item.find_element(By.XPATH, './p[@class="price"]/span').text# 作者
book['author'] = item.find_element(By.XPATH, './p[@class="search_book_author"]/span[1]').text# 出版时间
book['Publication_time'] = item.find_element(By.XPATH, './/p[@class="search_book_author"]/span[2]').text# 出版社
book['Publishing_house'] = item.find_element(By.XPATH, './/p[@class="search_book_author"]/span[3]').textbooks.append(book)
except Exception as e:
print(e.__class__.__name__)# print(books,len(books))
return books# 翻页函数
def Next_page(self):
alldata = []
while True:
books = self.Getitem()
alldata += books
print(len(alldata),"*" * 50)
if self.driver.page_source.find("next none") == -1:
next_tag = self.driver.find_element(By.XPATH, '//li[@class="next"]/a')
self.driver.execute_script("arguments[0].click();", next_tag)
time.sleep(1)
else:
self.driver.quit()
break
return alldata# 写入数据
def WriteData(self,alldata):
headers = ('img', 'name', 'price', 'author','Publication_time','Publishing_house')
with open('当当.csv', mode='w', encoding='utf-8', newline="")as f:
writer = csv.DictWriter(f, headers)
writer.writeheader() # 写入表头
writer.writerows(alldata)if __name__ == '__main__':
DD = DDspider()
alldata = DD.Next_page()
DD.WriteData(alldata)