如果访问网页的时候或者说使用click点击按钮以后因为网速等各种原因，新的页面可能无法立即出现。可能需要等待一两秒但是程序的执行是很快的它不会去等待这1秒2秒那么如果新页面没有加载完成，又执行了find_element程序就会报错。提示找不到元素通常我们就需要使用一些办法，让程序延迟执行find_element指令time导入time模块import time在需要延迟的地方加上time.sleep(1)这表示暂停（延迟）程序执行1秒钟但是这会有一个问题，到底暂停多少秒合适呢？有可能网页2秒 5秒才加载完毕呢隐式等待（全局等待）隐式等待（Implicit Waits）是一种全局等待机制，在使用Selenium时可以设置一个固定的等待时间，让WebDriver在查找元素时等待一段时间，如果在指定时间内找到了元素，则立即执行下一步操作；如果超过了指定时间仍未找到元素，则抛出异常。使用隐式等待可以为整个WebDriver的生命周期设置一个统一的等待时间，这样在查找元素时就不需要显式地每次都设置等待时间。导入from selenium import webdriver可以在代码的最前面设置等待时间，这表示最长等待10秒，如果超出10秒还没找到这个元素就抛出异常# 设置隐式等待时间为10秒 driver.implicitly_wait(10)其他代码就不需要额外修改。需要注意的是，隐式等待是全局设置，适用于整个WebDriver的生命周期，所以一旦设置了隐式等待时间，后续的所有查找元素操作都会遵循这个等待时间。但是在实际使用中，我发现会出现一些问题，目前尚不清楚原因。所以不太推荐这种方法显式等待使用显式等待可以等待指定条件成立后再继续执行后续操作，它会在一直不断尝试判断条件是否满足，如果条件满足，则立即执行后续操作；在使用 wait.until() 方法时，它会持续等待，直到传入的条件返回 True 或达到了超时时间。等待的时间取决于页面的加载速度和条件的满足情况。如果条件在等待时间内满足，那么它会立即返回找到的元素。如果超过等待时间，而条件仍未满足，那么将抛出 TimeoutException 异常。导入from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC设置显式等待时间10秒wait = WebDriverWait(wd, 10) 显式等待-选择查找单个元素element = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'input_text')))显式等待-选择查找多个元素elements = wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'input_text')))
Python × Selenium 获取元素属性 & 定位指定标签名称的元素 & 获取整个元素的HTML
获取文本例如我想获取本博客的这段文字首先第一步，还是定位这个元素注意之前提到的 空格用.来代替element = wd.find_element(By.CLASS_NAME,'m-n.font-thin.text-black.l-h')使用element.text就可以获取到了这里print一下from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By wd = webdriver.Chrome(service = Service('chromedriver.exe')) wd.get('https://www.yuofyou.cn') element = wd.find_element(By.CLASS_NAME,'m-n.font-thin.text-black.l-h') print(element.text) input()成功获取到获取元素属性值如果我们想获取到第一个文章的链接观察第一个文章对应的代码链接出现在了一个class名为m-t-none text-ellipsis index-post-title text-title里面的a标签的href属性首先我们还是定位这个最外层的元素（注意这里因为我们想获取的是第一个文章 所以就直接使用element即可，无需使用elements）element = wd.find_element(By.CLASS_NAME,'m-t-none.text-ellipsis.index-post-title.text-title')如果直接获取href属性是获取不到的。因为这个class本身是没有href属性的。我们需要再定位到它下层的a标签这里使用By里面的TAG_NAME方法，在 Selenium 中，通过 By.TAG_NAME 可以定位具有指定标签名称的元素。element = element.find_element(By.TAG_NAME, 'a')然后使用获取元素属性的get_attributehref = element.get_attribute('href')完整代码from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By wd = webdriver.Chrome(service = Service('chromedriver.exe')) wd.get('https://www.yuofyou.cn') element = wd.find_element(By.CLASS_NAME,'m-t-none.text-ellipsis.index-post-title.text-title') element = element.find_element(By.TAG_NAME, 'a') href = element.get_attribute('href') print(href) input()获取整个元素的HTML在程序编写的时候有些时候需要debug。可以获取一下整个页面的HTML 或者某个元素的HTML以此来查错要获取整个元素对应的HTML文本内容，可以使用 element.get_attribute('outerHTML')如果只是想获取某个元素 内部 的HTML文本内容，可以使用 element.get_attribute('innerHTML')
有些时候网页中有些元素它们的名字是一样的，以至于使用前面提到的方法我们实现我们想要的效果这个时候我们需要使用wd.find_elements() 来获取网页上的多个元素以本博客为例假设我们想点击第三个文章的图片通过开发者工具找到图片对应的代码我们发现了class属性，如果用之前wd.find_element(By.CLASS_NAME,'')是**不能获取**到第三个选择定位到第三个图片的。因为item-thumb-small lazy在文章中有多处出现，使用find_element只能选择第一个item-thumb-small lazy使用wd.find_elements()elements = wd.find_elements(By.CLASS_NAME,'item-thumb-small lazy')如果你这样写，会报错错误的原因在于，虽然它CLASS的值是item-thumb-small lazy 但是在写代码的时候这个空格要给他换成.正确写法应该是：elements = wd.find_elements(By.CLASS_NAME,'item-thumb-small.lazy')它会返回一个数组 此时elements是一个数组由于页面上有五个文章图片item-thumb-small lazy 所以这个elements就分别代表这五个也就是说elements[0]代表了页面上第一个图片我们要点击的是第三个图片 所以就是elements[2]完整代码from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By wd = webdriver.Chrome(service = Service('chromedriver.exe')) wd.get('https://www.yuofyou.cn') elements = wd.find_elements(By.CLASS_NAME,'item-thumb-small.lazy') elements[2].click() input()
在使用Selenium做自动化时，首先需要选择页面上的元素，然后才可以做点击、输入之类的操作要告诉浏览器，要操作哪个元素我们需要找到这个元素的特征 以百度为例我们可以右键需要找的元素点击检查就会弹出 开发者工具，并且自动定位到我们需要找的这个元素另外，我们也可以在打开网页后按下F12 打开开发者工具，按下这个图标然后鼠标在去页面上点击相应的元素，也可以自动定位根据id属性 选择元素根据上文中我们定位的百度搜索框的代码 百度搜索框的属性id是kw所以如果我们要选择百度输入框，我们可以通过定位这个id属性kw但是请注意：这个名字叫kw的id属性必须在这个页面是唯一的，才可以准确定位。如果有多个属性ID名字相同的元素，它将只返回第一个匹配的元素导入By模块在定位之前，我们需要用到Selenium 中的 By 模块，用于定位元素时指定定位策略。from selenium.webdriver.common.by import Byfind_element()选择元素根据id属性来选择元素我们使用find_elementelement = wd.find_element(By.ID, 'kw')send_keys()发送文本element.send_keys() 是 Selenium 中的一个方法，用于向输入框或可编辑元素发送文本或按键事件。上一步，我们选择了ID名为kw的元素（也就是百度搜索框），现在我们向这个输入框输入yuofyouelement.send_keys("yuofyou")完整代码from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By wd = webdriver.Chrome(service = Service('chromedriver.exe')) wd.get('https://www.baidu.com') element = wd.find_element(By.ID, 'kw') element.send_keys("yuofyou") input()此时我们发现yuofyou 被输入上去了我们如果需要搜索 有两种方法一种是 回车另外一种是 点击百度一下 这个按钮回车的方法我们只需要在发送文本的时候加上一个换行符\n：element.send_keys("yuofyou\n")清除输入框如果我们想清除输入框中现在已有是字符串使用elemet.clear()click按钮点击无论是点击按钮，还是输入内容。首先第一步选择元素通过开发者工具 可以看到百度一下的按钮id是su使用上文提供的方法选择这个按钮element = wd.find_element(By.ID,'su')点击按钮element.click()完整代码from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By wd = webdriver.Chrome(service = Service('chromedriver.exe')) wd.get('https://www.baidu.com') element = wd.find_element(By.ID, 'kw') element.send_keys("yuofyou") element = wd.find_element(By.ID,'su') element.click() input()根据class属性 选择元素在实际应用中我们发现有些元素无法通过ID去定位选择，只能通过class属性例如我想点击这个相机图标定位代码发现只有class属性我们使用By模块里的CLASS_NAME进行定位 并点击element = wd.find_element(By.CLASS_NAME,'soutu-btn') element.click()完整代码：from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By wd = webdriver.Chrome(service = Service('chromedriver.exe')) wd.get('https://www.baidu.com') element = wd.find_element(By.ID, 'kw') element.send_keys("yuofyou") element = wd.find_element(By.ID,'su') element.click() element = wd.find_element(By.CLASS_NAME,'soutu-btn') element.click() input()但是！！！注意：在这种跳转了其他页面的情况，有一定概率你会触发一个报错大致就是因为程序运行实在太快了，执行click以后因为网速的原因还没能跳转到第二个页面，程序就开始查找元素，就会报错找不到这个元素这个时候我们可以在click以后添加一个延迟导入time模块import time在需要延迟的地方加上一句这个time.sleep(1)完整代码：import time from selenium import webdriver from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By wd = webdriver.Chrome(service = Service('chromedriver.exe')) wd.get('https://www.baidu.com') element = wd.find_element(By.ID, 'kw') element.send_keys("yuofyou") element = wd.find_element(By.ID,'su') element.click() time.sleep(1) element = wd.find_element(By.CLASS_NAME,'soutu-btn') element.click() input()
Selenium官方中文文档：https://www.selenium.dev/zh-cn/documentation/本文是基于Python下的Selenium操作导入模块from selenium import webdriver from selenium.webdriver.chrome.service import Servicewebdriver 是 Selenium 提供的一个模块，用于创建浏览器实例和执行与浏览器交互的操作。webdriver.chrome.service 则是该模块中的一个子模块，用于配置和管理 Chrome 浏览器的服务。这段代码使用了 Selenium 的 WebDriver 模块，并且使用 ChromeDriver 作为 Chrome 浏览器的服务来进行自动化测试。创建对象我们需要将 浏览器驱动chromedriver.exe 放到程序运行目录wd = webdriver.Chrome(service = Service(r'chromedriver.exe'))创建Webdriver对象，指定chrome浏览器驱动路径当这句代码执行以后，chrome浏览器就会运行打开网址使用WebDriver的get方法打开本博客wd.get('https://www.yuofyou.cn')
Selenium是一个用于web的自动化工具它通过调用浏览器，模拟用户在浏览器中操作。比如点击、输入等等也可以在网页中获取需要的信息Selenium的工作流程是：通过我们编写的自动化程序，调用浏览器驱动，浏览器驱动调用浏览器进行操作Selenium 安装在命令行程序中，执行pip install selenium安装浏览器和浏览器驱动推荐Chrome浏览器，确保Chrome浏览器安装完成以后，需要下载对应浏览器版本的浏览器驱动Chrome浏览器驱动：https://chromedriver.storage.googleapis.com/index.htmlEdge浏览器驱动：https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/以Chrome浏览器为例，你可以在关于Chrome中看到浏览器版本例如我的是114.0.5735.199!](https://www.yuofyou.cn/usr/uploads/2023/07/3406968576.png)可以在浏览器驱动网页找到对应的版本根据系统选择对应浏览器驱动
Python爬虫 - UA(User-Agent) 请求载体的身份标识 UA伪装
UAUser-Agent（请求载体的身份标识）UA检测网站的服务器会检测对应请求的载体身份标识，如果检测请求的载体身份标识为某一款浏览器说明是一个正常的请求。但是如果检测到的载体身份标识不是某一款浏览器则标识该请求不正常，则可能会被拒绝该次请求UA伪装让爬虫对应的请求载体身份标识伪装成某一款浏览器伪装方法构造一个User-Agentheaders = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' }发起get请求的第三个参数使用刚刚构造的User-Agentresponse = requests.get(url=url, params=param, headers=headers)以naver为例import requests # UA：User-Agent（请求载体的身份标识） # UA检测: 网站的服务器会检测对应请求的载体身份标识，如果检测请求的载体身份标识为某一款浏览器说明是一个正常的请求。 # 但是如果检测到的载体身份标识不是某一款浏览器则标识该请求不正常 # UA伪造 if __name__ == '__main__': # UA伪装：将对应的User-Agent封装到一个字典中 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36' } url = 'https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&' # 处理url携带的参数：封装到字典中 kw = input('enter a word:') param = { 'query':kw } # 对指定的url发起的请求对应的url是携带参数的，并且请求过程中处理了参数 response = requests.get(url=url, params=param, headers=headers) response.encoding='utf-8' # 先转换为utf-8格式编码 避免乱码 # 获取响应数据 page_text = response.text fileName = kw+'.html' with open (fileName,'w',encoding='utf-8') as fp: fp.write(page_text) print(fileName,'保存成功！')
是什么requests模块：python中原生的一款基于网络请求的模块，功能非常强大，简单便携，效率极高。作用：模拟浏览器发请求如何使用（编码流程）指定url发起请求获取响应数据持久化存储环境安装pip install requests实战编码需求：爬取百度首页的页面数据导入模块import requests指定url# step 1: 指定url url = 'https://www.baidu.com'发起请求# step 2: 发起请求 # get方法会返回一个响应对象 response = requests.get(url=url)获取响应数据# step 3: 获取响应数据 text返回的是字符串形式的响应数据 response.encoding='utf-8' # 先转换为utf-8格式编码 避免乱码 page_text = response.text print(page_text)持久化存储# step 4: 持久化存储 with open('./baidu.html','w',encoding='utf-8') as fp: fp.write(page_text)
Python爬虫 - 概念: 协议 请求头 响应头 加密方式
协议http协议服务器和客户端进行数据交互的一种形式https协议安全的超文本传输协议常用请求头信息User-Agent请求载体的身份标识Connection请求完毕后，是断开连接还是保持连接常用响应头信息Content-Type服务器响应回客户端的数据类型加密方式对称密钥加密非对称密钥加密证书密钥加密https