Mac如何通过 Selenium 爬取网页并处理懒加载的图片
本文将演示如何使用 Selenium 和 BeautifulSoup 来抓取网页上的图片,包括如何处理懒加载的图片。懒加载是一种常见的网页优化技术,只有当图片即将出现在用户视口时,图片才会被加载。
我们将通过模拟浏览器滚动页面,触发懒加载,直到页面所有的图片都加载完毕。
1. 准备工作
确保你已经安装了以下依赖库:
-
Selenium:用于自动化操作浏览器。
-
BeautifulSoup:用于解析 HTML 内容。
-
requests:用于下载图片并计算其大小。
pip3 install selenium beautifulsoup4 requests
2. 使用 Chrome 浏览器和 Selenium
设置 ChromeDriver 路径
由于每个人的操作系统和文件路径不同,需要确保正确指定 chromedriver
的路径。
- 我们使用
os.path.expanduser()
来扩展用户目录~
,以确保代码能正确找到 ChromeDriver。
ini
import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
# 设置 chromedriver 路径
chromedriver_path = os.path.expanduser("~/Desktop/chromedriver-mac-x64/chromedriver")
service = Service(chromedriver_path)
driver = webdriver.Chrome(service=service)
# 访问网页
driver.get("需要抓取的网址")
3. 访问网页并处理页面懒加载
模拟页面滚动
懒加载技术通常通过监听滚动事件来加载图片。我们需要模拟用户滚动页面的行为,直到页面加载完所有图片。以下代码模拟了滚动页面并等待图片加载的过程。
ini
import time
# 设置滚动的暂停时间
scroll_pause_time = 4 # 每次滚动等待4秒
scroll_height = driver.execute_script("return document.body.scrollHeight")
while True:
# 向下滚动页面
driver.execute_script("window.scrollTo(0, window.innerHeight + window.scrollY);")
# 等待页面加载完毕
time.sleep(scroll_pause_time)
# 获取新的滚动高度并判断是否滚动到页面底部
new_scroll_height = driver.execute_script("return window.scrollY + window.innerHeight")
if new_scroll_height >= scroll_height:
scroll_height = new_scroll_height
break # 如果没有新内容加载,则停止滚动
解释:
driver.execute_script("window.scrollTo(0, window.innerHeight + window.scrollY);")
:模拟浏览器滚动,滚动到当前窗口的底部。time.sleep(scroll_pause_time)
:等待一段时间,让页面加载新内容。new_scroll_height >= scroll_height
:检查是否已滚动到底部,如果没有新内容加载,则退出循环。
4. 解析 HTML 获取图片链接
我们通过 driver.page_source
获取页面的完整 HTML 内容,传递给 BeautifulSoup
进行解析。
ini
from bs4 import BeautifulSoup
import requests
# 获取页面的 HTML 内容
html = driver.page_source
# 使用 BeautifulSoup 解析 HTML
soup = BeautifulSoup(html, 'html.parser')
# 获取所有的 img 标签
img_tag = soup.find_all('img')
# 设置图片 URL 中需要包含的关键字
target_value = "image.yfswebstatic.com" # 根据需要修改
# 循环图片标签,获取图片 URL 和大小
for item in img_tag:
img_url = item.get('src')
if img_url:
if target_value in img_url:
# 请求图片并获取大小
img_response = requests.get(img_url, stream=True)
size_kb = len(img_response.content) / 1024 # KB
print(f"图片 URL: {img_url},大小: {size_kb:.2f} KB")
5. 关闭浏览器
bash
# 关闭浏览器
driver.quit()
6. 总结
在此代码中,我们模拟了用户滚动页面来加载懒加载的图片。我们通过 Selenium
控制浏览器不断向下滚动页面,并在每次滚动后等待页面加载新的内容。在页面加载完成后,我们提取页面的 HTML,并使用 BeautifulSoup
获取所有图片标签。
常见问题
- 图片没有加载完 :懒加载的图片需要通过滚动页面触发加载,如果图片较多,可能需要增加滚动的时间(
scroll_pause_time
)。 - 无法获取图片 URL:确保页面已经完全加载,尤其是动态生成的内容。通过增加等待时间,确保图片都加载完毕。
懒加载 vs 非懒加载网页
懒加载网页:
- 图片通过延迟加载的方式进行加载,通常只有当用户滚动到页面底部时,图片才会被加载到浏览器中。
- 需要模拟滚动和等待页面加载,确保图片能被抓取。
非懒加载网页:
- 图片会随着页面的加载而立即显示,不需要等待滚动。
- 一旦页面加载完成,所有的图片都会出现在 HTML 内容中。
关于懒加载网页的抓取要点:
- 滚动加载:需要模拟用户滚动页面,触发图片的加载。可以通过不断向下滚动页面并等待每次滚动后的内容加载完成来实现。
- 适应性:懒加载页面的实现方式各不相同,因此需要针对具体页面进行调整。如果有"加载更多"按钮或其他触发懒加载的机制,可能需要使用 Selenium 来点击这些按钮。
- 等待加载完成:对于懒加载的图片,确保在获取 HTML 内容前页面已完全加载,可以通过增加滚动间隔时间、检测加载状态等方式保证抓取到所有的图片。
通过这种方式,你可以抓取页面中懒加载的图片,获取它们的 URL 和大小。
7. 完整代码
ini
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from bs4 import BeautifulSoup
import requests
import time
# os: chromedriver 路径 "~/Desktop/chromedriver-mac-x64/chromedriver" 可能存在问题,因为 ~ (Home 目录) 在 Python 中不会自动展开
# 修正方法
# 🔹 使用绝对路径
import os
# 设置 chromedriver 路径
chromedriver_path = os.path.expanduser("~/Desktop/chromedriver-mac-x64/chromedriver")
service = Service(chromedriver_path)
driver = webdriver.Chrome(service=service)
# 访问网页
driver.get("需要抓取的网址")
scroll_pause_time = 4 # 每次滚动等待4秒
scroll_height = driver.execute_script("return document.body.scrollHeight")
while True:
# 向下滚动页面
driver.execute_script("window.scrollTo(0, window.innerHeight + window.scrollY);")
# 等待页面加载完毕
time.sleep(scroll_pause_time)
# 获取新的滚动高度并判断是否滚动到页面底部
new_scroll_height = driver.execute_script("return window.scrollY + window.innerHeight")
print('页面高度: ', scroll_height)
print('执行滚动: ', new_scroll_height)
if new_scroll_height >= scroll_height:
scroll_height = new_scroll_height
break # 如果没有新内容加载,则停止滚动
# driver.page_source 获取网页 HTML 内容,再传递给 BeautifulSoup 解析
html = driver.page_source
# 解析 HTML
soup = BeautifulSoup(html, 'html.parser')
# 获取图片标签
img_tag = soup.find_all('img')
# 设置图片关键字
target_value = "image.yfswebstatic.com"
# print('图片标签:', img_tag)
# 循环图片
for item in img_tag:
img_url = item.get('src')
if img_url:
if target_value in img_url:
# 获取图片大小
img_response = requests.get(img_url, stream=True)
size_kb = len(img_response.content) / 1024 # KB
# 打印
print(f"图片 URL: {img_url},大小: {size_kb:.2f} KB")
# 关闭浏览器
driver.quit()