You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需API实现WhatsApp接收自拍、人脸比对及匹配图片回传

问题描述

我正在开发一个Python项目,需求如下:

  • 用户通过WhatsApp发送自拍
  • 将自拍与我的婚礼图片数据库中的人脸进行比对
  • 把包含该用户的所有图片回传给对方
  • 要求不使用官方API,采用免费方案

我已经完成了人脸比对的核心代码:

import face_recognition
import os
import time

def load_face_images(source_folder):
    known_encodings = []
    image_paths = []

    for filename in os.listdir(source_folder):
        image_path = os.path.join(source_folder, filename)
        image = face_recognition.load_image_file(image_path)
        face_locations = face_recognition.face_locations(image)

        # Process all detected faces in the image
        for face_location in face_locations:
            face_encoding = face_recognition.face_encodings(image, [face_location])[0]
            known_encodings.append(face_encoding)
            image_paths.append(image_path)

    return known_encodings, image_paths


def search_person_in_images(target_image, known_encodings, image_paths, tolerance=0.5):
    target_face_locations = face_recognition.face_locations(target_image)
    target_face_encodings = face_recognition.face_encodings(target_image, target_face_locations)

    matching_image_paths = {}

    for i, face_encoding in enumerate(target_face_encodings):
        matches = face_recognition.compare_faces(known_encodings, face_encoding, tolerance=tolerance)
        matching_image_paths[i] = [image_paths[j] for j, match in enumerate(matches) if match]

    return matching_image_paths

start_time = time.time()
source_folder = "faces"
known_encodings, image_paths = load_face_images(source_folder)

target_image_path = "image1.jpeg"
target_image = face_recognition.load_image_file(target_image_path)

matching_image_paths = search_person_in_images(target_image, known_encodings, image_paths)

num_matches = sum(len(paths) for paths in matching_image_paths.values())
print("Number of matching images:", num_matches)

end_time = time.time()
execution_time = end_time - start_time
print("Execution time:", execution_time, "seconds")

现需解决:如何实现自动接收WhatsApp用户发送的图片、完成人脸比对并回传匹配图片?要求用免费方案。


免费实现方案(基于WhatsApp Web自动化)

核心思路是通过Selenium操控WhatsApp Web实现收发图片,结合你已有的人脸比对逻辑完成全流程。

1. 依赖安装

执行以下命令安装所需库:

pip install selenium pillow face_recognition

同时下载与你的Chrome浏览器版本匹配的ChromeDriver,放在项目目录下。

2. 完整整合代码

import time
import os
import shutil
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import face_recognition

# 保留你已有的人脸比对函数
def load_face_images(source_folder):
    known_encodings = []
    image_paths = []

    for filename in os.listdir(source_folder):
        image_path = os.path.join(source_folder, filename)
        image = face_recognition.load_image_file(image_path)
        face_locations = face_recognition.face_locations(image)

        for face_location in face_locations:
            face_encoding = face_recognition.face_encodings(image, [face_location])[0]
            known_encodings.append(face_encoding)
            image_paths.append(image_path)

    return known_encodings, image_paths

def search_person_in_images(target_image, known_encodings, image_paths, tolerance=0.5):
    target_face_locations = face_recognition.face_locations(target_image)
    target_face_encodings = face_recognition.face_encodings(target_image, target_face_locations)

    matching_image_paths = {}

    for i, face_encoding in enumerate(target_face_encodings):
        matches = face_recognition.compare_faces(known_encodings, face_encoding, tolerance=tolerance)
        matching_image_paths[i] = [image_paths[j] for j, match in enumerate(matches) if match]

    return matching_image_paths

# WhatsApp自动化逻辑
def init_whatsapp_web(driver_path):
    options = webdriver.ChromeOptions()
    # 保存会话,避免重复扫码
    options.add_argument("user-data-dir=./whatsapp_session")
    driver = webdriver.Chrome(executable_path=driver_path, options=options)
    driver.get("https://web.whatsapp.com/")
    print("请扫码登录WhatsApp Web,登录后按回车继续...")
    input()
    return driver

def download_latest_image(driver, temp_dir):
    try:
        # 获取最新图片消息
        image_elements = driver.find_elements(By.XPATH, "//div[@data-testid='message-image']")
        if not image_elements:
            return None
        
        latest_image = image_elements[-1]
        latest_image.click()
        time.sleep(2)
        
        # 下载原图
        download_btn = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//div[@data-testid='download']"))
        )
        download_btn.click()
        time.sleep(3)
        
        # 移动到临时目录
        download_dir = os.path.expanduser("~/Downloads")
        files = sorted(os.listdir(download_dir), key=lambda x: os.path.getctime(os.path.join(download_dir, x)))
        latest_file = files[-1]
        src_path = os.path.join(download_dir, latest_file)
        dest_path = os.path.join(temp_dir, latest_file)
        shutil.move(src_path, dest_path)
        
        # 关闭预览窗口
        close_btn = driver.find_element(By.XPATH, "//div[@data-testid='close']")
        close_btn.click()
        time.sleep(1)
        
        return dest_path
    except Exception as e:
        print(f"下载图片出错: {e}")
        return None

def send_images_to_user(driver, images_paths):
    try:
        # 打开附件菜单
        attach_btn = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//div[@data-testid='attach-menu']"))
        )
        attach_btn.click()
        time.sleep(1)
        
        # 选择图片并添加
        image_input = driver.find_element(By.XPATH, "//input[@accept='image/*,video/mp4,video/3gpp,video/quicktime']")
        for img_path in images_paths:
            image_input.send_keys(img_path)
            time.sleep(2)
        
        # 发送图片
        send_btn = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//div[@data-testid='send']"))
        )
        send_btn.click()
        time.sleep(3)
    except Exception as e:
        print(f"发送图片出错: {e}")

def main():
    # 配置参数
    driver_path = "./chromedriver"  # 替换为你的ChromeDriver路径
    wedding_images_folder = "./faces"  # 婚礼图片数据库目录
    temp_dir = "./temp_images"
    os.makedirs(temp_dir, exist_ok=True)
    
    # 加载人脸编码库
    known_encodings, image_paths = load_face_images(wedding_images_folder)
    print(f"已加载 {len(known_encodings)} 个人脸编码")
    
    # 初始化WhatsApp Web
    driver = init_whatsapp_web(driver_path)
    
    try:
        print("开始监听消息...")
        while True:
            # 检查新图片
            img_path = download_latest_image(driver, temp_dir)
            if img_path:
                print(f"收到新图片: {img_path}")
                # 人脸比对
                target_image = face_recognition.load_image_file(img_path)
                matching_paths = search_person_in_images(target_image, known_encodings, image_paths)
                # 去重收集匹配图片
                all_matches = list(set([path for paths in matching_paths.values() for path in paths]))
                
                if all_matches:
                    print(f"找到 {len(all_matches)} 张匹配图片,正在发送...")
                    send_images_to_user(driver, all_matches)
                else:
                    print("未找到匹配图片")
                
                # 删除临时文件
                os.remove(img_path)
            
            time.sleep(5)  # 每5秒检查一次消息
    except KeyboardInterrupt:
        print("程序终止")
    finally:
        driver.quit()
        shutil.rmtree(temp_dir)

if __name__ == "__main__":
    main()

3. 关键注意事项

  • ChromeDriver版本:必须与本地Chrome浏览器版本完全匹配,否则会启动失败。
  • 会话保留:第一次扫码登录后,user-data-dir目录会保存登录状态,后续启动无需重复扫码。
  • 反限制机制:WhatsApp Web对自动化操作有检测,避免过于频繁的消息收发,建议调整监听间隔(比如5-10秒)。
  • 图片去重:同一张婚礼图片可能包含多个匹配人脸,用set去重避免重复发送。

内容的提问来源于stack exchange,提问作者eitan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:59:51