python脚本,通过facebook官方API,每天自动在Facebook公共主页发帖

✍️Auth:运维笔记       Date:2024/11/19       Cat:python相关       👁️:250 次浏览

一,简介

基本功能实现,每天自动在公共主页,发布ywtv.live电影网站最新图文帖子,同时在帖子下发送评论链接。
电影更新内容,在数据库中获取更新信息,下载图片,然后通过脚本发送至公共主页。

准备工作,facebook创建公共主页,https://www.facebook.com/profile.php?id=61567617441502

登录https://developers.facebook.com/,创建应用。
创建类型”商务”,商务类型包含公共主页所有权限,不需要额外申请权限。此账号需要是公共主页的管理员或者拥有者才有权限。

应用模式默认为“开发中”,开发中的通过脚本发送的帖子,只有本账号才可以看见查看,其他人不可见。最后测试完成,需要将模式改“上线”默认,发送的帖子所有人才可以看见。


创建完成后,在图谱 API 探索工具,选择自己的公共主页可以查看临时口令token。正式上线可以申请永久口令。


口令token分三种,其他口令获取方式,参考文档
临时口令:几小时过期
长期口令:60天有效期
长期主页访问口令:永久有效,仅限公主主页使用,如果账号管理员权限改动,也会失效。

二,代码基本介绍

1. 导入必要的模块

from dotenv import load_dotenv
import mysql.connector
import requests
import os
import time
import emoji
import logging

dotenv:用于加载环境变量。
mysql.connector:用于连接 MySQL 数据库。
requests:用于发送 HTTP 请求(如下载图片和调用 Facebook API)。
os:处理文件系统路径和环境变量。
time:用于延时。
emoji:用于在文本中添加表情符号。
logging:配置日志记录。

2. 配置日志

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

配置日志记录级别为 INFO,并设置日志格式。

3. 加载环境变量和配置 Facebook API 信息

load_dotenv()
page_id = os.getenv('page_id')
access_token = os.getenv('access_token')
graph_url = f"https://graph.facebook.com/v21.0/{page_id}/photos"

从 .env 文件中加载 Facebook 的 page_id 和 access_token,构建发布图片的 API URL。

4. 配置 MySQL 数据库连接信息

DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_HOST = os.getenv('DB_HOST')
DB_NAME = os.getenv('DB_NAME')

从环境变量中加载 MySQL 数据库的用户名、密码、主机地址和数据库名。

5. 定义图片的基础 URL

IMG_BASE_URL = 'https://ywtv.live/'  # 图片的基础 URL

这里定义了图片的基础 URL,用于拼接生成完整的图片链接。

6. 函数 fetch_movie_updates:获取最近两小时内的电影更新

def fetch_movie_updates():
    ...

连接 MySQL 数据库,执行查询,获取最近两小时内更新的电影数据。每条数据包含电影 ID、名称、类型、年份、图片地址、地区和简介。
查询成功后关闭连接并返回结果。

7. 函数 download_image:下载并保存图片

def download_image(image_url, image_filename):
    ...

通过请求 image_url 下载图片,并保存到本地路径 image_filename。
下载成功则返回 True,失败则记录错误并返回 False。

8. 函数 post_to_facebook:将电影信息发布到 Facebook

def post_to_facebook(movie, image_filename):
    ...

构建发布的消息内容,包括电影的标题、类型、简介等信息,并嵌入表情符号。
如果图片文件存在,发送请求将图片和消息一起发布到 Facebook。
发布成功后获取帖子 ID,并在该帖子下发布两个评论:
评论1:播放地址链接。
评论2:频道链接。
如果发布失败,记录错误信息。

9. 函数 post_comment:在帖子下发布评论

def post_comment(post_id, comment_message):
    ...

接受 post_id 和 comment_message,通过 Facebook API 在指定帖子下发布评论。
发布成功则记录日志,失败则记录错误信息。

10. 主程序逻辑

if __name__ == "__main__":
    movies = fetch_movie_updates()

    for movie in movies:
        ...
        if not os.path.exists(image_filename):
            downloaded_image = download_image(image_url, image_filename)
            if not downloaded_image:
                continue

        post_to_facebook(movie, image_filename)

        time.sleep(60)  # 在每个电影之间增加等待时间

调用 fetch_movie_updates() 获取电影更新列表。
遍历每部电影的信息:
检查本地是否已存在图片文件,不存在则调用 download_image 下载图片。
调用 post_to_facebook 将电影信息发布到 Facebook。
在每次发布之间增加 60秒的延时,获取更久,以降低被频率限制的风险。

三,完整代码

环境参数.env配置

vim .env

.env 内容,配置数据库参数,和公共主页ID(公共主页简介展示查看)和口令token。

DB_USER='user'
DB_PASSWORD='pasword'
DB_HOST='192.168.10.100'
DB_NAME='moive'

page_id = '442713123261478'
access_token = 'EAAHutHIL8TUBO6X...'

最后代码为:

from dotenv import load_dotenv
import mysql.connector
import requests
import os
import time
import emoji
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

load_dotenv()
# Facebook API 配置
page_id = os.getenv('page_id')
access_token = os.getenv('access_token')
graph_url = f"https://graph.facebook.com/v21.0/{page_id}/photos"

# 打印 Page ID 和 Access Token 检查是否为空

# MySQL 配置
DB_USER = os.getenv('DB_USER')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB_HOST = os.getenv('DB_HOST')
DB_NAME = os.getenv('DB_NAME')

# 图片基础 URL
IMG_BASE_URL = 'https://ywtv.live/'  # 图片的基础 URL

def fetch_movie_updates():
    """
    连接 MySQL 数据库并获取最近2小时内的电影更新信息。
    """
    try:
        connection = mysql.connector.connect(
            user=DB_USER,
            password=DB_PASSWORD,
            host=DB_HOST,
            database=DB_NAME
        )
        cursor = connection.cursor(dictionary=True)

        # 查询数据库获取最近2小时内的电影更新信息
        query = """
            SELECT vod_id, vod_name, vod_class, vod_year, vod_pic, vod_area, vod_blurb
            FROM mac_vod 
            WHERE FROM_UNIXTIME(vod_time) >= NOW() - INTERVAL 2 HOUR
            AND type_id_1 = 1
            ORDER BY vod_time DESC
        """
        cursor.execute(query)
        result = cursor.fetchall()

        cursor.close()
        connection.close()
        logging.info(f"获取到 {len(result)} 条电影更新。")
        return result
    except mysql.connector.Error as err:
        logging.error(f"数据库错误: {err}")
        return []

def download_image(image_url, image_filename):
    """
    下载图片并保存到指定路径。
    """
    try:
        response = requests.get(image_url, stream=True)
        if response.status_code == 200:
            # 创建目录
            os.makedirs(os.path.dirname(image_filename), exist_ok=True)
            with open(image_filename, 'wb') as out_file:
                for chunk in response.iter_content(1024):
                    out_file.write(chunk)
            logging.info(f"成功下载图片: {image_filename}")
            return True
        else:
            logging.error(f"无法下载图片,状态码: {response.status_code}")
            return False
    except Exception as e:
        logging.error(f"下载图片时出错: {e}")
        return False

def post_to_facebook(movie, image_filename):
    """
    将电影信息发布到 Facebook,包括带图片的帖子。
    """
    message = (
        "✅有味影視ywtv資源更新✅:\n\n"
        "⬇️播放地址請見評論區⬇️\n\n"
        f"-片名{emoji.emojize(':clapper_board:')}:【{movie['vod_name']}】\n\n"
        f"-類型{emoji.emojize(':clown_face:')}:【{movie['vod_class']}/{movie['vod_area']}/{movie['vod_year']}】\n\n"
        f"-簡介{emoji.emojize(':open_book:')}:{movie['vod_blurb']}\n\n"
        "----------------------------------\n"
        "加入我们的讨论小组:有味影视讨论小组 https://www.facebook.com/groups/1036832098191473\n"
    )

    # 检查图片是否存在
    if not os.path.exists(image_filename):
        logging.info(f"图片 {image_filename} 不存在,跳过该电影。")
        return

    # 准备请求数据
    files = {
        'file': open(image_filename, 'rb')
    }
    data = {
        'caption': message,
        'access_token': access_token
    }

    # 发送请求到 Facebook
    response = requests.post(graph_url, files=files, data=data)

    if response.status_code == 200:
        post_id = response.json().get('post_id')
        logging.info(f"成功发布电影:{movie['vod_name']},Post ID: {post_id}")
        time.sleep(1) 
        # 发布评论1:在线播放地址
        comment1 = f"https://ywtv.live/index.php/vod/detail/id/{movie['vod_id']}.html 在線播放地址"
        post_comment(post_id, comment1)

        time.sleep(1) 
        # 发布评论2:TG 频道链接
        comment2 = "https://t.me/ywtv_live 電影頻道,每天更多即時更新,全站資源線上搜尋"
        post_comment(post_id, comment2)

    else:
        logging.error(f"发布失败,状态码:{response.status_code}")
        logging.error(f"响应信息:{response.json()}")

def post_comment(post_id, comment_message):
    """
    在发布的帖子下发布评论
    """
    comment_url = f"https://graph.facebook.com/v21.0/{post_id}/comments"
    data = {
        'message': comment_message,
        'access_token': access_token
    }
    response = requests.post(comment_url, data=data)

    if response.status_code == 200:
        logging.info(f"成功发布评论: {comment_message}")
    else:
        logging.error(f"发布评论失败,状态码:{response.status_code}")
        logging.error(f"响应信息:{response.json()}")


if __name__ == "__main__":
    # 获取最近的电影更新
    movies = fetch_movie_updates()

    # 遍历电影列表并发布到 Facebook
    for movie in movies:
        image_url = f"{IMG_BASE_URL}{movie['vod_pic']}"  # 构建图片 URL
        image_filename = f"images/{movie['vod_id']}.jpg"  # 本地保存路径

        # 如果图片不存在,则下载
        if not os.path.exists(image_filename):
            logging.info(f"图片 {image_filename} 不存在,开始下载...")
            downloaded_image = download_image(image_url, image_filename)
            if not downloaded_image:
                logging.error(f"图片 {image_filename} 下载失败,跳过该电影。")
                continue

        # 发布到 Facebook
        post_to_facebook(movie, image_filename)

        # 在每个电影之间增加随机等待时间,减少频率限制的风险
        time.sleep(600)

四,效果演示

脚本运行演示,已经发送。参考主页:https://www.facebook.com/profile.php?id=61567617441502


查看评论区:

最后在服务器设置个定时任务就可以了,同时将日志输送到文件。

python3 fb_public.py >> fb_public.log 2>&1

查看日志文件显示

打赏作者

发表评论