许多用户在使用 Telegram 时,希望将 PTT(批踢踢实业坊)上的特定看板文章或推文自动转发到自己的 Telegram 频道或群组中。然而,PTT 本身不提供官方 API,手动搬运又耗时费力。本文将手把手教你如何利用开源工具与 Telegram Bot 实现自动转传,无需编程基础也能快速上手。

问题现象描述

当你想要实时追踪 PTT 热门看板(如八卦版、股票版)的文章更新时,却发现需要频繁手动刷新网页或使用第三方 App 才能获取最新内容。更麻烦的是,若你想将这些信息分享到 Telegram 群组或频道,只能一条条复制粘贴,效率极低。此外,PTT 的网页版有时会因为流量限制或改版导致抓取失败,导致转传中断而不自知。本教程将解决以上所有痛点,帮助你实现从 PTT 到 Telegram 的全自动化消息流转。

第一步:准备运行环境与必要工具

要实现自动转传,我们需要一个能 7x24 小时运行的服务器或电脑,以及一个 Telegram Bot。

具体操作说明:

1. 获取 Telegram Bot Token:在 Telegram 中搜索 @BotFather,发送 /newbot命令,按提示输入机器人名称和用户名(如 MyPTTForwarderBot)。创建成功后,BotFather 会返回一串 API Token(格式如 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11),请务必复制并保存好

2. 准备运行环境:推荐使用免费的云服务器(如 Oracle Cloud 的永久免费实例)或家里的旧电脑(安装 Linux 系统,如 Ubuntu 22.04)。如果你没有服务器,也可以使用 ReplitHeroku这类在线平台(注意 Heroku 免费计划已取消,Replit 需配置 UptimeRobot 防止休眠)。

3. 安装必要软件:在服务器终端执行以下命令安装 Python 3 和 pip(若已安装可跳过):

`

sudo apt update && sudo apt install python3 python3-pip git -y

`

4. 安装核心库:执行 pip3 install python-telegram-bot requests beautifulsoup4 lxml安装 Telegram Bot 库、网络请求库和 HTML 解析库。

注意事项/小提示:

  • 如果使用 Windows 系统运行,建议安装 WSL2(Windows Subsystem for Linux)或使用 Python 虚拟环境,避免路径冲突。
  • Bot Token 是机器人的唯一凭证,切勿公开分享,否则他人可控制你的机器人。
  • 免费云服务器通常有 CPU 和内存限制,PTT 转传脚本非常轻量,完全够用。

备用方案:

  • 如果没有服务器,可以使用 GitHub Actions的定时任务(Cron Job)来执行脚本,但需要将 Token 存储在 Secrets 中。
  • 若不想自己搭建,可以寻找现成的第三方机器人(如 @ptt2telegram_bot),但存在隐私和稳定性风险。

第二步:编写 PTT 文章抓取脚本

这一步是核心,我们需要写一个 Python 脚本,定期抓取指定 PTT 看板的最新文章标题和链接。

具体操作说明:

1. 在服务器上创建一个文件夹(如 ptt_forwarder),然后新建文件 ptt_scraper.py

2. 写入以下代码(以抓取 Stock股票版为例):

`python

import requests

from bs4 import BeautifulSoup

import time

def fetch_ptt_articles(board='Stock', limit=5):

url = f'https://www.ptt.cc/bbs/{board}/index.html'

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}

try:

response = requests.get(url, headers=headers, timeout=10)

soup = BeautifulSoup(response.text, 'lxml')

articles = []

for item in soup.select('div.r-ent')[:limit]:

title_tag = item.select_one('div.title a')

if title_tag:

title = title_tag.text.strip()

link = 'https://www.ptt.cc' + title_tag['href']

articles.append({'title': title, 'link': link})

return articles

except Exception as e:

print(f'抓取失败: {e}')

return []

`

3. 保存文件后,在终端运行 python3 ptt_scraper.py测试,如果输出文章列表,说明抓取成功。

注意事项/小提示:

  • PTT 网页版对爬虫有一定限制,必须添加 User-Agent 头,否则可能被拒绝访问。
  • limit参数控制每次抓取的文章数量,建议设为 5-10,避免请求过于频繁被封 IP。
  • 如果抓取热门看板(如八卦版),建议增加 随机延迟(如 time.sleep(2))降低被 ban 风险。

备用方案:

  • 如果 requests被屏蔽,可以尝试使用 Selenium模拟浏览器,但资源消耗更大。
  • 也可以使用 PTT API 第三方封装库(如 ptt-lib),但维护性可能不如直接解析 HTML。

第三步:编写 Telegram 消息发送函数

抓取到文章后,需要将其格式化并发送到指定的 Telegram 频道或群组。

具体操作说明:

1. 在同一个文件夹中新建文件 telegram_sender.py,写入以下代码:

`python

import requests

BOT_TOKEN = '你的Bot Token' # 替换为实际Token

CHAT_ID = '@你的频道用户名或群组ID' # 例如 @my_channel 或 -1001234567890

def send_telegram_message(message):

url = f'https://api.telegram.org/bot{BOT_TOKEN}/sendMessage'

data = {

'chat_id': CHAT_ID,

'text': message,

'parse_mode': 'HTML',

'disable_web_page_preview': False # 设为True可关闭链接预览

}

try:

response = requests.post(url, data=data, timeout=10)

if response.status_code == 200:

print('消息发送成功')

else:

print(f'发送失败: {response.text}')

except Exception as e:

print(f'网络错误: {e}')

`

2. 获取 CHAT_ID:将机器人加入你的频道或群组后,访问 https://api.telegram.org/bot你的Token/getUpdates,在返回的 JSON 中找到 message.chat.id字段。如果是公开频道,直接使用 @频道用户名即可。

3. 在主脚本中调用此函数,例如:

`python

articles = fetch_ptt_articles()

for art in articles:

msg = f'{art["title"]}\n{art["link"]}'

send_telegram_message(msg)

time.sleep(1) # 避免触发频率限制

`

注意事项/小提示:

  • Telegram Bot 有 消息频率限制(大约每秒 20 条消息),如果文章较多,建议分批发送或合并成一条消息。
  • parse_mode设为 HTML后,可以使用 、等标签美化文本,但注意不要嵌套错误。
  • 如果你的频道是私有的,必须先将机器人设为管理员,否则无法发送消息。

备用方案:

  • 如果不想自己写发送函数,可以使用 python-telegram-bot 库send_message方法,功能更强大。
  • 对于大量文章,可以使用 队列系统(如 Redis 或简单的列表)暂存消息,再按节奏发送。

第四步:实现自动定时运行与去重

为了防止重复发送相同的文章,我们需要记录已发送的文章链接,并设置定时任务自动执行。

具体操作说明:

1. 实现去重机制:在脚本中添加一个本地文件 sent_links.txt来记录已发送的链接。修改主逻辑如下:

`python

def load_sent_links():

try:

with open('sent_links.txt', 'r') as f:

return set(line.strip() for line in f)

except FileNotFoundError:

return set()

def save_sent_links(links):

with open('sent_links.txt', 'a') as f:

for link in links:

f.write(link + '\n')

sent = load_sent_links()

articles = fetch_ptt_articles()

new_articles = [a for a in articles if a['link'] not in sent]

for art in new_articles:

msg = f'{art["title"]}\n{art["link"]}'

send_telegram_message(msg)

time.sleep(1)

save_sent_links([a['link'] for a in new_articles])

`

2. 设置定时任务:在 Linux 系统中使用 crontab。执行 crontab -e,添加以下行(每 5 分钟运行一次):

`

*/5 * * * * /usr/bin/python3 /home/user/ptt_forwarder/ptt_scraper.py

`

注意路径要使用绝对路径。

3. 测试定时任务:手动运行一次脚本,检查 sent_links.txt是否生成,以及 Telegram 是否收到消息。

注意事项/小提示:

  • 去重文件 sent_links.txt会逐渐增大,建议每月手动清理一次,或只保留最近 1000 条记录。
  • crontab 的路径和 Python 解释器路径必须写完整,否则任务可能无法执行。可以通过 which python3查看路径。
  • 如果使用 Windows,可以使用 任务计划程序nssm将脚本注册为服务。

备用方案:

  • 可以使用 SQLite 数据库代替文本文件来存储已发送链接,更稳定且支持并发。
  • 定时频率不宜过高(建议 5-10 分钟一次),PTT 文章更新速度有限,过频抓取可能浪费资源。

第五步:验证转传结果与异常处理

完成配置后,需要验证系统是否正常工作,并添加错误通知机制。

具体操作说明:

1. 手动触发测试:在终端执行 python3 ptt_scraper.py,观察是否输出新文章,并检查 Telegram 频道是否收到消息。

2. 检查日志:在脚本中添加日志输出,例如将错误信息写入 error.log

`python

import logging

logging.basicConfig(filename='forwarder.log', level=logging.INFO,

format='%(asctime)s - %(levelname)s - %(message)s')

`

然后用 logging.error()代替 print()记录错误。

3. 设置错误通知:当脚本连续失败 3 次时,发送一条报警消息到你的私人 Telegram 账号。可以创建一个简单的计数器:

`python

error_count = 0

while True:

try:

# 主逻辑

error_count = 0

except Exception as e:

error_count += 1

if error_count >= 3:

send_telegram_message('⚠️ PTT转发脚本连续失败3次,请检查!')

break

time.sleep(60)

`

注意事项/小提示:

  • 首次测试时,可以手动将 sent_links.txt清空,以便触发发送旧文章。
  • 如果发现文章内容为空或乱码,可能是 PTT 网页结构发生了变化,需要更新 BeautifulSoup 的选择器。
  • 建议在脚本中加入 网络重试机制(如使用 requestsretry适配器)。

备用方案:

  • 可以使用 Telegram Bot 的 Webhook代替轮询,但需要公网 IP 和 SSL 证书,适合更复杂的场景。
  • 对于关键看板,可以设置 多个备用抓取源(如 PTT 的 API 镜像站),在主源失败时自动切换。

常见问题补充

问:为什么脚本抓取不到文章?

答:最常见的原因是 PTT 网页版改版或反爬措施升级。请先手动访问 https://www.ptt.cc/bbs/Stock/index.html确认页面是否正常。如果正常,检查 User-Agent 是否设置正确,或尝试更换为 Mozilla/5.0的移动端版本。

问:发送消息时提示 "chat not found" 怎么办?

答:这通常是因为 CHAT_ID 填写错误机器人未加入目标群组/频道。请确认机器人已被设为管理员,且频道是公开的(或你使用了正确的群组 ID)。注意群组 ID 通常以 -100开头。

问:如何同时监控多个 PTT 看板?

答:可以在主脚本中循环遍历看板列表,例如:

`python

boards = ['Stock', 'Gossiping', 'C_Chat']

for board in boards:

articles = fetch_ptt_articles(board)

# 发送消息时注明看板名称

for art in articles:

msg = f'[{board}] {art["title"]}\n{art["link"]}'

send_telegram_message(msg)

`

注意每个看板的抓取间隔建议至少 2 秒,避免被 PTT 封 IP。

问:脚本运行一段时间后突然停止怎么办?

答:可能是服务器内存不足或网络中断。建议使用 systemdsupervisor来管理脚本,使其在崩溃后自动重启。例如使用 supervisor 的配置:

`

[program:ptt_forwarder]

command=python3 /path/to/script.py

autostart=true

autorestart=true

`

总结:通过搭建本地抓取脚本 + Telegram Bot,你可以轻松实现 PTT 文章到 Telegram 频道的自动转传,关键在于配置好去重机制和定时任务,并做好异常监控。