下载地址:www.pan38.com/yun/share.p… 提取密码:5575
这个小红书批量发布工具包含三个主要文件:主上传程序、配置文件和主程序入口。它支持批量上传图片和视频,自动添加标题和标签,并包含随机等待时间以避免频繁操作。使用时需要安装selenium、requests等依赖库。
import os
import time
import random
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from PIL import Image
import cv2
import numpy as np
import json
import mimetypes
class XiaohongshuUploader:
def __init__(self, username, password):
self.username = username
self.password = password
self.driver = None
self.logged_in = False
self.session = requests.Session()
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Referer': 'https://www.xiaohongshu.com/',
'Origin': 'https://www.xiaohongshu.com'
}
def init_driver(self):
chrome_options = Options()
chrome_options.add_argument("--disable-notifications")
chrome_options.add_argument("--disable-infobars")
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--window-size=1920,1080")
chrome_options.add_argument("--start-maximized")
chrome_options.add_argument("--headless") # 无头模式
self.driver = webdriver.Chrome(options=chrome_options)
self.driver.implicitly_wait(10)
def login(self):
self.driver.get("https://www.xiaohongshu.com/user/profile")
# 等待登录页面加载
try:
WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//input[@placeholder='请输入手机号']"))
)
except:
print("已登录或页面加载失败")
return True
# 输入用户名和密码
username_input = self.driver.find_element(By.XPATH, "//input[@placeholder='请输入手机号']")
username_input.send_keys(self.username)
password_input = self.driver.find_element(By.XPATH, "//input[@placeholder='请输入密码']")
password_input.send_keys(self.password)
# 点击登录按钮
login_button = self.driver.find_element(By.XPATH, "//button[contains(text(),'登录')]")
login_button.click()
# 等待登录完成
try:
WebDriverWait(self.driver, 20).until(
EC.presence_of_element_located((By.XPATH, "//div[contains(@class,'user-info')]"))
)
self.logged_in = True
print("登录成功")
return True
except:
print("登录失败")
return False
def upload_image(self, image_path, caption, tags=[]):
if not self.logged_in:
if not self.login():
return False
# 打开发布页面
self.driver.get("https://www.xiaohongshu.com/explore")
time.sleep(2)
# 点击发布按钮
publish_button = self.driver.find_element(By.XPATH, "//div[contains(@class,'publish-btn')]")
publish_button.click()
time.sleep(1)
# 选择图片上传
file_input = self.driver.find_element(By.XPATH, "//input[@type='file']")
file_input.send_keys(os.path.abspath(image_path))
time.sleep(3)
# 输入标题
caption_input = self.driver.find_element(By.XPATH, "//textarea[@placeholder='分享你的生活...']")
caption_input.send_keys(caption)
time.sleep(1)
# 添加标签
for tag in tags:
caption_input.send_keys(" #" + tag)
time.sleep(0.5)
# 点击发布
publish_button = self.driver.find_element(By.XPATH, "//button[contains(text(),'发布')]")
publish_button.click()
time.sleep(5)
# 检查是否发布成功
try:
WebDriverWait(self.driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//div[contains(text(),'发布成功')]"))
)
print(f"图片发布成功: {image_path}")
return True
except:
print(f"图片发布失败: {image_path}")
return False
def upload_video(self, video_path, caption, tags=[]):
if not self.logged_in:
if not self.login():
return False
# 打开发布页面
self.driver.get("https://www.xiaohongshu.com/explore")
time.sleep(2)
# 点击发布按钮
publish_button = self.driver.find_element(By.XPATH, "//div[contains(@class,'publish-btn')]")
publish_button.click()
time.sleep(1)
# 切换到视频上传
video_tab = self.driver.find_element(By.XPATH, "//div[contains(text(),'视频')]")
video_tab.click()
time.sleep(1)
# 选择视频上传
file_input = self.driver.find_element(By.XPATH, "//input[@type='file']")
file_input.send_keys(os.path.abspath(video_path))
time.sleep(10) # 等待视频上传和转码
# 输入标题
caption_input = self.driver.find_element(By.XPATH, "//textarea[@placeholder='分享你的生活...']")
caption_input.send_keys(caption)
time.sleep(1)
# 添加标签
for tag in tags:
caption_input.send_keys(" #" + tag)
time.sleep(0.5)
# 点击发布
publish_button = self.driver.find_element(By.XPATH, "//button[contains(text(),'发布')]")
publish_button.click()
time.sleep(10)
# 检查是否发布成功
try:
WebDriverWait(self.driver, 15).until(
EC.presence_of_element_located((By.XPATH, "//div[contains(text(),'发布成功')]"))
)
print(f"视频发布成功: {video_path}")
return True
except:
print(f"视频发布失败: {video_path}")
return False
def batch_upload_images(self, image_folder, captions_file, tags=[]):
with open(captions_file, 'r', encoding='utf-8') as f:
captions = [line.strip() for line in f.readlines()]
image_files = [f for f in os.listdir(image_folder) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
for i, image_file in enumerate(image_files):
image_path = os.path.join(image_folder, image_file)
caption = captions[i % len(captions)] if captions else f"分享图片 {i+1}"
if not self.upload_image(image_path, caption, tags):
print(f"上传失败: {image_file}")
continue
# 随机等待时间,避免频繁操作
time.sleep(random.randint(10, 30))
def batch_upload_videos(self, video_folder, captions_file, tags=[]):
with open(captions_file, 'r', encoding='utf-8') as f:
captions = [line.strip() for line in f.readlines()]
video_files = [f for f in os.listdir(video_folder) if f.lower().endswith(('.mp4', '.mov', '.avi'))]
for i, video_file in enumerate(video_files):
video_path = os.path.join(video_folder, video_file)
caption = captions[i % len(captions)] if captions else f"分享视频 {i+1}"
if not self.upload_video(video_path, caption, tags):
print(f"上传失败: {video_file}")
continue
# 随机等待时间,避免频繁操作
time.sleep(random.randint(30, 60))
def close(self):
if self.driver:
self.driver.quit()
xiaohongshu_uploader import XiaohongshuUploader
import json
import time
def main():
# 加载配置
with open('config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
# 初始化上传器
uploader = XiaohongshuUploader(config['username'], config['password'])
uploader.init_driver()
try:
# 批量上传图片
if os.path.exists(config['image_folder']):
print("开始批量上传图片...")
uploader.batch_upload_images(
config['image_folder'],
config['captions_file'],
config['tags']
)
# 批量上传视频
if os.path.exists(config['video_folder']):
print("开始批量上传视频...")
uploader.batch_upload_videos(
config['video_folder'],
config['captions_file'],
config['tags']
)
except Exception as e:
print(f"发生错误: {str(e)}")
finally:
uploader.close()
if __name__ == "__main__":
main()