--- tags: PTTLibrary --- # PTT Library 完全使用手冊 0.8 :::danger 註1: 此手冊僅支援 0.8.36,如果你使用 0.8 版本,請更新至 0.8.36 後再參考手冊 註2: 有出現在本手冊中的使用者或文章,如果不想出現,很抱歉請馬上告知我 註3: 此版本程式碼已經停止更新,如有修正將會更新在 0.9 或更新版本 註4: 如果你使用的是 0.9.x,請參考 [使用手冊 0.9](https://github.com/PttCodingMan/PyPtt/tree/master/doc) ::: 有任何問題都可以直接問我 [![chatroom icon](https://patrolavia.github.io/telegram-badge/chat.png)](https://t.me/PyPtt) Github: [PyPtt](https://github.com/PttCodingMan/PyPtt) --- ## 取得 ###### 安裝 ```batch= pip install PTTLibrary==0.8.36 ``` --- ## 例外 這裡列出了你可能遭遇到的例外 ###### PTT.Exceptions.LoginError 登入失敗 ###### PTT.Exceptions.NoSuchUser 無此使用者 ###### PTT.Exceptions.RequireLogin 使用此 API 前請先登入 ###### PTT.Exceptions.NoPermission 無權限,你可能被水桶或者帳號資格不符 ###### PTT.Exceptions.NoFastPush 此看板不支援快速推文,推文 API 會幫你重推 ###### PTT.Exceptions.UserOffline 使用者離線 ###### PTT.Exceptions.ParseError 此畫面解析錯誤,導致原因可能為傳輸過程中遺失訊息 ###### PTT.Exceptions.NoMoney 沒錢 ###### PTT.Exceptions.MoneyTooFew 錢太少 ###### PTT.Exceptions.NoSuchBoard 沒有這個看板 ###### PTT.Exceptions.ConnectionClosed Since 0.8.13 連線已經被關閉 ###### PTT.Exceptions.UnregisteredUser Since 0.8.13 尚未註冊使用者或被退註使用者,因權限受限將無法使用全部功能 ###### PTT.Exceptions.MultiThreadOperated Since 0.8.13 一個 PTT Library 物件只能被同一個 thread 操作 如果有第二個 thread 使用就會跳出此例外 ###### PTT.Exceptions.WrongIDorPassword Since 0.8.14 帳號密碼錯誤 ###### PTT.Exceptions.LoginTooOften Since 0.8.14 登入太頻繁 ###### PTT.Exceptions.UseTooManyResources Since 0.8.15 使用過多 PTT 資源,請稍等一段時間並增加操作之間的時間間隔 ###### PTT.Exceptions.HostNotSupport Since 0.8.25 批踢踢萬或批踢踢兔不支援這個操作 ###### PTT.Exceptions.NoPush Since 0.8.25 禁止推文 ###### PTT.Exceptions.NoResponse Since 0.8.26 禁止回應 ###### PTT.Exceptions.NeedModeratorPermission Since 0.8.26 需要板主權限 ###### PTT.Exceptions.NoSuchPost Since 0.8.27 沒有該文章 --- ## API ### 初始設定 :::info PTT Library 並不支援兩個以上的 thread 同時操作一個物件 如果有需求,請啟動新 thread 後,所有操作都在同一個 thread ::: 以下是初始化物件的方式 ```python= PTTBot = PTT.Library() ``` 如果有改變語言顯示的需求,目前有支援英文與繁體中文 ```python= PTTBot = PTT.Library( # (預設值) Chinese # Language=PTT.Language.Chinese, Language=PTT.Language.English, ) ``` 也可以修改 Log 等級方便回報錯誤 ```python= PTTBot = PTT.Library( # (預設值) INFO # LogLevel=PTT.LogLevel.INFO, # LogLevel=PTT.LogLevel.DEBUG, LogLevel=PTT.LogLevel.TRACE, ) ``` 當然如果你有需要將 log 輸出成檔案或者其他需要處理 log 的需求 你可以加入 log handler 就可以捕捉到所有輸出 Since 0.8.11 ```python= def handler(Msg): with open('LogHandler.txt', 'a', encoding='utf-8') as F: F.write(Msg + '\n') PTTBot = PTT.Library( LogHandler=handler ) ``` 當然 PTT Library 也支援批踢踢兔。 Since 0.8.25 ```python= PTT2Bot = PTT.Library( # (預設值) PTT1 # Host=PTT.Host.PTT1, # Host=PTT.Host.PTT2, Host=PTT.Host.PTT2 ) ``` --- ### 登入登出 以下就是登入登出範例 ```python= import sys from PTTLibrary import PTT PTTBot = PTT.Library() try: PTTBot.login(ID, Password) except PTT.Exceptions.LoginError: PTTBot.log('登入失敗') sys.exit() except PTT.Exceptions.WrongIDorPassword: PTTBot.log('帳號密碼錯誤') sys.exit() except PTT.Exceptions.LoginTooOften: PTTBot.log('請稍等一下再登入') sys.exit() PTTBot.log('登入成功') PTTBot.logout() ``` 執行結果 ![](https://i.imgur.com/wfaf8Bk.gif) 如果你的登入需要剔除其他的登入 那可以將 KickOtherLogin=True 加入 login 參數 ```python= import sys from PTTLibrary import PTT PTTBot = PTT.Library() try: PTTBot.login( ID, Password, KickOtherLogin=True ) except PTT.Exceptions.LoginError: PTTBot.log('登入失敗') sys.exit() except PTT.Exceptions.WrongIDorPassword: PTTBot.log('帳號密碼錯誤') sys.exit() except PTT.Exceptions.LoginTooOften: PTTBot.log('請稍等一下再登入') sys.exit() PTTBot.log('登入成功') PTTBot.logout() ``` --- ### 取得特定文章 以下便是最簡單的取得特定文章的範例 註: Python 板第 7486 篇文章 ```python= import sys from PTTLibrary import PTT Post = PTTBot.getPost( 'Python', PostIndex=7486 ) ``` 或者用 AID 也可以的 ```python= import sys from PTTLibrary import PTT Post = PTTBot.getPost( 'Python', PostAID='1TJH_XY0' ) ``` 從以上兩個範例可以看到 getPost 回傳了 Post 這裡面包含了文章所有屬性 這可以從以下範例明白怎麼取出每個屬性 ```python+=8 if Post is None: print('Post is None') return if Post.getDeleteStatus() != PTT.PostDeleteStatus.NotDeleted: if Post.getDeleteStatus() == PTT.PostDeleteStatus.ByModerator: print(f'[板主刪除][{Post.getAuthor()}]') elif Post.getDeleteStatus() == PTT.PostDeleteStatus.ByAuthor: print(f'[作者刪除][{Post.getAuthor()}]') elif Post.getDeleteStatus() == PTT.PostDeleteStatus.ByUnknow: print(f'[不明刪除]') return if not Post.isFormatCheck(): print('[不合格式]') return print('Board: ' + Post.getBoard()) print('AID: ' + Post.getAID()) print('Author: ' + Post.getAuthor()) print('Date: ' + Post.getDate()) print('Title: ' + Post.getTitle()) print('Content: ' + Post.getContent()) print('Money: ' + str(Post.getMoney())) print('URL: ' + Post.getWebUrl()) print('IP: ' + Post.getIP()) # 在文章列表上的日期 print('List Date: ' + Post.getListDate()) print('地區: ' + Post.getLocation()) # Since 0.8.19 print('文章推文數: ' + Post.getPushNumber()) if Post.isUnconfirmed(): # Since 0.8.30 print('待證實文章') PushCount = 0 BooCount = 0 ArrowCount = 0 for Push in Post.getPushList(): if Push.getType() == PTT.PushType.Push: Type = '推' PushCount += 1 if Push.getType() == PTT.PushType.Boo: Type = '噓' BooCount += 1 if Push.getType() == PTT.PushType.Arrow: Type = '箭頭' ArrowCount += 1 Author = Push.getAuthor() Content = Push.getContent() Buffer = f'{Author} 給了一個{Type} 說 {Content}' if Push.getIP() is not None: Buffer += f'來自 {Push.getIP()}' Buffer += f'時間是 {Push.getTime()}' print(Buffer) print(f'Total {PushCount} Pushs {BooCount} Boo {ArrowCount} Arrow') ``` 執行結果 ![](https://i.imgur.com/M6XGFzD.png) :::info 備註: 因為 PTT 推文計數有三分鐘的時間間隔,所以在使用推文條件搜尋的情況下 可能導致結果不夠即時 ::: 當然如果需要加條件搜尋也是可以的 只是我們需要知道加了搜尋條件之後的最大編號是多少 請看以下範例 ```python= TestList = [ ('Python', PTT.PostSearchType.Keyword, '[公告]') ] for (Board, SearchType, Condition) in TestList: Index = PTTBot.getNewestIndex( PTT.IndexType.BBS, Board, SearchType=SearchType, SearchCondition=Condition, ) print(f'{Board} 最新文章編號 {Index}') Post = PTTBot.getPost( Board, PostIndex=Index, SearchType=SearchType, SearchCondition=Condition, ) print('標題:') print(Post.getTitle()) print('內文:') print(Post.getContent()) print('=' * 50) ``` 執行結果 ![](https://i.imgur.com/jF63MGp.png) 如果只需要對文章按 Q 的資訊 Since 0.8.16 ![](https://i.imgur.com/TJ9xMO0.png) 你可以啟用 Query 模式,這樣就不會點進去解析內文、推文跟 IP 等等 可以加快一些速度,並減少出錯機率 ```python= Post = PTTBot.getPost( Board, PostIndex=Index, Query=True, ) ``` --- ### 取得最新文章編號 當你想要取得的文章編號範圍包含最新文章的時候, 你就會需要這隻 API 來取得最新編號是多少 ```python= TestBoardList = [ 'Wanted', 'Gossiping', 'Test', 'Stock', 'movie', ] for Board in TestBoardList: Index = PTTBot.getNewestIndex( PTT.IndexType.BBS, Board=Board ) print(f'{Board} 最新文章編號 {Index}') ``` 當然如果下了搜尋條件,編號也會跟著不同,這時候只需要把搜尋條件塞進去即可 ```python= TestList = [ # ('Stock', PTT.PostSearchType.Keyword, '盤中閒聊'), ('Baseball', PTT.PostSearchType.Push, '20') ] for (Board, SearchType, Condition) in TestList: NewestIndex = PTTBot.getNewestIndex( PTT.IndexType.BBS, Board, SearchType=SearchType, SearchCondition=Condition, ) print(f'{Board} 最新文章編號 {NewestIndex}') ``` 如果是需要取得網頁版的最新頁數,則只需要改一下 Index Type 即可 Since 0.8.25 ```python= TestBoardList = [ 'Wanted', 'Gossiping', 'Test', 'Stock', 'movie', ] for Board in TestBoardList: Index = PTTBot.getNewestIndex( PTT.IndexType.Web, Board=Board ) print(f'{Board} 網頁版最新頁數 {Index}') ``` --- ### 取得大範圍文章 以下是大範圍爬文範例 [效能比較表](https://hackmd.io/@CodingMan/crawlerbenchmark) ```python= Query = False def crawlHandler(Post): global Query if Post.getDeleteStatus() != PTT.PostDeleteStatus.NotDeleted: if Post.getDeleteStatus() == PTT.PostDeleteStatus.ByModerator: print(f'[板主刪除][{Post.getAuthor()}]') elif Post.getDeleteStatus() == PTT.PostDeleteStatus.ByAuthor: print(f'[作者刪除][{Post.getAuthor()}]') elif Post.getDeleteStatus() == PTT.PostDeleteStatus.ByUnknow: print(f'[不明刪除]') return print(f'[{Post.getAID()}][{Post.getTitle()}]') TestBoard='Gossiping' TestRange = 1000 NewestIndex = PTTBot.getNewestIndex( PTT.IndexType.BBS, Board=TestBoard ) StartIndex = NewestIndex - TestRange + 1 print(f'預備爬行 {TestBoard} 編號 {StartIndex} ~ {NewestIndex} 文章') ErrorPostList, DelPostList = PTTBot.crawlBoard( crawlHandler, PTT.CrawlType.BBS, TestBoard, # 使用 Index 來標示文章範圍 StartIndex=StartIndex, EndIndex=NewestIndex, # 使用 AID 來標示文章範圍 # Since 0.8.27 StartAID=StartAID, EndAID=EndAID, # Index 與 AID 標示方式擇一即可 ) if len(ErrorPostList) > 0: print('格式錯誤文章: \n' + '\n'.join(str(x) for x in ErrorPostList)) else: print('沒有偵測到格式錯誤文章') if len(DelPostList) > 0: print(f'共有 {len(DelPostList)} 篇文章被刪除') ``` 執行結果 ![](https://i.imgur.com/BO3QLf2.png) :::info 備註: 因為 PTT 推文計數有三分鐘的時間間隔,所以在使用推文條件搜尋的情況下 可能導致結果不夠即時 ::: 當然我們也可以像 getPost 那樣加入搜尋條件來爬我們的結果 :::info 在有下搜尋條件的情況下,無法使用 AID 來標記爬文範圍 ::: ```python= def showCondition(Board, SearchType, Condition): if SearchType == PTT.PostSearchType.Keyword: Type = '關鍵字' if SearchType == PTT.PostSearchType.Author: Type = '作者' if SearchType == PTT.PostSearchType.Push: Type = '推文數' if SearchType == PTT.PostSearchType.Mark: Type = '標記' if SearchType == PTT.PostSearchType.Money: Type = '稿酬' print(f'{Board} 使用 {Type} 搜尋 {Condition}') TestRange = 10 TestList = [ ('Wanted', PTT.PostSearchType.Keyword, '[公告]'), ('Wanted', PTT.PostSearchType.Author, 'gogin'), ('Wanted', PTT.PostSearchType.Push, '10'), ('Wanted', PTT.PostSearchType.Mark, 'm'), ('Wanted', PTT.PostSearchType.Money, '5'), ('Gossiping', PTT.PostSearchType.Keyword, '[公告]'), ('Gossiping', PTT.PostSearchType.Author, 'ReDmango'), ('Gossiping', PTT.PostSearchType.Push, '10'), ('Gossiping', PTT.PostSearchType.Mark, 'm'), ('Gossiping', PTT.PostSearchType.Money, '5'), ('Gossiping', PTT.PostSearchType.Push, '-100'), ('Gossiping', PTT.PostSearchType.Push, '150'), ] for (Board, SearchType, Condition) in TestList: showCondition(Board, SearchType, Condition) NewestIndex = PTTBot.getNewestIndex( PTT.IndexType.BBS, Board, SearchType=SearchType, SearchCondition=Condition, ) print(f'{Board} 最新文章編號 {NewestIndex}') StartIndex = NewestIndex - TestRange + 1 # 有下條件的情況下,無法使用 AID 來標記範圍 ErrorPostList, DelPostList = PTTBot.crawlBoard( crawlHandler, PTT.CrawlType.BBS, Board, StartIndex=StartIndex, EndIndex=NewestIndex, SearchType=SearchType, SearchCondition=Condition, ) # print('標題: ' + Post.getTitle()) print('=' * 50) ``` 如果只需要對文章按 Q 的資訊 Since 0.8.16 ![](https://i.imgur.com/p4kt1JC.png) 你可以啟用 Query 模式,這樣就不會點進去解析內文、推文跟 IP 等等 可以加快一些速度,並減少出錯機率 ```python= ErrorPostList, DelPostList = PTTBot.crawlBoard( crawlHandler, PTT.CrawlType.BBS, TestBoard, StartIndex=StartIndex, EndIndex=NewestIndex, Query=True, # Optional ) ``` --- ### 貼文推文 以下範例是在測試板貼文的範例 ```python= Board = 'Test' Content = '\r\n\r\n'.join( [ 'PTT Library 貼文測試,如有打擾請告知。', '程式碼: https://tinyurl.com/y2wuh8ck' ] ) PTTBot.post( # 看板 Board, # 標題 'PTT Library 程式貼文測試', # 內文 Content, # 標題分類 1, # 簽名檔 0 ) ``` 以下則是推文範例 ```python+=20 Index = PTTBot.getNewestIndex(PTT.IndexType.BBS, Board=Board) print(f'{Board} 最新文章編號 {Index}') Content = ''' What is Ptt? 批踢踢 (Ptt) 是以學術性質為目的,提供各專業學生實習的平台,而以電子佈告欄系統 (BBS, Bulletin Board System) 為主的一系列服務。 期許在網際網路上建立起一個快速、即時、平等、免費,開放且自由的言論空間。批踢踢實業坊同時承諾永久學術中立,絕不商業化、絕不營利。 ''' PTTBot.push(Board, PTT.PushType.Push, Content, PostIndex=IndexOfPost) ``` 執行結果 ![](https://i.imgur.com/EhJlJ2l.png) ![](https://i.imgur.com/bd1Vjjf.png) --- ### 查詢使用者 以下是查詢使用者範例 如果查無使用者則會丟出 PTT.Exceptions.NoSuchUser 例外 ```python= try: User = PTTBot.getUser('CodingMan') if User is None: return PTTBot.log('使用者ID: ' + User.getID()) PTTBot.log('使用者經濟狀況: ' + str(User.getMoney())) PTTBot.log('登入次數: ' + str(User.getLoginTime())) PTTBot.log('有效文章數: ' + str(User.getLegalPost())) PTTBot.log('退文文章數: ' + str(User.getIllegalPost())) PTTBot.log('目前動態: ' + User.getState()) PTTBot.log('信箱狀態: ' + User.getMail()) PTTBot.log('最後登入時間: ' + User.getLastLogin()) PTTBot.log('上次故鄉: ' + User.getLastIP()) PTTBot.log('五子棋戰績: ' + User.getFiveChess()) PTTBot.log('象棋戰績:' + User.getChess()) PTTBot.log('簽名檔:' + User.getSignatureFile()) except PTT.Exceptions.NoSuchUser: print('無此使用者') ``` 執行結果 ![](https://i.imgur.com/wz4Zcy6.png) --- ### 呼叫器 在這裡將會展示取得現在呼叫器狀態後 隨機地去設定除了現在以外的一種呼叫器狀態 ```python= def showCallStatus(CallStatus): if CallStatus == PTT.CallStatus.On: print('呼叫器狀態[打開]') elif CallStatus == PTT.CallStatus.Off: print('呼叫器狀態[關閉]') elif CallStatus == PTT.CallStatus.Unplug: print('呼叫器狀態[拔掉]') elif CallStatus == PTT.CallStatus.Waterproof: print('呼叫器狀態[防水]') elif CallStatus == PTT.CallStatus.Friend: print('呼叫器狀態[朋友]') else: print(f'Unknow CallStatus: {CallStatus}') CallStatus = PTTBot.getCallStatus() showCallStatus(CallStatus) TestQueue = [x for x in range( PTT.CallStatus.MinValue, PTT.CallStatus.MaxValue + 1 )] random.shuffle(TestQueue) TestQueue.remove(CallStatus) PTTBot.setCallStatus(TestQueue[0]) CallStatus = PTTBot.getCallStatus() showCallStatus(CallStatus) ``` 執行結果 ![](https://i.imgur.com/C0qco4O.png) --- ### 水球 首先展示丟水球的範例 在這裡則可以看到有兩種例外 無此使用者 PTT.Exceptions.NoSuchUser 使用者離線 PTT.Exceptions.UserOffline ```python= TagetID = 'SampleUser' TestWaterBall = '水球測試 :D' try: PTTBot.throwWaterBall(TagetID, TestWaterBall) except PTT.Exceptions.NoSuchUser: print('無此使用者') except PTT.Exceptions.UserOffline: print('使用者離線') ``` 接下來是接水球範例 建議如果要穩定收到水球請參考 [呼叫器](#呼叫器) 先將呼叫器切換成關閉 ```python= import sys import time # 存取歷史水球可以有三個後續動作可以選 # 不做任何事 # OperateType = PTT.WaterBallOperateType.DoNothing # 存入信箱 # OperateType = PTT.WaterBallOperateType.Mail # 清除 OperateType = PTT.WaterBallOperateType.Clear while True: WaterBallList = PTTBot.getWaterBall(OperateType) if WaterBallList is None: time.sleep(1) continue for WaterBall in WaterBallList: if WaterBall.getType() == PTT.WaterBallType.Catch: # 收到水球 Temp = '★' + WaterBall.getTarget() + ' ' elif WaterBall.getType() == PTT.WaterBallType.Send: # 你丟出去的水球紀錄 Temp = 'To ' + WaterBall.getTarget() + ': ' Temp += WaterBall.getContent() + ' [' + WaterBall.getDate() + ']' print(Temp) ``` --- ### 給 P 幣 以下是給 P 幣的範例 ```python= PTTBot.giveMoney('CodingMan', 100) ``` 簡單到不知道要寫什麼,嗯 --- ### 寄信 以下是寄信範例 如果對象不存在則會丟出 PTT.Exceptions.NoSuchUser 例外 ```python= ID = 'SampleUser' Content = '\r\n\r\n'.join( [ '如有誤寄,對..對不起', 'PTT Library 程式寄信測試內容', '程式碼: https://tinyurl.com/y2wuh8ck' ] ) try: PTTBot.mail( # 寄信對象 ID, # 標題 '程式寄信標題', # 內文 Content, # 簽名檔 0 ) except PTT.Exceptions.NoSuchUser: print('No Such User') ``` 執行結果 ![](https://i.imgur.com/749XDXD.png) ![](https://i.imgur.com/V5R24nJ.png) ![](https://i.imgur.com/XubpFRP.png) --- ### 偵測是否有新信 ```python= HowManyNewMail = PTTBot.hasNewMail() if HowManyNewMail > 0: print(f'You got {HowManyNewMail} mail(s)') else: print('No new mail') ``` 執行結果 ![](https://i.imgur.com/15iTEbM.png) --- ### 取得所有 PTT 看板名稱 Since 0.8.13 ```python= BoardList = PTTBot.getBoardList() print(f'總共有 {len(BoardList)} 個板名') ``` 執行結果 ![](https://i.imgur.com/mWoxxEA.png) --- ### 取得我的最愛列表 Since 0.8.28 ```python= FavouriteBoardList = PTTBot.getFavouriteBoard() for board in FavouriteBoardList: # getBoard 板名 # getType 類別 # getBoardTitle 板標 Buff = f'[{board.getBoard()}][{board.getType()}][{board.getBoardTitle()}]' print(Buff) ``` 執行結果 ![](https://i.imgur.com/ynLfYJn.png) --- ### 搜尋網友 以下是搜尋網友功能,輸入部分帳號回傳所有可能 支援特定頁面範圍,以提升搜尋效能 Since 0.8.30 ```python= userlist = PTTBot.searchUser( 'coding', # minpage=1, # maxpage=10 ) print(userlist) print(len(userlist)) ``` 執行結果 ![](https://i.imgur.com/gce3qy4.png) --- ### 取得看板資訊 Since 0.8.32 以下是取得看板資訊 API ```python= getSetting = True BoardInfo = PTTBot.getBoardInfo('Gossiping', setting=getSetting) print('板名: ', BoardInfo.getBoard()) print('線上人數: ', BoardInfo.getOnlineUser()) if getSetting: print('中文敘述: ', BoardInfo.getChineseDes()) print('板主: ', BoardInfo.getModerators()) print('公開狀態(是否隱形): ', BoardInfo.isOpen()) print('隱板時是否可進入十大排行榜: ', BoardInfo.canIntoTopTenWhenHide()) print('是否開放非看板會員發文: ', BoardInfo.canNonBoardMembersPost()) print('是否開放回應文章: ', BoardInfo.canReplyPost()) print('是否開放自刪文章: ', BoardInfo.canSelfDelPost()) print('是否開放推薦文章: ', BoardInfo.canPushPost()) print('是否開放噓文: ', BoardInfo.canBooPost()) print('是否可以快速連推文章: ', BoardInfo.canFastPush()) print('推文最低間隔時間: ', BoardInfo.getMinInterval()) print('推文時是否記錄來源 IP: ', BoardInfo.isPushRecordIP()) print('推文時是否對齊開頭: ', BoardInfo.isPushAligned()) print('板主是否可刪除部份違規文字: ', BoardInfo.canModeratorCanDelIllegalContent()) print('轉錄文章是否自動記錄,且是否需要發文權限: ', BoardInfo.isTranPostAutoRecordedAndRequirePostPermissions()) print('是否為冷靜模式: ', BoardInfo.isCoolMode()) print('是否需要滿十八歲才可進入: ', BoardInfo.isRequire18()) print('發文與推文限制需多少次以上: ', BoardInfo.getRequireLoginTime()) print('發文與推文限制退文篇數多少篇以下: ', BoardInfo.getRequireIllegalPost()) ``` ![](https://i.imgur.com/TIR71MY.png) 執行結果 ![](https://i.imgur.com/unHbEUp.png) --- ## 板主專用 API ### 設定板標 Since 0.8.26 如果有定時設定板標的需求,這時候就可以使用 setBoardTitle ```python= from time import gmtime, strftime PTTBot = PTT.Library() try: PTTBot.login( ID, Password, ) except PTT.Exceptions.LoginError: PTTBot.log('登入失敗') sys.exit() while True: Time = strftime('%H:%M:%S') try: PTTBot.setBoardTitle( 'SampleBoard', f'現在時間 {Time}' ) except PTT.Exceptions.ConnectionClosed: while True: try: PTTBot.login( ID, Password, KickOtherLogin=True ) except PTT.Exceptions.LoginError: PTTBot.log('登入失敗') time.sleep(1) except PTT.Exceptions.ConnectError: PTTBot.log('登入失敗') time.sleep(1) except PTT.Exceptions.UseTooManyResources: while True: try: PTTBot.login( ID, Password, KickOtherLogin=True ) except PTT.Exceptions.LoginError: PTTBot.log('登入失敗') time.sleep(1) except PTT.Exceptions.ConnectError: PTTBot.log('登入失敗') time.sleep(1) print('已經更新時間 ' + Time, end='\r') try: time.sleep(1) except KeyboardInterrupt: print('已經更新時間 ' + Time) PTTBot.setBoardTitle( 'SampleBoard', '原來的板標' ) print('板標已經恢復') break ``` --- ### 標記文章 Since 0.8.26 如果板主有標記文章 S or D 的需求,可以參考以下使用方法 ```python= # s 文章 MarkType = PTT.MarkType.S # 標記文章 MarkType = PTT.MarkType.D # 刪除標記文章 MarkType = PTT.MarkType.DeleteD # M 起來 # Since 0.8.27 MarkType = PTT.MarkType.M # 待證實文章 # Since 0.8.30 MarkType = PTT.MarkType.Unconfirmed PTTBot.markPost( MarkType, 'YourBoad', # AID 與 Index 擇一使用 PostAID, # PostIndex 可搭配 SearchType and SearchCondition 使用 PostIndex, SearchType, # Optional SearchCondition # Optional ) ``` --- ## 疑難排解 ### 在 jupyter 使用 因為 jupyter 內部也使用了 asyncio 作為協程管理工具 會跟 PTT Library 內部的 asyncio 衝突 所以如果想要在 jypyter 內使用,請在你的程式碼中加入以下程式碼 安裝 ```python= ! pip install nest_asyncio ``` 引用 ```python= import nest_asyncio ``` 全部引用完之後 ```python= nest_asyncio.apply() ``` 就可以順利在 jupyter 使用了 ### Po 文上色教學 如果在 Po 文的時候有上色的需求,可以透過模擬鍵盤輸入的方式達到上色碼的效果 ```python= Content = [ PTT.Command.Ctrl_C + PTT.Command.Left + '5' + PTT.Command.Right + '這是閃爍字' + PTT.Command.Ctrl_C, PTT.Command.Ctrl_C + PTT.Command.Left + '31' + PTT.Command.Right + '前景紅色' + PTT.Command.Ctrl_C, PTT.Command.Ctrl_C + PTT.Command.Left + '44' + PTT.Command.Right + '背景藍色' + PTT.Command.Ctrl_C, ] Content = '\r\n'.join(Content) PTTBot.post( 'Test', 'PTT Library 程式貼文測試', Content, 1, 0 ) ``` 執行結果 ![](https://i.imgur.com/TOskgf0.png)