智能网页浏览助手:基于 Selenium + GLM-4V 的百度自动搜索与内容提取系统
项目目标:构建一个能自主完成"打开百度 → 随机搜索 → 点击结果 → 提取内容"全流程的 AI 系统,全程无需硬编码元素定位器,完全依赖 GLM-4V 多模态理解能力。

1. 项目文件结构
bash
baidu-ai-browser/
├── config/
│ └── settings.py # 配置文件
├── core/
│ ├── browser.py # Selenium 浏览器控制
│ ├── vision.py # GLM-4V 视觉理解
│ └── content_extractor.py # 内容提取逻辑
├── utils/
│ ├── image_utils.py # 图像处理工具
│ └── logger.py # 日志记录
├── outputs/ # 输出目录(自动生成)
│ ├── search_results.txt # 搜索结果摘要
│ └── page_contents/ # 各网页内容
├── main.py # 主程序入口
├── requirements.txt # 依赖列表
└── README.md # 部署说明
2. 依赖安装(requirements.txt)
txt
selenium==4.18.1
opencv-python==4.8.1.78
Pillow==10.2.0
requests==2.31.0
python-dotenv==1.0.1
3. 核心代码实现
3.1 配置文件(config/settings.py)
python
import os
from dotenv import load_dotenv
load_dotenv()
class Settings:
# GLM API 配置
ZHIPU_API_KEY = os.getenv("ZHIPU_API_KEY")
GLM_MODEL = "glm-4v"
# 浏览器配置
HEADLESS = False # 调试时设为 False
WINDOW_WIDTH = 1920
WINDOW_HEIGHT = 1080
# 搜索关键词池
KEYWORDS = [
"人工智能最新进展", "Python自动化教程", "大模型应用案例",
"气候变化解决方案", "量子计算突破", "新能源汽车技术"
]
# 输出路径
OUTPUT_DIR = "outputs"
CONTENT_DIR = os.path.join(OUTPUT_DIR, "page_contents")
# 超时设置
PAGE_LOAD_TIMEOUT = 10
GLM_TIMEOUT = 30
settings = Settings()
3.2 浏览器控制模块(core/browser.py)
python
import time
import os
from selenium import webdriver
from selenium.webdriver.chrome.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 EC
from config.settings import settings
from utils.logger import logger
class SmartBrowser:
def __init__(self):
self.driver = self._init_driver()
self.wait = WebDriverWait(self.driver, settings.PAGE_LOAD_TIMEOUT)
def _init_driver(self):
options = Options()
if settings.HEADLESS:
options.add_argument("--headless")
options.add_argument(f"--window-size={settings.WINDOW_WIDTH},{settings.WINDOW_HEIGHT}")
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
return webdriver.Chrome(options=options)
def capture_fullpage_screenshot(self):
"""捕获完整页面截图并返回缩放比例"""
# 获取实际页面尺寸
total_width = self.driver.execute_script("return Math.max(document.body.scrollWidth, document.documentElement.scrollWidth);")
total_height = self.driver.execute_script("return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);")
# 设置窗口大小
self.driver.set_window_size(total_width, total_height)
screenshot = self.driver.get_screenshot_as_png()
# 计算缩放比例
from PIL import Image
import io
img = Image.open(io.BytesIO(screenshot))
scale_x = img.width / total_width
scale_y = img.height / total_height
return img, scale_x, scale_y
def smart_click(self, x: int, y: int, scale_x: float, scale_y: float):
"""根据图片坐标执行点击"""
web_x = int(x / scale_x)
web_y = int(y / scale_y)
self.driver.execute_script(f"document.elementFromPoint({web_x}, {web_y}).click();")
time.sleep(2) # 等待页面响应
def get_page_text(self):
"""获取当前页面纯文本内容"""
return self.driver.find_element(By.TAG_NAME, "body").text
def quit(self):
self.driver.quit()
3.3 视觉理解模块(core/vision.py)
python
import base64
import io
import requests
import json
import re
from config.settings import settings
from utils.logger import logger
class GLMVision:
def __init__(self):
self.api_url = "https://open.bigmodel.cn/api/paas/v4/chat/completions"
self.headers = {
"Authorization": f"Bearer {settings.ZHIPU_API_KEY}",
"Content-Type": "application/json"
}
def analyze_image(self, image, prompt: str) -> str:
"""调用GLM-4V分析图像"""
# 转换为base64
buffered = io.BytesIO()
image.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue()).decode()
payload = {
"model": settings.GLM_MODEL,
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img_str}"}}
]
}
],
"temperature": 0.1 # 降低随机性
}
try:
response = requests.post(
self.api_url,
headers=self.headers,
json=payload,
timeout=settings.GLM_TIMEOUT
)
response.raise_for_status()
result = response.json()
return result["choices"][0]["message"]["content"]
except Exception as e:
logger.error(f"GLM API 调用失败: {str(e)}")
raise
def extract_coordinates(self, response: str):
"""从响应中提取坐标"""
# 匹配多种坐标格式
patterns = [
r'\(?(\d+)[,\s]+(\d+)\)?',
r'x[=:\s]*(\d+).*?y[=:\s]*(\d+)',
r'坐标.*?(\d+).*?(\d+)'
]
for pattern in patterns:
match = re.search(pattern, response, re.IGNORECASE)
if match:
return int(match.group(1)), int(match.group(2))
return None
def find_search_box(self, image):
"""定位百度搜索框"""
prompt = """
你是一个网页自动化专家,请精确识别百度首页搜索框的中心坐标。
要求:
1. 忽略广告和无关元素
2. 返回整数坐标(x, y)
3. 坐标基于图片左上角(0,0)
4. 只返回坐标,不要其他文字
"""
response = self.analyze_image(image, prompt)
return self.extract_coordinates(response)
def find_search_button(self, image):
"""定位百度搜索按钮"""
prompt = """
请找出百度搜索按钮(通常标有"百度一下")的中心坐标。
返回格式:(x, y)
"""
response = self.analyze_image(image, prompt)
return self.extract_coordinates(response)
def find_search_results(self, image):
"""识别前3个搜索结果的坐标"""
prompt = """
请识别搜索结果页面中前3个自然搜索结果(非广告)的标题区域中心坐标。
按顺序返回3组坐标,格式:
1. (x1, y1)
2. (x2, y2)
3. (x3, y3)
"""
response = self.analyze_image(image, prompt)
coords = []
for line in response.split('\n'):
coord = self.extract_coordinates(line)
if coord:
coords.append(coord)
if len(coords) == 3:
break
return coords[:3]
3.4 内容提取模块(core/content_extractor.py)
python
import os
import re
from config.settings import settings
from utils.logger import logger
class ContentExtractor:
def __init__(self):
os.makedirs(settings.CONTENT_DIR, exist_ok=True)
def extract_valuable_content(self, text: str, url: str) -> str:
"""提取有价值的内容(简化版)"""
# 移除无用内容
cleaned = re.sub(r'\s+', ' ', text) # 合并空白字符
cleaned = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9.,!?;:()\[\]{}\-_]', ' ', cleaned)
# 保留有意义的段落(长度>50字符)
sentences = [s.strip() for s in cleaned.split('。') if len(s.strip()) > 50]
# 取前10句作为摘要
summary = '。'.join(sentences[:10]) + '。' if sentences else cleaned[:500]
return f"URL: {url}\n\n{summary}"
def save_content(self, content: str, filename: str):
"""保存内容到文件"""
filepath = os.path.join(settings.CONTENT_DIR, filename)
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
logger.info(f"内容已保存: {filepath}")
3.5 图像工具(utils/image_utils.py)
python
from PIL import Image
import io
def resize_image_for_glm(image, max_width=768):
"""调整图片尺寸以优化GLM调用成本"""
if image.width > max_width:
ratio = max_width / image.width
new_height = int(image.height * ratio)
return image.resize((max_width, new_height), Image.LANCZOS)
return image
3.6 日志工具(utils/logger.py)
python
import logging
import os
# 创建日志目录
os.makedirs('logs', exist_ok=True)
logger = logging.getLogger('BaiduAIBrowser')
logger.setLevel(logging.INFO)
# 文件处理器
file_handler = logging.FileHandler('logs/app.log', encoding='utf-8')
file_handler.setLevel(logging.INFO)
# 控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 格式化器
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
3.7 主程序(main.py)
python
import random
import time
import os
from config.settings import settings
from core.browser import SmartBrowser
from core.vision import GLMVision
from core.content_extractor import ContentExtractor
from utils.image_utils import resize_image_for_glm
from utils.logger import logger
def main():
# 初始化组件
browser = SmartBrowser()
vision = GLMVision()
extractor = ContentExtractor()
try:
# 1. 打开百度
logger.info("正在打开百度...")
browser.driver.get("https://www.baidu.com")
time.sleep(2)
# 2. 随机选择关键词
keyword = random.choice(settings.KEYWORDS)
logger.info(f"随机选择关键词: {keyword}")
# 3. 定位搜索框并输入关键词
img, sx, sy = browser.capture_fullpage_screenshot()
img_resized = resize_image_for_glm(img)
search_box_coords = vision.find_search_box(img_resized)
if not search_box_coords:
raise Exception("未找到搜索框")
# 点击搜索框
browser.smart_click(search_box_coords[0], search_box_coords[1], sx, sy)
# 输入关键词
browser.driver.switch_to.active_element.send_keys(keyword)
time.sleep(1)
# 4. 点击搜索按钮
img2, sx2, sy2 = browser.capture_fullpage_screenshot()
img2_resized = resize_image_for_glm(img2)
search_btn_coords = vision.find_search_button(img2_resized)
if not search_btn_coords:
raise Exception("未找到搜索按钮")
browser.smart_click(search_btn_coords[0], search_btn_coords[1], sx2, sy2)
logger.info("已执行搜索")
time.sleep(3)
# 5. 获取搜索结果坐标
img3, sx3, sy3 = browser.capture_fullpage_screenshot()
img3_resized = resize_image_for_glm(img3)
result_coords = vision.find_search_results(img3_resized)
if len(result_coords) < 3:
logger.warning(f"只找到 {len(result_coords)} 个结果,继续处理...")
# 6. 依次点击并保存内容
results_summary = f"搜索关键词: {keyword}\n\n"
for i, coords in enumerate(result_coords[:3], 1):
logger.info(f"正在处理第 {i} 个搜索结果...")
# 点击结果
browser.smart_click(coords[0], coords[1], sx3, sy3)
time.sleep(3)
# 获取页面内容
current_url = browser.driver.current_url
page_text = browser.get_page_text()
# 提取有价值内容
valuable_content = extractor.extract_valuable_content(page_text, current_url)
# 保存到文件
filename = f"result_{i}_{keyword.replace(' ', '_')}.txt"
extractor.save_content(valuable_content, filename)
# 添加到摘要
results_summary += f"结果 {i}: {current_url}\n"
results_summary += f"摘要: {valuable_content.split('URL:')[0][:200]}...\n\n"
# 返回搜索结果页
browser.driver.back()
time.sleep(2)
# 重新获取截图(页面可能变化)
img3, sx3, sy3 = browser.capture_fullpage_screenshot()
img3_resized = resize_image_for_glm(img3)
# 7. 保存搜索结果摘要
with open(os.path.join(settings.OUTPUT_DIR, "search_results.txt"), 'w', encoding='utf-8') as f:
f.write(results_summary)
logger.info("搜索结果摘要已保存")
except Exception as e:
logger.error(f"执行过程中出错: {str(e)}")
raise
finally:
browser.quit()
logger.info("浏览器已关闭")
if __name__ == "__main__":
# 创建输出目录
os.makedirs(settings.OUTPUT_DIR, exist_ok=True)
main()
4. 部署说明(README.md)
环境要求
- Python 3.8+
- Chrome 浏览器(版本 ≥ 115)
- ChromeDriver(与 Chrome 版本匹配)
安装步骤
bash
# 1. 克隆项目
git clone https://github.com/yourname/baidu-ai-browser.git
cd baidu-ai-browser
# 2. 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows
# 3. 安装依赖
pip install -r requirements.txt
# 4. 配置API密钥
echo "ZHIPU_API_KEY=your_zhipu_api_key_here" > .env
# 5. 下载ChromeDriver
# 访问 https://chromedriver.chromium.org/ 下载对应版本
# 将 chromedriver 放入系统PATH或项目根目录
运行项目
bash
python main.py
输出说明
outputs/search_results.txt
:搜索结果摘要outputs/page_contents/
:各网页详细内容logs/app.log
:执行日志
注意事项
- API 成本:每次运行约调用 5-6 次 GLM-4V(约 0.1-0.15 元)
- 网络要求:需能访问百度和智谱AI API
- 反爬策略:百度可能触发验证码,建议降低运行频率
- 调试模式 :将
config/settings.py
中的HEADLESS = False
可查看浏览器操作过程
5. 效果示例
search_results.txt 内容:
搜索关键词: 人工智能最新进展
结果 1: https://www.example-ai-news.com/latest-ai-breakthroughs
摘要: 2024年人工智能领域迎来重大突破,多模态大模型在医疗诊断准确率提升至95%...
结果 2: https://tech.sina.com.cn/ai/2024-06-15/doc-ai_news
摘要: 中国科学家发布新型AI芯片,能效比提升10倍,专为大模型推理优化...
结果 3: https://www.zhihu.com/question/ai-progress-2024
摘要: 人工智能最新进展包括:1. 开源模型质量接近闭源 2. Agent技术实用化...
6. 扩展建议
- 增加重试机制:对 GLM 识别失败的情况自动重试
- 内容质量评分:用 GLM 对提取内容进行相关性打分
- 多语言支持:自动检测页面语言并调整提示词
- 分布式执行:使用 Celery 实现多任务并行处理
项目地址 :github.com/wyg5208/baidu-ai-browser
免责声明:本项目仅用于技术学习,请遵守百度 robots.txt 及相关法律法规。
通过这个项目,你将掌握 多模态大模型 + Web 自动化 的前沿技术组合,为构建更复杂的智能代理系统打下坚实基础!