下载地址:www.pan38.com/yun/share.p… 提取密码:1133
这个自动发布工具包含完整的模块化设计,支持多平台发布、内容管理、定时任务和日志记录等功能。使用时需要根据各平台的实际API进行调整,并注意遵守各平台的使用规则。
源码部分哈:【仅供学习参考~~~】
import os
import time
import random
from datetime import datetime
from platforms import Xiaohongshu, Douyin, Kuaishou
from content_manager import ContentManager
from scheduler import Scheduler
from logger import setup_logger
logger = setup_logger('auto_poster')
class AutoPoster:
def __init__(self):
self.platforms = {
'xiaohongshu': Xiaohongshu(),
'douyin': Douyin(),
'kuaishou': Kuaishou()
}
self.content_manager = ContentManager()
self.scheduler = Scheduler()
def authenticate_all(self):
for name, platform in self.platforms.items():
try:
platform.login()
logger.info(f"{name} 登录成功")
except Exception as e:
logger.error(f"{name} 登录失败: {str(e)}")
def prepare_content(self, content_type):
return self.content_manager.get_content(content_type)
def post_to_platform(self, platform_name, content):
platform = self.platforms.get(platform_name)
if not platform:
logger.error(f"不支持的平台: {platform_name}")
return False
try:
result = platform.upload(content)
logger.info(f"内容已成功发布到 {platform_name}")
return result
except Exception as e:
logger.error(f"发布到 {platform_name} 失败: {str(e)}")
return False
def batch_post(self, content_type, platforms):
content = self.prepare_content(content_type)
if not content:
logger.error("内容准备失败")
return
for platform in platforms:
self.post_to_platform(platform, content)
time.sleep(random.randint(5, 15)) # 随机延迟避免被封
def run_scheduled_posts(self):
self.scheduler.run(self)
if __name__ == "__main__":
poster = AutoPoster()
poster.authenticate_all()
poster.run_scheduled_posts()
import requests
import json
from fake_useragent import UserAgent
class BasePlatform:
def __init__(self):
self.session = requests.Session()
self.ua = UserAgent()
self.headers = {
'User-Agent': self.ua.random,
'Accept': 'application/json',
'Accept-Language': 'zh-CN,zh;q=0.9',
}
def login(self):
raise NotImplementedError
def upload(self, content):
raise NotImplementedError
def _make_request(self, method, url, data=None, files=None):
try:
response = self.session.request(
method,
url,
headers=self.headers,
data=data,
files=files,
timeout=30
)
response.raise_for_status()
return response.json()
except Exception as e:
raise Exception(f"请求失败: {str(e)}")
class Xiaohongshu(BasePlatform):
def __init__(self):
super().__init__()
self.base_url = "https://edith.xiaohongshu.com/api"
self.login_url = f"{self.base_url}/sns/login"
def login(self):
# 实际实现中需要替换为真实的登录逻辑
login_data = {
'username': 'your_username',
'password': 'your_password',
'captcha': ''
}
response = self._make_request('POST', self.login_url, data=login_data)
self.headers['X-Session-Id'] = response.get('session_id')
return True
def upload(self, content):
upload_url = f"{self.base_url}/sns/note/create"
files = None
if content.get('images'):
files = [('images', (img['name'], img['data'])) for img in content['images']]
data = {
'title': content['title'],
'desc': content['description'],
'content': content['content'],
'topic_ids': json.dumps(content.get('topics', [])),
'at_users': json.dumps(content.get('mentioned_users', [])),
'location': json.dumps(content.get('location', {}))
}
return self._make_request('POST', upload_url, data=data, files=files)
class Douyin(BasePlatform):
# 类似实现,省略部分代码...
pass
class Kuaishou(BasePlatform):
# 类似实现,省略部分代码...
pass
import os
import random
from PIL import Image
import io
from datetime import datetime
class ContentManager:
def __init__(self):
self.content_templates = self._load_templates()
self.image_pool = self._load_images()
self.video_pool = self._load_videos()
def _load_templates(self):
# 加载内容模板
return [
{
'title': '今日穿搭分享',
'description': '今天穿这套出门被夸了好多次!',
'content': '详细穿搭介绍...'
},
# 更多模板...
]
def _load_images(self):
# 加载图片资源
images = []
img_dir = 'resources/images'
if os.path.exists(img_dir):
for img_file in os.listdir(img_dir):
if img_file.lower().endswith(('.png', '.jpg', '.jpeg')):
with open(os.path.join(img_dir, img_file), 'rb') as f:
images.append({
'name': img_file,
'data': f.read()
})
return images
def _load_videos(self):
# 加载视频资源
videos = []
video_dir = 'resources/videos'
if os.path.exists(video_dir):
for video_file in os.listdir(video_dir):
if video_file.lower().endswith(('.mp4', '.mov', '.avi')):
with open(os.path.join(video_dir, video_file), 'rb') as f:
videos.append({
'name': video_file,
'data': f.read()
})
return videos
def get_content(self, content_type):
template = random.choice(self.content_templates)
if content_type == 'note':
images = random.sample(self.image_pool, min(3, len(self.image_pool)))
return {
**template,
'images': images,
'topics': ['穿搭', '时尚'],
'mentioned_users': ['user123']
}
elif content_type == 'video':
video = random.choice(self.video_pool)
return {
**template,
'video': video,
'hashtags': ['vlog', '日常']
}
else:
return None
def generate_thumbnail(self, image_data, size=(800, 800)):
img = Image.open(io.BytesIO(image_data))
img.thumbnail(size)
thumb_io = io.BytesIO()
img.save(thumb_io, format='JPEG')
return thumb_io.getvalue()
import schedule
import time
from datetime import datetime, timedelta
import random
import threading
class Scheduler:
def __init__(self):
self.jobs = []
self.running = False
self.thread = None
def add_daily_job(self, time_str, func, *args, **kwargs):
schedule.every().day.at(time_str).do(func, *args, **kwargs)
def add_random_job(self, min_hours, max_hours, func, *args, **kwargs):
def job_wrapper():
func(*args, **kwargs)
next_run = datetime.now() + timedelta(
hours=random.uniform(min_hours, max_hours)
)
schedule.every().day.at(next_run.strftime('%H:%M')).do(job_wrapper)
initial_run = datetime.now() + timedelta(
hours=random.uniform(0, max_hours)
)
schedule.every().day.at(initial_run.strftime('%H:%M')).do(job_wrapper)
def run(self, poster):
self.running = True
# 添加定时任务
self.add_daily_job('09:30', poster.batch_post, 'note', ['xiaohongshu'])
self.add_daily_job('12:00', poster.batch_post, 'video', ['douyin', 'kuaishou'])
self.add_random_job(3, 6, poster.batch_post, 'note', ['xiaohongshu'])
def run_continuously():
while self.running:
schedule.run_pending()
time.sleep(1)
self.thread = threading.Thread(target=run_continuously)
self.thread.start()
def stop(self):
self.running = False
if self.thread:
self.thread.join()