要行动,要坚持,要理智,要清醒,拒绝内耗!
编程就像搭积木,不管用哪种语言解决问题,搞清需求,找到最小的积木,一切都不是问题。selenium是一个模拟浏览器操作的Python库,可以帮助我们傻瓜式爬取数据,换句话说,你在浏览器上怎么浏览数据,用selenium把你的动作实现自动化,就可以啦!
打开浏览器,打开页面
https://blog.csdn.net/qq_43965708/article/details/120658713?spm=1001.2014.3001.5506
from selenium import webdriver
# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
# 注意此处添加了chrome_options参数
driver = webdriver.Chrome(chrome_options=option)
# 打开csdn页面
driver.get('https://www.csdn.net/')
控制浏览器(最大化等等)
from time import sleep
from selenium import webdriver
# ======================================== 打开浏览器及csdn页面====================================
# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
# 注意此处添加了chrome_options参数
driver = webdriver.Chrome(chrome_options=option)
# 打开csdn页面
driver.get('https://www.csdn.net/')
# ========================================== 修改浏览器窗口大小========================================
# 设置浏览器浏览器的宽高为:600x800
driver.set_window_size(600, 800)
# 也可以使用 maximize_window() 方法可以实现浏览器全屏显示。
driver.maximize_window()
# ========================================== 浏览器前进&后退========================================
sleep(2)
# 访问CSDN个人主页
driver.get('https://blog.csdn.net/qq_43965708')
sleep(2)
# 返回(后退)到CSDN首页
driver.back()
sleep(2)
# 前进到个人主页
driver.forward()
# 在新标签中打开新链接
js = "window.open('https://blog.csdn.net/qq_42340965')"
driver.execute_script(js)
# ========================================== 浏览器刷新========================================
# 刷新页面
driver.refresh()
# ========================================== 浏览器窗口切换========================================
# 在很多时候我们都需要用到窗口切换,比如:当我们点击注册按钮时,它一般会打开一个新的标签页,但实际上代码并没有切换到最新页面中,这时你如果要定位注册页面的标签就会发现定位不到,这时就需要将实际窗口切换到最新打开的那个窗口。我们先获取当前各个窗口的句柄,这些信息的保存顺序是按照时间来的,最新打开的窗口放在数组的末尾,这时我们就可以定位到最新打开的那个窗口了。
# 获取打开的多个窗口句柄
windows = driver.window_handles
# 切换到当前最新打开的窗口
driver.switch_to.window(windows[-1])
根据各种方式定位元素
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 11:19
# @Author : zfq
from selenium import webdriver
# ========================================== 打开浏览器及页面========================================
# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
# 注意此处添加了chrome_options参数
driver = webdriver.Chrome(chrome_options=option)
# 打开csdn页面
driver.get('https://www.csdn.net/')
# ========================================== 定位标签========================================
# 根据id定位标签,标签的 id 具有唯一性
# <input id="toolbar-search-input" autocomplete="off" type="text" value="" placeholder="C++难在哪里?">
driver.find_element_by_id("toolbar-search-input")
# 根据name定位标签,在页面中可以不唯一(相同的name可以对应多个标签)
# <meta name="keywords" content="CSDN博客,CSDN学院,CSDN论坛,CSDN直播">
driver.find_element_by_name("keywords")
# 根据class定位标签,在页面中可以不唯一(相同的class可以对应多个标签)
# <div class="toolbar-search-container">
driver.find_element_by_class_name("toolbar-search-container")
# 根据tag定位,每个tag往往用来定义一类功能,所以通过 tag 来识别某个元素的成功率很低,每个页面一般都用很多相同的 tag ,比如:\<div\>、\<input\> 等。这里还是用上面的 div 作为例子。
# <div class="toolbar-search-container">
driver.find_element_by_tag_name("div")
# xpath定位
# xpath 定位的方式多样并不唯一,使用时根据情况进行解析即可。
# 绝对路径(层级关系)定位
# 绝对路径(层级关系)定位
driver.find_element_by_xpath(
"/html/body/div/div/div/div[2]/div/div/input[1]")
# 利用元素属性定位
driver.find_element_by_xpath("//*[@id='toolbar-search-input']")
# 层级+元素属性定位
driver.find_element_by_xpath(
"//div[@id='csdn-toolbar']/div/div/div[2]/div/div/input[1]")
# 逻辑运算符定位
driver.find_element_by_xpath(
"//*[@id='toolbar-search-input' and @autocomplete='off']")
# css定位
driver.find_element_by_css_selector('#toolbar-search-input')
driver.find_element_by_css_selector('html>body>div>div>div>div>div>div>input')
# link定位,link专门用来定位文本链接
# <div class="practice-box" data-v-04f46969="">加入!每日一练</div>
driver.find_element_by_link_text("加入!每日一练")
# partial_link 定位部分链接,对于有些文本很长
# # <div class="practice-box" data-v-04f46969="">加入!每日一练</div>
driver.find_element_by_partial_link_text("加入")
在input中输入+鼠标控制
from time import sleep
from selenium import webdriver
# ======================================== 打开浏览器及csdn页面====================================
# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
# 注意此处添加了chrome_options参数
driver = webdriver.Chrome(chrome_options=option)
# 打开csdn页面
driver.get('https://www.csdn.net/')
sleep(2)
# ========================================== 打开浏览器及页面========================================
# 定位搜索输入框
text_label = driver.find_element_by_xpath('//*[@id="toolbar-search-input"]')
# 在搜索框中输入 Dream丶Killer
text_label.send_keys('Dream丶Killer')
sleep(2)
# 清除搜索框中的内容
text_label.clear()
# 输出搜索框元素是否可见
print(text_label.is_displayed())
# 输出placeholder的值
print(text_label.get_attribute('placeholder'))
# ========================================== 鼠标控制========================================
# 在webdriver中,鼠标操作都封装在ACtionChains类中
# 定位搜索按钮
button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')
# 输出按钮的大小
print(button.size)
# 输出按钮上的文本
print(button.text)
# ========================================== 单击右键========================================
from selenium.webdriver.common.action_chains import ActionChains
# 右键搜索按钮
ActionChains(driver).context_click(button).perform()
# ========================================== 单击左键========================================
# 模拟完成单击鼠标左键的操作,一般点击进入子页面等会用到,左键不需要ACtionChains
button.click()
# ========================================== 执行双击动作========================================
# 双击
# 定位搜索按钮
button = driver.find_element_by_xpath('//*[@id="toolbar-search-button"]/span')
ActionChains(driver).double_click(button).perform()
# ========================================== 拖动========================================
# 定位要拖动的元素
source = driver.find_element_by_xpath('xxx')
# 定位目标元素
target = driver.find_element_by_xpath('xxx')
# 执行拖动动作
ActionChains(driver).drag_and_drop(source, target).perform()
# ========================================== 鼠标悬停========================================
# 定位收藏栏
collect = driver.find_element_by_xpath('//*[@id="csdn-toolbar"]/div/div/div[3]/div/div[3]/a')
# 悬停至收藏标签处
ActionChains(driver).move_to_element(collect).perform()
键盘控制
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 14:06
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
# ======================================== 打开浏览器及csdn页面====================================
# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
# 注意此处添加了chrome_options参数
driver = webdriver.Chrome(chrome_options=option)
# 打开csdn页面
driver.get('https://www.csdn.net/')
# ======================================== 键盘控制====================================
from selenium.webdriver.common.keys import Keys
# 定位输入框并输入文本
driver.find_element_by_id('xxx').send_keys('Dream丶killer')
# 模拟回车键进行跳转(输入内容后)
driver.find_element_by_id('xxx').send_keys(Keys.ENTER)
# 使用 Backspace 来删除一个字符
driver.find_element_by_id('xxx').send_keys(Keys.BACK_SPACE)
# Ctrl + A 全选输入框中内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'a')
# Ctrl + C 复制输入框中内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'c')
# Ctrl + V 粘贴输入框中内容
driver.find_element_by_id('xxx').send_keys(Keys.CONTROL, 'v')
设置元素等待
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 14:16
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
# ======================================== 打开浏览器及csdn页面====================================
# 不自动关闭浏览器
option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
# 注意此处添加了chrome_options参数
driver = webdriver.Chrome(chrome_options=option)
# 打开csdn页面
driver.get('https://www.csdn.net/')
# 很多页面都使用 ajax 技术,页面的元素不是同时被加载出来的,为了防止定位这些尚在加载的元素报错,可以设置元素等来增加脚本的稳定性。webdriver 中的等待分为 显式等待 和 隐式等待。
# ======================================== 显式等待====================================
# 显式等待:设置一个超时时间,每个一段时间就去检测一次该元素是否存在,如果存在则执行后续内容,如果超过最大时间(超时时间)则抛出超时异常(TimeoutException)。显示等待需要使用 WebDriverWait,同时配合 until 或 not until 。下面详细讲解一下。
# WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
# driver:浏览器驱动
# timeout:超时时间,单位秒
# poll_frequency:每次检测的间隔时间,默认为0.5秒
# ignored_exceptions:指定忽略的异常,如果在调用 until 或 until_not 的过程中抛出指定忽略的异常,则不中断代码,默认忽略的只有 NoSuchElementException 。
from selenium.webdriver.common.by import By
from selenium import webdriver
# 先定义一个定位器
driver = webdriver.Chrome()
locator = (By.ID, 'kw')
element = driver.find_element_by_id('kw')
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# until(method, message=’ ‘)
# until_not(method, message=’ ')
# method:指定预期条件的判断方法,在等待期间,每隔一段时间调用该方法,判断元素是否存在,直到元素出现。until_not 正好相反,当元素消失或指定条件不成立,则继续执行后续代码
# message: 如果超时,抛出 TimeoutException ,并显示 message 中的内容
# method 中的预期条件判断方法是由 expected_conditions 提供,下面列举常用方法。
driver = webdriver.Chrome()
element = WebDriverWait(driver, 5, 0.5).until(
EC.presence_of_element_located((By.ID, 'kw')),
message='超时啦!')
# ======================================== 隐式等待====================================
# 隐式等待也是指定一个超时时间,如果超出这个时间指定元素还没有被加载出来,就会抛出 NoSuchElementException 异常。
# 除了抛出的异常不同外,还有一点,隐式等待是全局性的,即运行过程中,如果元素可以定位到,它不会影响代码运行,但如果定位不到,则它会以轮询的方式不断地访问元素直到元素被找到,若超过指定时间,则抛出异常。
from selenium import webdriver
from time import time
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/qq_43965708')
start = time()
driver.implicitly_wait(5)
try:
driver.find_element_by_id('kw')
except Exception as e:
print(e)
print(f'耗时:{time()-start}')
# ======================================== 强制等待====================================
# 使用 time.sleep() 强制等待,设置固定的休眠时间,对于代码的运行效率会有影响。以上面的例子作为参照,将 隐式等待 改为 强制等待。
from selenium import webdriver
from time import time, sleep
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/qq_43965708')
start = time()
sleep(5)
try:
driver.find_element_by_id('kw')
except Exception as e:
print(e)
print(f'耗时:{time()-start}')
定位一组元素
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 14:41
# 定位一组元素使用的方法只需要将 element 改为 elements 即可,它的使用场景一般是为了批量操作元素。
# 这一组元素一般有相同的类名
from selenium import webdriver
# 设置无头浏览器
option = webdriver.ChromeOptions()
option.add_argument('--headless')
driver = webdriver.Chrome(options=option)
driver.get('https://blog.csdn.net/')
p_list = driver.find_elements_by_xpath("//p[@class='name']")
name = [p.text for p in p_list]
print(name)
窗口切换
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 14:44
# 在 selenium 操作页面的时候,可能会因为点击某个链接而跳转到一个新的页面(打开了一个新标签页),这时候 selenium 实际还是处于上一个页面的,需要我们进行切换才能够定位最新页面上的元素
# 窗口切换需要使用 switch_to.windows() 方法。
from selenium import webdriver
# ======================================== 窗口切换====================================
handles = []
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
# 设置隐式等待
driver.implicitly_wait(3)
# 获取当前窗口的句柄
handles.append(driver.current_window_handle)
# 点击 python,进入分类页面
driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click()
# 切换窗口
driver.switch_to.window(driver.window_handles[-1])
# 获取当前窗口的句柄
handles.append(driver.current_window_handle)
print(handles)
print(driver.window_handles)
上传文件
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 15:00
from selenium import webdriver
from pathlib import Path
from time import sleep
driver = webdriver.Chrome()
file_path = Path(Path.cwd(), '上传下载.html')
driver.get('file:///' + str(file_path))
driver.find_element_by_xpath('//*[@name="upload"]').send_keys(str(file_path))
下载文件
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 15:03
from pathlib import Path
from selenium import webdriver
prefs = {'profile.default_content_settings.popups': 0,
'download.default_directory': str(Path.cwd())}
option = webdriver.ChromeOptions()
option.add_experimental_option('prefs', prefs)
driver = webdriver.Chrome(options=option)
driver.get("https://pic.sogou.com/d?query=%E7%83%9F%E8%8A%B1&did=4&category_from=copyright")
driver.find_element_by_xpath('/html/body/div/div/div/div[2]/div[1]/div[2]/div[1]/div[2]/a').click()
driver.switch_to.window(driver.window_handles[-1])
driver.find_element_by_xpath('./html').send_keys('thisisunsafe')
cookies操作
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 15:19
# cookies是识别用户登录与否的关键,爬虫中常常使用selenium+requests实现cookie持久化
# 即先用selenium模拟登录获取cookie
# 再通过requests携带cookie进行请求
# webdriver 提供 cookies 的几种操作:读取、添加删除
# get_cookies:以字典的形式返回当前会话中可见的 cookie 信息。
# get_cookie(name):返回 cookie 字典中 key == name 的 cookie 信息。
# add_cookie(cookie_dict):将 cookie 添加到当前会话中
# delete_cookie(name):删除指定名称的单个 cookie。
# delete_all_cookies():删除会话范围内的所有 cookie。
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://blog.csdn.net/")
# 输出所有cookie信息
print(driver.get_cookies())
cookie_dict = {
'domain': '.csdn.net',
'expiry': 1664765502,
'httpOnly': False,
'name': 'test',
'path': '/',
'secure': True,
'value': 'null'}
# 添加cookie
driver.add_cookie(cookie_dict)
# 显示 name = 'test' 的cookie信息
print(driver.get_cookie('test'))
# 删除 name = 'test' 的cookie信息
driver.delete_cookie('test')
# 删除当前会话中的所有cookie
driver.delete_all_cookies()
调用js
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 15:31
# webdriver对于滚动条的处理需要用到JavaScript
# 同时也可以向textarea文本框中输入文本(webdriver 只能定位,不能输入文本)
# webdrver中使用execute_script方法实现javascript的执行
# =======================滑动滚动条===============================
# =======================通过x/y轴滑动===============================
# 对于这种通过坐标滑动的方法,我们需要知道坐标的起始位置在页面左上角
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://blog.csdn.net/")
sleep(1)
js = "window.scrollTo(0,500);"
driver.execute_script(js)
# =======================通过参照标签滑动===============================
# 这种方式需要先找一个参照标签,然后将滚动条滑动至该标签的位置。下面还是用 CSDN 首页做示例,我们用循环来实现重复滑动。该 li 标签实际是一种懒加载,当用户滑动至最后标签时,才会加载后面的数据。
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://blog.csdn.net/")
sleep(1)
driver.implicitly_wait(3)
for i in range(31, 102, 10):
sleep(1)
target = driver.find_element_by_xpath(f'//*[@id="feedlist_id"]/li[{i}]')
driver.execute_script("arguments[0].scrollIntoView();", target)
关闭页面
# -*- coding: utf-8 -*-
# @Time : 2023/2/11 15:42
# ====================================关闭当前页面====================
# 使用 close() 方法可以关闭当前页面,使用时要注意 “当前页面” 这四个字,当你关闭新打开的页面时,需要切换窗口才能操作新窗口并将它关闭。,下面看一个简单的例子,这里不切换窗口,看一下是否能够关闭新打开的页面。
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/')
driver.implicitly_wait(3)
# 点击进入新页面
driver.find_element_by_xpath('//*[@id="mainContent"]/aside/div[1]/div').click()
# 切换窗口
# driver.switch_to.window(driver.window_handles[-1])
sleep(3)
driver.close()
# ====================================关闭所有页面====================
# 使用 quit() 方法可以关闭所有窗口并退出驱动程序。
driver.quit()
12309起诉书
# -*- coding: utf-8 -*-
# @Time : 2023/2/14 13:49
import os
import time
from selenium import webdriver
from selenium.webdriver import Chrome
from pprint import pprint
from selenium.webdriver.support.wait import WebDriverWait
option = webdriver.ChromeOptions()
# option.add_argument("--headless")
# 无头浏览器需要添加user-agent来隐藏特征
# option.add_argument('--proxy-server=222.184.112.54:56099') # 使用代理ip
driver = Chrome(options=option)
driver.implicitly_wait(100)
with open('stealth.min.js') as f:
js = f.read()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": js
})
driver.get('https://www.12309.gov.cn/12309/zjxflws/index.shtml')
driver.implicitly_wait(30)
driver.refresh()
# 定位起诉意见书按钮并点击
driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[1]/ul/li[2]').click()
time.sleep(10)
# 会发现有771页起诉意见书,每一页有15条数据
for page in range(772):
for i in range(1, 16):
try:
# 获取每一个起诉意见书的标题
title = driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/ul/cmspro_documents/li[%s]/a' % i).text
# 根据标题定义文件名称变量
file_name = os.path.join(r'H:\demo\selenium_wenshu\12309', title + '.txt')
# 点击进入案件详情
driver.find_element_by_xpath('/html/body/div[3]/div[2]/div[2]/div[2]/ul/cmspro_documents/li[%s]/a' % i).click()
# 浏览器切换到最新页面
driver.switch_to.window(driver.window_handles[-1])
# 根据file_name创建文件
outf = open(file_name, 'a+', encoding='utf-8', errors='replace')
title = driver.find_element_by_class_name('detail_tit').text
# print(type(title))
# title = title.encode(errors='replace').decode()
outf.write(title)
outf.write('\n')
time1 = driver.find_element_by_class_name('detail_extend').text
# time1 = time1.encode(errors='replace').decode()
outf.write(time1)
outf.write('\n')
text = driver.find_element_by_class_name('detail_con').text
# text = text.encode(errors='replace').decode()
outf.write(text)
outf.close()
driver.close()
# 返回起诉书页面
driver.switch_to.window(driver.window_handles[0])
time.sleep(1)
except Exception as e:
print(e)
time.sleep(1)
driver.switch_to.window(driver.window_handles[0])
time.sleep(1)
continue
driver.find_element_by_class_name('nextbtn').click()
time.sleep(1)