自动网页浏览助手:基于 Selenium + GLM-4V 的百度自动搜索与内容提取系统
智能网页浏览助手:基于 Selenium + GLM-4V 的百度自动搜索与内容提取系统
项目目标:构建一个能自主完成“打开百度 → 随机搜索 → 点击结果 → 提取内容”全流程的 AI 系统,全程无需硬编码元素定位器,完全依赖 GLM-4V 多模态理解能力。
1. 项目文件结构
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)
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)
import os
from dotenv import load_dotenvload_dotenv()class Settings:# GLM API 配置ZHIPU_API_KEY = os.getenv("ZHIPU_API_KEY")GLM_MODEL = "glm-4v"# 浏览器配置HEADLESS = False # 调试时设为 FalseWINDOW_WIDTH = 1920WINDOW_HEIGHT = 1080# 搜索关键词池KEYWORDS = ["人工智能最新进展", "Python自动化教程", "大模型应用案例","气候变化解决方案", "量子计算突破", "新能源汽车技术"]# 输出路径OUTPUT_DIR = "outputs"CONTENT_DIR = os.path.join(OUTPUT_DIR, "page_contents")# 超时设置PAGE_LOAD_TIMEOUT = 10GLM_TIMEOUT = 30settings = Settings()
3.2 浏览器控制模块(core/browser.py)
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 loggerclass 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 Imageimport ioimg = Image.open(io.BytesIO(screenshot))scale_x = img.width / total_widthscale_y = img.height / total_heightreturn img, scale_x, scale_ydef 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").textdef quit(self):self.driver.quit()
3.3 视觉理解模块(core/vision.py)
import base64
import io
import requests
import json
import re
from config.settings import settings
from utils.logger import loggerclass 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分析图像"""# 转换为base64buffered = 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)}")raisedef 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 Nonedef 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:breakreturn coords[:3]
3.4 内容提取模块(core/content_extractor.py)
import os
import re
from config.settings import settings
from utils.logger import loggerclass 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)
from PIL import Image
import iodef resize_image_for_glm(image, max_width=768):"""调整图片尺寸以优化GLM调用成本"""if image.width > max_width:ratio = max_width / image.widthnew_height = int(image.height * ratio)return image.resize((max_width, new_height), Image.LANCZOS)return image
3.6 日志工具(utils/logger.py)
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)
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 loggerdef 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_urlpage_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)}")raisefinally: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 版本匹配)
安装步骤
# 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或项目根目录
运行项目
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 自动化 的前沿技术组合,为构建更复杂的智能代理系统打下坚实基础!