python进阶-05-利用Selenium来实现动态爬虫

python进阶-05-利用Selenium来实现动态爬虫

一.说明

这是python进阶部分05,我们上一篇文章学习了Scrapy来爬取网站,但是很多网站需要登录才能爬取有用的信息,或者网站的静态部分是一个空壳,内容是js动态加载的,或者人机验证,请求拦截转发等,那么这种情况Scrapy来爬取就很费劲,有人说我们可以分析登录接口,js加载内容实现爬取我们需要的内容,哼哼你想多了,请求内容经过服务器转发给你加过包的!所以还是不行,那就没有办法来抓取我们想要的数据了么?

有,就是Selenium动态爬取网页信息,Selenium会启动和控制浏览器直接实现自动登录,Selenium直接运行在浏览器中从而可以直接爬取js加载完的信息。

那么Selenium这么强大有没有什么缺陷?也是有的,效率不高!

但省事啊,就跟Python一样!人生苦短,我用Python,好,继续开始我们的日拱一卒,让我们彻底掌握这一技术!。

二.安装

要使用Selenium,就得先安装,但是Selenium安装不仅仅需要安装Selenium python库,还要在python虚拟环境中安装对应的浏览器驱动!所以安装Selenium分别为 安装Selenium Python库 下载和安装浏览器及对应浏览器的驱动

  1. 下载Selenium库

    pip install selenium -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com
    
  2. 下载对应浏览器和驱动

    1. Chrome的驱动chromedriver

      #谷歌浏览器驱动官方
      https://chromedriver.storage.googleapis.com/index.html 
      # 谷歌浏览器官方开发者文档
      # https://developer.chrome.com/docs/chromedriver/downloads?hl=zh-cn
      #谷歌浏览器历史版本下载
      https://downzen.com/en/windows/google-chrome/versions/?page=1
      #禁用谷歌浏览器更新,大家可看下面的文章,在此不进行重复说明
      #chrome://version/ 查看浏览器版本和安装文件夹
      https://blog.csdn.net/weixin_65228312/article/details/141724054

      在这里插入图片描述

      通过测试发现chromedriver下载的均为支持最新版本的谷歌浏览器,大家安装最新浏览器即可!

      如果驱动不支持 会提示您应该安装的浏览器版本,安装指定浏览器版本,和禁用浏览器更新即可。

    2. Firefox的驱动geckodriver下载地址

      https://github.com/mozilla/geckodriver/releases/
      

      在这里插入图片描述

    3. IE/微软Edge的驱动IEdriver下载地址

      https://www.nuget.org/packages/Selenium.WebDriver.IEDriver/
      
  3. 为了帮助大家快速理解,我已经准备了一套Firefox浏览器和对应驱动geckodriver,一套谷歌131版本的浏览器驱动,在我的资源里面,大家可以直接下,下载地址如下

    #Firefox的驱动geckodriver
    https://download.csdn.net/download/Lookontime/90059540
    #Chrome的驱动chromedriver
    https://download.csdn.net/download/Lookontime/90091812
    
  4. 如何安装,浏览器直接安装,geckodriver.exe 驱动文件放到 我们的虚拟python环境的Scripts中即可

    #直接复制到虚拟环境 Scripts中即可,如果没有装虚拟环境的小伙 直接将驱动放到python跟目录下
    F:\python_demo_07\my_venv\Scripts
    

三.启动selenium驱动浏览器的方法

  1. 启动谷歌浏览器来爬取内容

    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys #提供键盘按键的支持,如回车键 RETURNbrowser = webdriver.Chrome(executable_path="F:/python_demo_07/my_venv/Scripts/chromedriver.exe")
    browser.get('http://www.myurlhub.com')
    elem = browser.find_element_by_name("q") #获取节点
    elem.clear()                            #清除搜索框中的默认文本
    elem.send_keys("pycon")                 #输入 "pycon"
    elem.send_keys(Keys.RETURN)             #模拟按下键盘的回车键 RETURN,触发搜索
    assert "No results found." not in driver.page_source #断言页面标题中包含 "Python"。如果不包含,则抛出异常
    browser.close() #关闭浏览器窗口
    
  2. 启动Firefox

    from selenium import webdriver
    browser = webdriver.Firefox(executable_path="F:/python_demo_07/my_venv/Scripts/geckodriver.exe")
    browser.get('http://www.myurlhub.com')
    
  3. 启动IE(不推荐 古老项目可能需要吧)

    from selenium import webdriver
    browser = webdriver.Ie(executable_path="F:/python_demo_07/my_venv/Scripts/IEDriver .exe")
    browser.get('http://www.myurlhub.com')
    

四.selenium的详细用法

4.1 声明浏览器对象

from selenium import webdriver
browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Safari()
browser = webdriver.Edge()
browser = webdriver.PhantomJS()

4.2 访问页面

from selenium import webdriver
browser = webdriver.Chrome(executable_path="F:/python_demo_07/my_venv/Scripts/chromedriver.exe")
browser.get('http://www.myurlhub.com')
print(browser.page_source) #打印页面源代码
browser.close() #关闭浏览器窗口

4.3 查找单个元素

from selenium import webdriver
from selenium.webdriver.common.by import By #
browser = webdriver.Chrome(executable_path="F:/python_demo_07/my_venv/Scripts/chromedriver.exe")
browser.get('http://www.myurlhub.com')
# 1. 根据 ID 查找元素
element_by_id = browser.find_element(By.ID, "element_id")
element_by_id = browser.find_element_by_id("element_id")# 2. 根据 name 属性查找元素
element_by_name = browser.find_element(By.NAME, "element_name")# 3. 根据 class 名称查找元素
element_by_class_name = browser.find_element(By.CLASS_NAME, "class_name")
element_by_class_name = browser.find_element_by_css_selector("#class_name")
# 4. 根据标签名查找元素
element_by_tag_name = browser.find_element(By.TAG_NAME, "tag_name")# 5. 使用 CSS 选择器查找元素
element_by_css = browser.find_element(By.CSS_SELECTOR, ".class_name #element_id")# 6. 使用 XPath 查找元素
element_by_xpath = browser.find_element(By.XPATH, "//div[@class='class_name']")
browser.close() #关闭浏览器窗口

4.4 查找多个元素

from selenium import webdriver
from selenium.webdriver.common.by import By# 启动 Chrome 浏览器
browser = webdriver.Chrome(executable_path="F:/python_demo_07/my_venv/Scripts/chromedriver.exe")# 打开指定网址
browser.get('http://www.myurlhub.com')# 1. 根据 class 名查找多个元素
elements_by_class_name = browser.find_elements(By.CLASS_NAME, "class_name")
element_by_class_name = browser.find_element_by_css_selector("#class_name")
# 2. 根据标签名查找多个元素
elements_by_tag_name = browser.find_elements(By.TAG_NAME, "tag_name")# 3. 使用 CSS 选择器查找多个元素
elements_by_css = browser.find_elements(By.CSS_SELECTOR, ".class_name #element_id")# 4. 使用 XPath 查找多个元素
elements_by_xpath = browser.find_elements(By.XPATH, "//div[@class='class_name']")# 输出查找到的元素个数
print(f"找到 {len(elements_by_class_name)} 个元素")

4.5元素的交互操作

from selenium import webdriver
from selenium.webdriver.common.by import By# 启动 Chrome 浏览器
browser = webdriver.Chrome(executable_path="F:/python_demo_07/my_venv/Scripts/chromedriver.exe")# 打开指定网址
browser.get('http://www.myurlhub.com')#点击按钮
button = browser.find_element(By.ID, "submit_button")
button.click()  # 点击按钮#输入文本
input_box = browser.find_element(By.NAME, "username")
input_box.send_keys("my_username")  # 输入文本#清除文本框内容
input_box.clear()  # 清空输入框#获取元素文本
paragraph = browser.find_element(By.TAG_NAME, "p")
print(paragraph.text)  # 输出段落的文本内容#获取元素属性
link = browser.find_element(By.LINK_TEXT, "Python")
href = link.get_attribute("href")  # 获取链接的 href 属性
print(href)#提交表单
form = browser.find_element(By.ID, "search_form")
form.submit()  # 提交表单#悬停操作from selenium.webdriver.common.action_chains import ActionChains #引入动作链element = browser.find_element(By.ID, "hover_element")
actions = ActionChains(browser)
actions.move_to_element(element).perform()  # 悬停在元素上#拖放操作
source = browser.find_element(By.ID, "drag_source")
target = browser.find_element(By.ID, "drop_target")actions = ActionChains(browser)
actions.drag_and_drop(source, target).perform()  # 拖放操作#键盘操作
from selenium.webdriver.common.keys import Keysinput_box = browser.find_element(By.NAME, "query")
input_box.send_keys("selenium" + Keys.ENTER)  # 输入文本并回车#切换到 iframe
iframe = browser.find_element(By.TAG_NAME, "iframe")
browser.switch_to.frame(iframe)  # 切换到 iframe

4.6 执行JavaScript 脚本

#执行简单 JavaScript 脚本
browser.execute_script("alert('Hello from Selenium!');")
#操作 DOM 元素
element = browser.find_element(By.ID, "my_element")
browser.execute_script("arguments[0].style.backgroundColor = 'yellow';", element)
#获取js执行结果
title = browser.execute_script("return document.title;")
print(title)  # 输出页面标题
#滚动页面
# 滚动到页面底部
browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")# 滚动到特定元素
element = browser.find_element(By.ID, "target_element")
browser.execute_script("arguments[0].scrollIntoView(true);", element)
#添加动态内容
browser.execute_script("document.body.innerHTML += '<p>Added by Selenium</p>';")
#处理窗口大小和位置
# 调整窗口大小
browser.execute_script("window.resizeTo(1024, 768);")# 获取窗口位置
position = browser.execute_script("return window.screenX, window.screenY;")
print(position)

4.7 获取元素信息

element = browser.find_element(By.ID, "my_element")
print(element.text)  # 输出元素的文本内容element = browser.find_element(By.NAME, "username")
value = element.get_attribute("value")  # 获取输入框的值
print(value)href = element.get_attribute("href")  # 获取链接的 href 属性
print(href)element = browser.find_element(By.CLASS_NAME, "button")
color = element.value_of_css_property("color")  # 获取按钮的文字颜色
print(color)element = browser.find_element(By.ID, "my_element")
print(element.tag_name)  # 输出标签名,如 'div'、'input'element = browser.find_element(By.ID, "my_element")
print(element.size)      # 输出元素的宽度和高度 {'width': 100, 'height': 50}
print(element.location)  # 输出元素的位置 {'x': 50, 'y': 100}element = browser.find_element(By.ID, "my_element")
print(element.is_displayed())  # 检查元素是否可见
print(element.is_enabled())    # 检查元素是否启用
print(element.is_selected())   # 检查复选框或单选按钮是否选中element = browser.find_element(By.ID, "my_element")
print(element.is_displayed())  # 检查元素是否可见
print(element.is_enabled())    # 检查元素是否启用
print(element.is_selected())   # 检查复选框或单选按钮是否选中element = browser.find_element(By.ID, "my_element")
print(element.get_attribute("outerHTML"))  # 输出元素的完整 HTML
print(element.get_attribute("innerHTML"))  # 输出元素内部的 HTML

4.8 等待

等待的目的是确保操作的元素已经出现在页面上,避免因加载延迟导致的异常,Selenium 中等待分为隐式等待和显式等待

4.8.1 隐式等待

对整个 WebDriver 会话生效,隐式等待会在查找元素时,等待一定的时间。如果在超时时间内找到了元素,就继续执行;如果超时,抛出 NoSuchElementException

from selenium import webdriverbrowser = webdriver.Chrome()
browser.implicitly_wait(10)  # 设置隐式等待时间为10秒browser.get("http://example.com")
element = browser.find_element(By.ID, "my_element")  # 如果元素在10秒内加载完成,立即返回

4.8.2 显式等待

显式等待会针对特定条件或特定元素等待指定时间。可以结合条件使用,比如等待元素可见、可点击等。

Selenium 提供了一些常见的等待条件,配合显式等待使用:

  • presence_of_element_located: 等待元素出现在 DOM 中,但不一定可见。
  • visibility_of_element_located: 等待元素出现在 DOM 中并可见。
  • element_to_be_clickable: 等待元素可以被点击。
  • text_to_be_present_in_element: 等待某元素的文本出现。
  • alert_is_present: 等待弹窗出现。
#等待元素点击
from selenium.webdriver.common.by import By
from selenium.webdriver.common.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECbrowser = webdriver.Chrome()browser.get("http://example.com")# 等待最多10秒,直到元素可被点击
element = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID, "my_element"))
)
element.click()  # 点击元素#等待元素可见
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC# 等待元素可见,最多 10 秒
element = WebDriverWait(browser, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, "visible-element"))
)
element2 = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'p img'))
)
print(element.text)  # 输出元素文本#等待文本出现在元素中,等待元素中出现特定文本 "Success"。
element = WebDriverWait(browser, 10).until(EC.text_to_be_present_in_element((By.ID, "status"), "Success")
)
print("Text found!")#等待多个元素加载完成
elements = WebDriverWait(browser, 10).until(EC.presence_of_all_elements_located((By.TAG_NAME, "li"))
)
for element in elements:print(element.text)#等待按钮变为可点击状态
button = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".submit-button"))
)
button.click()  # 点击按钮#等待 iframe 可切换
iframe = WebDriverWait(browser, 10).until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe"))
)
print("Switched to iframe")
iframe = WebDriverWait(browser, 10).until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME, "iframe"))
)
print("Switched to iframe")# 等待 alert 弹窗出现
alert = WebDriverWait(browser, 10).until(EC.alert_is_present())
alert.accept()  # 接受 alert 弹窗#等待元素属性变化 等待元素的 class 属性变为 "completed"。
element = browser.find_element(By.ID, "progress")
WebDriverWait(browser, 10).until(lambda driver: element.get_attribute("class") == "completed"
)
print("Progress completed!")#等待页面标题变更
WebDriverWait(browser, 10).until(EC.title_contains("Dashboard"))
print("Page loaded with expected title!")#等待特定元素不可见
WebDriverWait(browser, 10).until(EC.invisibility_of_element_located((By.ID, "loading-spinner"))
)
print("Spinner disappeared!")#等待文件下载完成(JavaScript 控制按钮触发下载)点击下载按钮后,通过检查页面的 cookie 确认文件下载完成。
download_button = WebDriverWait(browser, 10).until(EC.element_to_be_clickable((By.ID, "download-btn"))
)
download_button.click()WebDriverWait(browser, 20).until(lambda driver: "file_downloaded=true" in driver.execute_script("return document.cookie")
)
print("File download completed!")

4.9 浏览器的前进和后退,刷新等操作

from selenium import webdriver
import timebrowser = webdriver.Chrome()# 打开两个页面
browser.get("https://www.example.com")
time.sleep(2)  # 等待页面加载
browser.get("https://www.google.com")
time.sleep(2)# 后退到第一个页面
browser.back()
print("后退到:", browser.current_url)# 前进到第二个页面
browser.forward()
print("前进到:", browser.current_url)# 刷新页面
browser.refresh()
print("页面已刷新")

4.10 cookies处理(了解即可 selenium 不需要操作cookies)

from selenium import webdriverbrowser = webdriver.Chrome()# 打开网站
browser.get("https://www.example.com")# 添加 Cookie
browser.add_cookie({"name": "my_cookie", "value": "cookie_value"})# 获取所有 Cookies
print("所有 Cookies:", browser.get_cookies())# 获取指定 Cookie
print("单个 Cookie:", browser.get_cookie("my_cookie"))# 删除指定 Cookie
browser.delete_cookie("my_cookie")# 删除所有 Cookies
browser.delete_all_cookies()
# 刷新页面以使添加和删除cookie 生效
browser.refresh()browser.quit()

4.11 JWT令牌处理(了解即可 selenium 不需要操作JWT 和发送请求)

#方式一 from selenium import webdriver
from selenium.webdriver.common.by import By# 初始化浏览器
browser = webdriver.Chrome()# 打开目标页面(需与 JWT 的域匹配)
browser.get("https://www.example.com")# 添加 JWT 令牌到 Cookie
jwt_token = "your_jwt_token_here"
browser.add_cookie({"name": "Authorization",  # 一般服务端会使用这个名称,但请根据具体情况修改"value": f"Bearer {jwt_token}","domain": "www.example.com",  # 确保域名与当前页面匹配"path": "/"
})# 刷新页面或访问需要 JWT 身份验证的页面
browser.refresh()# 验证是否登录成功
print("Current URL:", browser.current_url)#方式二browser.execute_script("""fetch('https://www.example.com/protected', {method: 'GET',headers: {'Authorization': 'Bearer your_jwt_token_here'}}).then(response => response.json()).then(data => console.log(data));
""")

4.12 切换页面操作

#页面切换
from selenium import webdriver
import timebrowser = webdriver.Chrome()# 打开第一个页面
browser.get("https://www.example.com")
print("当前窗口句柄:", browser.current_window_handle)# 打开新标签页
browser.execute_script("window.open('https://www.google.com');")
time.sleep(2)  # 等待页面加载# 获取所有窗口句柄
handles = browser.window_handles
print("所有窗口句柄:", handles)# 切换到新标签页(第二个窗口)
browser.switch_to.window(handles[1])
print("当前窗口句柄:", browser.current_window_handle)
print("当前页面 URL:", browser.current_url)# 切换回第一个窗口
browser.switch_to.window(handles[0])
print("当前窗口句柄:", browser.current_window_handle)
print("当前页面 URL:", browser.current_url)browser.quit()
#iframe 切换
from selenium import webdriverbrowser = webdriver.Chrome()
browser.get("https://www.example.com")# 切换到 iframe
iframe = browser.find_element_by_tag_name("iframe")
browser.switch_to.frame(iframe)# 在 iframe 内部执行操作
element = browser.find_element_by_id("inner_element")
element.click()# 切换回主页面
browser.switch_to.default_content()# 继续在主页面操作
browser.quit()

五.案例一 爬取翻译内容(技术文章仅用于学习与研究目的,不得用于违法行为,如需要翻译接口请购买正版翻译接口)

别看百度翻译很简单,其实我们直接Requests百度翻译或者Scrapy 会发现当字符超过一定长度,就无法获取结果,因为页面结果是js动态生成的!

针对这种情况,就需要分析页面结构,隐藏接口等情况,才能爬取,且翻译的字符超过一定数量接口就会改变,导致我们在做百度翻译,失败!

但是现在不同的!这时候就适合用selenium技术!不用哪些花里胡哨的的操作!

但是利用selenium技术,爬取页面内容会很慢,如需翻译接口,请购买百度翻译接口,本文主要是用来解释selenium技术。

1.开发环境

python 3.6.8

火狐浏览器:65.0.2 (64 位)

#Firefox的驱动geckodriver
https://download.csdn.net/download/Lookontime/90059540

1.我们新建一个FastAPI接口,创建和启用FastAPI接口,看我的这篇文章:

https://blog.csdn.net/Lookontime/article/details/143696629

2.在项目文件夹中创建main.py 代码如下

#main.pyfrom fastapi import FastAPI
from api.crawler import fanyi
app = FastAPI()# 包含用户相关的所有路由
app.include_router(fanyi.router, prefix="/crawler", tags=["CrawlerAPI"])

3.创建api文件夹 用作FastAPI路由

api文件夹下新建:__init__.py 文件 及crawler文件夹,其中__init__.py无任何内容

crawler文件夹下新建:fanyi.pyparams.py 文件

代码如下:

params.py 文件

#params.py
from pydantic import BaseModel
from typing import List, Optional
class FanyiParams(BaseModel):query: strlang: str = 'en2zh'ext_channel: str = 'DuSearch'

fanyi.py文件

#fanyi.py
from fastapi import APIRouter, HTTPException
from selenium import webdriver
from .params import *
#确保页面加载完成,避免异步调用导致异常
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECrouter = APIRouter()@router.post("/baidu_fanyi")
def baidu_fanyi(params:FanyiParams):try:# 设置 Firefox 的无头模式options = Options()options.headless = True  # 启用无头模式,避免打开实际浏览器browser = webdriver.Firefox(executable_path="F:/python_demo_07/my_venv/Scripts/geckodriver.exe", options=options)browser.get(f'https://fanyi.baidu.com/mtpe-individual/multimodal?query={params.query}&lang={params.lang}&ext_channel={params.ext_channel}')# 等待页面中某个元素加载完成WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, 'trans-selection')))fanyi = browser.find_element(By.ID, "trans-selection")fanyi_text = fanyi.textprint("翻译结果",fanyi_text)browser.close() # html = browser.page_source  # 获取完整 HTML 内容  return fanyi_textexcept Exception as e:print(f"发生错误: {e}")return {"error": "无法获取翻译结果"}

4.启动FastAPI

(my_venv) PS F:\python_demo_07> uvicorn main:app  --port 8082

但是很抱歉截止文章发布前,这种原生的selenium应用已经无法爬取翻译内容了

5.升级selenium

开发环境,这次我们用谷歌浏览器

python 3.12.6

谷歌浏览器:131.0.6778.109

#Chrome的驱动chromedriver
https://download.csdn.net/download/Lookontime/90091812

插件:undetected_chromedriver

pip install undetected_chromedriver -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com

因为selenium很容易被检测到是selenium驱动的浏览器,所以我们需要让浏览器检测不到

代码替换如下:

from fastapi import APIRouter, HTTPExceptionfrom .params import *
#确保页面加载完成,避免异步调用导致异常
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECrouter = APIRouter()@router.post("/baidu_fanyi")
def baidu_fanyi(params:FanyiParams):try:# 设置 无头模式options = uc.ChromeOptions()# 添加无头模式选项options.add_argument('--headless')# 添加其他必要参数options.add_argument('--disable-gpu')  # 禁用 GPUoptions.add_argument('--no-sandbox')  # 避免沙盒模式问题(可选)options.add_argument('--disable-dev-shm-usage')  # 防止共享内存问题(可选)options.add_argument('--window-size=1920,1080')  # 设置窗口大小options.add_argument('--disable-blink-features=AutomationControlled')  # 禁用自动化控制检测browser = uc.Chrome(executable_path="F:/开发源码/python_demo_07/my_venv_3_12_6/Scripts/chromedriver.exe", options=options)browser.get(f'https://fanyi.baidu.com/mtpe-individual/multimodal?query={params.query}&lang={params.lang}&ext_channel={params.ext_channel}')# 等待页面中某个元素加载完成WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, 'trans-selection')))fanyi = browser.find_element(By.ID, "trans-selection")fanyi_text = fanyi.textprint("翻译结果",fanyi_text)browser.close() # html = browser.page_source  # 获取完整 HTML 内容  return fanyi_textexcept Exception as e:print(f"发生错误: {e}")return {"error": "无法获取翻译结果"}

ok这次我们又可以了

六.案例二 利用selenium技术爬取壁纸(技术文章仅用于学习与研究目的,不得用于违法行为,如需要壁纸请购买)

这次我们测试selenium技术的壁纸网站是https://pic.netbian.com/new/ 我看很多大佬已经拿这个网站实验过了,但是现在想爬这个网站是有点难度了,因为网站加了一个人机验证,我们通过selenium会被认为是机器人,就拒绝我们访问!如果用Scrapy 那更不行了。。。好!看我们搞定!

在这里插入图片描述

6.1开发环境

python 3.12.6

谷歌浏览器:131.0.6778.109

#Chrome的驱动chromedriver
https://download.csdn.net/download/Lookontime/90091812

插件:undetected_chromedriver

pip install undetected_chromedriver -i http://pypi.doubanio.com/simple --trusted-host pypi.doubanio.com

6.2修改params.py 文件

#params.py文件
from pydantic import BaseModel
from typing import List, Optional
class FanyiParams(BaseModel):query: strlang: str = 'en2zh'ext_channel: str = 'DuSearch'# lang: Optional[str] = 'zh2en'# ext_channel: Optional[str] = 'DuSearch'class BiziParams(BaseModel):keyboard: str

6.3新增servers类库

  1. 在主目录在新增servers文件夹
  2. servers文件夹下新增__init__.py文件内容为空
  3. servers文件夹下新增seleniumHelper文件夹
  4. seleniumHelper文件夹 新增index.py文件
#index.py
import base64
from io import BytesIO
import os
from pathlib import Path
import re
import time
from PIL import Image#确保页面加载完成,避免异步调用导致异常
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECclass seleniumInit:def __init__(self):options = uc.ChromeOptions()options.add_argument('--disable-gpu')self.driver = uc.Chrome(executable_path="F:/开发源码/python_demo_07/my_venv_3_12_6/Scripts/chromedriver.exe", options=options)self.keyboard = Nonedef start_requests(self,keyboard='手机'):self.keyboard = keyboard# 初始页面只需要加载一次并输入关键词url = "https://pic.netbian.com/new/"self.driver.get(url)WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.NAME, 'keyboard')))input_box = self.driver.find_element(By.NAME, "keyboard")input_box.clear()input_box.send_keys(keyboard + Keys.RETURN)# 等待页面跳转到搜索结果页WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'nextpage')))# 从搜索结果开始解析self.parse_with_selenium(self.driver.current_url)def parse_with_selenium(self, url):self.driver.get(url)WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, "//a[@target='_blank']")))next_page_element = self.driver.find_element(By.XPATH, "//li[@class='nextpage']/a")next_page_href = next_page_element.get_attribute('href')a_list = self.driver.find_elements(By.XPATH, "//a[@target='_blank']")hrefs = [a.get_attribute('href') for a in a_list if a.get_attribute('href')]for href in hrefs:if href.startswith('https://pic.netbian.com/tupian'):print(f"发现链接: {href}")self.get_img(href)# 处理下一页try:if next_page_href:self.parse_with_selenium(next_page_href)except Exception:print("没有下一页")def get_img(self, url):self.driver.get(url)WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, 'a#img img')))img_element = self.driver.find_element(By.CSS_SELECTOR, 'a#img img')img_src = img_element.get_attribute('src')if img_src:# 确保 URL 是完整的img_url = img_src if img_src.startswith('http') else f"https://pic.netbian.com{img_src}"print('准备下载图片:', img_url)# 下载并保存图片# 设置保存图片的文件夹路径save_folder = f"F:/ImageFiles/{self.keyboard}/"  # 你可以根据需要修改这个路径if not os.path.exists(save_folder):os.makedirs(save_folder)  # 如果文件夹不存在,则创建# 合成完整的文件路径file_name = img_url.split('/')[-1]file_path = os.path.join(save_folder, file_name)js = "let c = document.createElement('canvas');let ctx = c.getContext('2d');" \"let img  = document.querySelector('a#img img'); /*找到图片*/ " \"c.height=img.naturalHeight;c.width=img.naturalWidth;" \"ctx.drawImage(img, 0, 0,img.naturalWidth, img.naturalHeight);" \"let base64String = c.toDataURL();return base64String;"base64_str = self.driver.execute_script(js)img = self.base64_to_image(base64_str)print("最终img",img)# 转换为RGB模式(如果是RGBA)if img.mode == 'RGBA':img = img.convert('RGB')img.save(file_path, format='JPEG')time.sleep(6)print(f'图片已保存: {file_name}')def base64_to_image(self,base64_str):base64_data = re.sub('^data:image/.+;base64,', '', base64_str)byte_data = base64.b64decode(base64_data)image_data = BytesIO(byte_data)img = Image.open(image_data)return img

6.4 修改fanyi.py文件添加一个接口

#fanyi.py
from fastapi import APIRouter, HTTPExceptionfrom .params import *
#确保页面加载完成,避免异步调用导致异常
import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from servers.seleniumHelper.index import seleniumInitrouter = APIRouter()@router.post("/baidu_fanyi")
def baidu_fanyi(params:FanyiParams):try:# 设置 无头模式options = uc.ChromeOptions()# 添加无头模式选项options.add_argument('--headless')# 添加其他必要参数options.add_argument('--disable-gpu')  # 禁用 GPUoptions.add_argument('--no-sandbox')  # 避免沙盒模式问题(可选)options.add_argument('--disable-dev-shm-usage')  # 防止共享内存问题(可选)options.add_argument('--window-size=1920,1080')  # 设置窗口大小options.add_argument('--disable-blink-features=AutomationControlled')  # 禁用自动化控制检测browser = uc.Chrome(executable_path="F:/开发源码/python_demo_07/my_venv_3_12_6/Scripts/chromedriver.exe", options=options)browser.get(f'https://fanyi.baidu.com/mtpe-individual/multimodal?query={params.query}&lang={params.lang}&ext_channel={params.ext_channel}')# 等待页面中某个元素加载完成WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, 'trans-selection')))fanyi = browser.find_element(By.ID, "trans-selection")fanyi_text = fanyi.textprint("翻译结果",fanyi_text)browser.close() # html = browser.page_source  # 获取完整 HTML 内容  return fanyi_textexcept Exception as e:print(f"发生错误: {e}")return {"error": "无法获取翻译结果"}#  2.爬取壁纸
@router.post("/iciba_fanyi")
def iciba_fanyi(params:BiziParams):sInit = seleniumInit()sInit.start_requests(params.keyboard)return "爬取完成"

总结下这个网站我是看csdn上有个大佬爬过,所以我也就试试用来测试技术,技术文章仅用于学习与研究目的,不得用于违法行为,如需要壁纸请购买,支持正版,而且正版的壁纸清晰度很高,这部分不能是爬取到的。

但是发现这个网站加了机器人 加了图片请求转换,等待,所以开发的思路就是不能用原生selenium,否则机器人检测我们过不去,等我们千辛万苦绕过机器人时,发现请求图片被后端进行转换了并不能给你图片信息,这个时候就需要用js来实现复制图片。

代码地址:

https://download.csdn.net/download/Lookontime/90097745

七.总结

Python 进阶中的selenium就介绍到这里,再次声明文章只是为了研究selenium技术。

创作整理不易,请大家多多关注 多多点赞,有写的不对的地方欢迎大家补充,我来整理,再次感谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/889207.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS常用的尺寸单位

像素px 以屏幕上的一个点为单位&#xff0c;比较稳定和精确用的最多 em 以字体大小为参考&#xff0c;&#xff08;是自身字体大小的倍数&#xff09;当自身的字体大小改变时&#xff0c;em也会随着改变em * font-size px rem 以根元素 < html > 作为参考&#xff…

容器部署Prometheus+Grafana

一、Grafana介绍 Zabbix 和 Grafana 是两种流行的监控工具,它们在功能和用途上有所不同: Zabbix: Zabbix 是一个开源的监控解决方案,主要用于监控网络服务和应用程序。它包括了自己的数据存储解决方案,可以直接从监控的设备收集数据。Zabbix 提供了广泛的监控功能,包括但…

qt之插件编译

QtXlsxWriter sudo apt install qtbase5-private-dev git clone https://github.com/dbzhang800/QtXlsxWriter.git cd QtXlsxWriter/ qmake make -j6 sudo make install #将生成的lib 及 include copy至项目路径的lib 及include里项目配置&#xff1a; QT xlsxbluetoo…

Linux —— vim 编辑器

一、什么是vim vim是一个功能强大、高度可定制的文本编辑器。以下是对vim编辑器的具体介绍&#xff1a; 历史背景&#xff1a;vim最初由Bram Moolenaar在1991年开发&#xff0c;作为vi编辑器的增强版&#xff0c;增加了许多新的特性和改进。它继承了vi的基本编辑功能和键盘快捷…

高效率同步降压转换器 - YB2416D: 实现快速充电和高效能供电的利器

概述: YB2416是一款输入耐压超过40V&#xff0c;在4.5V~30V输入电压条件下正常工作&#xff0c;并且能够实现精确恒压以及恒流的同步降压型DC-DC转换器。 内部集成80m2的上管和40m2的下管&#xff0c;无需外部肖特基二极管&#xff0c;可连续输出3A电流。输出3A电流时系统转换…

Repo管理

文章目录 前言Repo介绍清单仓库清单仓库的组成 初始化Repo同步远程仓库Repo实际应用 前言 我们知道&#xff0c;Git是用来管理某一个仓库&#xff0c;那当一个项目用到了多个仓库时&#xff0c;怎么来同步管理这些仓库呢&#xff1f;这个时候就可以引入Repo管理。 Repo介绍 …

神经网络的起源与工作原理

神经网络起源&#xff1a;一个生物神经网络是由一组化学上相连或功能上相关的神经元组成。一个神经元可能与许多其他神经元相连&#xff0c;网络中的神经元和连接的总数可能很广泛。连接&#xff0c;称为突触&#xff0c;通常是从轴突到树突形成的&#xff0c;尽管树突和其他连…

Qwen2.5-7B-Instruct vLLM 部署调用

Qwen2.5-7B-Instruct vLLM 部署调用 vLLM 简介 vLLM 框架是一个高效的大语言模型推理和部署服务系统&#xff0c;具备以下特性&#xff1a; 高效的内存管理&#xff1a;通过 PagedAttention 算法&#xff0c;vLLM 实现了对 KV 缓存的高效管理&#xff0c;减少了内存浪费&…

解决 Mac(M1/M2)芯片,使用node 14版本

前言 nvm 在安装 Node.js v14.21.3 时&#xff0c;报错&#xff1a; nvm install 14 Downloading and installing node v14.21.3... Downloading https://nodejs.org/dist/v14.21.3/node-v14.21.3-darwin-arm64.tar.xz... curl: (56) The requested URL returned error: 404Bin…

TesseractOCR-GUI:基于WPF/C#构建TesseractOCR简单易用的用户界面

前言 前篇文章使用Tesseract进行图片文字识别介绍了如何安装TesseractOCR与TesseractOCR的命令行使用。但在日常使用过程中&#xff0c;命令行使用还是不太方便的&#xff0c;因此今天介绍一下如何使用WPF/C#构建TesseractOCR简单易用的用户界面。 普通用户使用 参照上一篇教…

车载ADB:让汽车更智能的桥梁

随着科技的不断进步&#xff0c;汽车行业也在迅速迈向智能化。车载Android系统&#xff08;通常称为Android Auto&#xff09;正在变得越来越流行&#xff0c;而Android Debug Bridge (ADB) 作为连接和调试这些系统的桥梁&#xff0c;也变得尤为重要。在本文中&#xff0c;我们…

【ETCD】【源码阅读】configurePeerListeners() 函数解析

configurePeerListeners 是 ETCD 的一个核心函数&#xff0c;用于为集群中节点之间的通信配置监听器&#xff08;Peer Listener&#xff09;。这些监听器主要负责 Raft 协议的消息传递、日志复制等功能。函数返回一个包含所有监听器的列表。 函数签名 func configurePeerList…

uniapp改成用vue起项目

目的&#xff1a;让项目按照vue的打包流程跑流水线 1.按照uniapp官网教程执行 2.执行第二条命令时报错 ERROR Failed to get response from true/vue-cli-version-marker 3.解决方式 报错可能跟yarn有关&#xff0c;然后切换成npm 找到自己本地电脑的这个文件 按照截图修…

装饰器模式(Decorator Pattern)

装饰器模式&#xff08;Decorator Pattern&#xff09; 定义 装饰器模式是一种结构性设计模式&#xff0c;通过 动态组合对象 的方式&#xff0c;为对象添加额外功能&#xff0c;而无需修改原有类。 装饰器模式的核心思想 对象增强&#xff1a;在现有类的基础上动态添加功能&…

【SH】微信小程序调用EasyDL零门槛AI开发平台的图像分类研发笔记

文章目录 微信小程序字符串字符串模板字符串拼接 上传图片编写JS代码编写wxml代码编写wxss代码 GET请求测试编写测试代码域名不合法问题 GET和POST请求测试编写JS代码编写wxml代码编写wxss代码 效果展示 微信小程序字符串 字符串模板 这是ES6引入的特性&#xff0c;允许你通过…

【C#】int? , C# 中的可空类型(Nullable Types)

在 C# 中&#xff0c;问号&#xff08;?&#xff09;用于表示可空类型&#xff08;nullable types&#xff09;。在你的代码中&#xff0c;int? 表示的是可空的整数类型&#xff0c;也就是可以存储 int 类型的值&#xff0c;也可以存储 null。具体来说&#xff1a; int? 详…

[小白系列]Ubuntu安装教程-安装prometheus和Grafana

Docker安装prometheus 拉取镜像 docker pull prom/prometheus 配置文件prometheus.yml 在/data/prometheus/建立prometheus.yml配置文件。&#xff08;/data/prometheus/可根据自己需要调整&#xff09; global:scrape_interval: 15s # By default, scrape targets ev…

在Spring Boot项目中整合Redis:高效数据存储与缓存的最佳实践

目录 1. 引入依赖 2. 创建序列化配置类 2.1 序列化的选择 3. 配置YAML文件 3.1 连接池的配置 4. 使用Redis 4.1 复杂数据类型的存储 4.2 列表、集合和哈希的使用 4.2.1 列表示例 4.2.2 集合示例 4.2.3 哈希示例 5. 处理事务和管道 5.1 事务示例 5.2 管道示例 6…

嵌入式硬件设计 — 智能设备背后的隐形架构大师

目录 引言 一、嵌入式硬件设计概述 &#xff08;一&#xff09;需求分析 &#xff08;二&#xff09;硬件选型 &#xff08;三&#xff09;电路设计 &#xff08;四&#xff09;PCB 制作与焊接 &#xff08;五&#xff09;硬件调试与测试 &#xff08;六&#xff09;软…

调度系统:使用 Airflow 对 Couchbase 执行 SQL 调度时的潜在问题

使用 Airflow 对 Couchbase 执行 SQL 调度时&#xff0c;通常情况下不会直接遇到与 Couchbase 分布式特性相关的异常&#xff0c;但在某些特定情境下&#xff0c;可能会出现一些与分布式环境、调度和数据一致性相关的潜在问题。以下是一些可能会遇到的问题和建议的解决方案&…