Last Updated on 2021-10-17 by Clay
最近比較多網友詢問了我關於如何透過程式在 WordPress 上發表文章,正好藉這次的機會,嘗試使用之前比較沒有研究的 REST API 來達到發表文章的目的。
什麼是 REST API
REST(Representational State Transfer, 表現層狀態轉換)是一種架構相對簡潔的網路傳遞資訊建構風格。使用者只需要根據自己的需求設定好 HTTP 的參數、屬性,便可以在伺服器的接口上,使用不同的軟體及程式發出請求。
所以,REST 本身是一種設計的『風格』。而今天我要紀錄的,則是所謂的 WordPress REST API,也即是 WordPress 面向開發人員所設計程式接口。
如果我的解釋有未盡之處,請參閱官方的手冊:https://developer.wordpress.org/rest-api/
而我們要若要使用 WordPress REST API,則需要完成下面兩個步驟:
- 建立『Application Passwords』
- 撰寫程式執行操作
其實並不複雜。
Application Passwords
在 WordPress 5.6 及以後版本中,這個功能已經預設開啟;而若低於此版本的話,則建議可以搜尋相關的外掛,比方說著名的『Application Passwords』plugin 來啟用。
首先前往後台,在左側選單中找到 "User"-> "Profile"。
往下找到 Application Passwords 的欄位,並設定新的應用程式名稱。這裡可以取個有意義、不會忘記的名稱,幫助自己辨識。
建立完畢後,應該會看到隨機產生的密碼。密碼應是英數混雜、大小寫區分的以下格式:
xxxx xxxx xxxx xxxx xxxx xxxx
最後別忘了更新 profile。我第一次操作時忘記更新,導致我後續步驟一直失敗,十分悲憤。
撰寫程式執行操作
在這一小節,我使用 Python 程式語言來發出請求。如有其他熟悉的語言,也可以使用其他語言進行請求,並無限制。
我會紀錄以下幾個 demo:
- 確認 REST API 能夠訪問網站
- 發表文章
- 更新文章
- 刪除文章
確認 REST API 能夠訪問網站
首先,這是最重要的一步。若是訪問時返回的網頁狀態碼並非 200,則需要上網查詢相關資訊,並依照錯誤訊息進行調整。
# coding: utf-8
import base64
import json
import requests
from pprint import pprint
def main():
# Init
url = "https://YOURS.com/wp-json/wp/v2/posts"
username = "USERNAME"
password = "PASSWORD"
credentials = "{}:{}".format(username, password)
token = base64.b64encode(credentials.encode())
# Header
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Authorization": "Basic {}".format(token.decode("utf-8")),
"content-type": "application/json",
}
# Check
r = requests.get(
url,
headers=headers,
)
# Print
print(r)
if __name__ == "__main__":
main()
Output:
<Response [200]>
這裡介紹幾個重要的參數:
- url: 你的 WordPress 網站中 REST API 位址
- username:帳號,也可能是你的電子郵件地址
- password:這裡並不是真的密碼,而是剛剛所生成的『應用程式密碼』
- headers:標頭。這裡的 3 個參數都很重要。
若程式回傳了狀態碼 200,那麼恭喜!你的 WordPress 網站使用 REST API 多半是沒有問題的。
發表文章
發表文章跟剛才的操作很像,只是從 get()
變成了 post()
。
與此同時,還需要額外設定文章的資訊。詳細情況請參閱下方程式碼:
# coding: utf-8
import base64
import json
import requests
from pprint import pprint
def main():
# Init
url = "https://YOURS.com/wp-json/wp/v2/posts"
username = "USERNAME"
password = "PASSWORD"
credentials = "{}:{}".format(username, password)
token = base64.b64encode(credentials.encode())
# Header
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Authorization": "Basic {}".format(token.decode("utf-8")),
"content-type": "application/json",
}
# Post info
post = {
"title": "This is a REST API test",
"content": "Accessed.",
"status": "draft",
}
# Post
r = requests.post(
url,
headers=headers,
json=post,
)
# Print
pprint(r.text)
if __name__ == "__main__":
main()
Output:
('{"id":5204,"date":"2021-03-22T04:58:33","date_gmt":"2021-03-22T04:58:33","guid":{"rendered":"https:\\/\\/clay-atlas.com\\/?p=5204","raw":"https:\\/\\/clay-atlas.com\\/?p=5204"},"modified":"2021-03-22T04:58:33","modified_gmt":"2021-03-22T04:58:33","password":"","slug":"","status":"draft","type":"post","link":"https:\\/\\/clay-atlas.com\\/?p=5204","title":{"raw":"This '
'is a REST API test","rendered":"This is a REST API '
'test"},"content":{"raw":"Accessed.","rendered":"<p>Accessed.<\\/p>\\n","protected":false,"block_version":0},"excerpt":{"raw":"","rendered":"<p>Accessed.<\\/p> ...
若返回了上方資訊,則代表發表成功(雖然只是草稿)。你應該可以在後台看到我們剛才新增的草稿:
內容也與剛才設定的並無二致。
更新文章
還記得剛才發表文章後,我們螢幕上所印出的文章 ID: 5204 嗎?當然,當你測試的時候,你的文章 ID 會與我的不同;若要更新該篇文章的話,則需要記起文章的 ID。
可以參考下方程式碼:
# coding: utf-8
import base64
import json
import requests
from pprint import pprint
def main():
# Init
url = "https://YOURS.com/wp-json/wp/v2/posts"
username = "USERNAME"
password = "PASSWORD"
credentials = "{}:{}".format(username, password)
token = base64.b64encode(credentials.encode())
# Header
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Authorization": "Basic {}".format(token.decode("utf-8")),
"content-type": "application/json",
}
# Post info
post_id = 5204 # <--- add post id
post = {
"title": "This is a REST API test",
"content": "Updated!", # <--- change the content
"status": "draft",
}
# Post
r = requests.post(
"{}/{}".format(url, post_id), # <--- change the url
headers=headers,
json=post,
)
# Print
pprint(r.text)
if __name__ == "__main__":
main()
Output:
執行程式後,再次打開文章,應該會發現文章內容已經被更新了。
刪除文章
刪除文章就只需要文章的 ID、以及將 post()
修改為 delete()
即可。
# coding: utf-8
import base64
import json
import requests
from pprint import pprint
def main():
# Init
url = "https://YOURS.com/wp-json/wp/v2/posts"
username = "USERNAME"
password = "PASSWORD"
credentials = "{}:{}".format(username, password)
token = base64.b64encode(credentials.encode())
# Header
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"Authorization": "Basic {}".format(token.decode("utf-8")),
"content-type": "application/json",
}
# Post info
post_id = 5204
# Delete
r = requests.delete( # <--- change "post" to "delete"
"{}/{}".format(url, post_id),
headers=headers,
)
# Print
pprint(r.text)
if __name__ == "__main__":
main()
Output:
這時我們再去後台查看,應該會發現此篇文章已經被收至垃圾桶中了。
References
- https://medium.com/analytics-vidhya/wordpress-rest-api-with-python-f53a25827b1c
- https://blogs.pjjk.net/phil/using-the-wordpress-rest-api-to-post-a-book-from-wikisource-to-pressbooks-with-python/
- https://www.yannyann.com/2018/09/wp-rest-api-create-new-post-and-upload-image/
- https://blog.csdn.net/cunjie3951/article/details/106921938
我在你更新的時候,就嘗試的去用REST API更新文章,但大多得到都是400、401、403的錯誤,剛好你今天也更新文章,我有使用你的程式碼,第一段程式碼回傳200,那表示網站使用 REST API 多半是沒有問題的,但只要使用post之後,就開始回傳錯誤碼,這次是回傳401,讓我不禁思考是不是我的網站哪個地方設定錯誤
或許可以嘗試看看如何排除 401 的報錯:https://www.wpbeginner.com/wp-tutorials/how-to-fix-the-401-error-in-wordpress-solutions/
當然你可能早已嘗試過了也說不定,牽涉到更改後台安全防護時仍須小心。
希望你能早日成功,加油!
請容我再次追加我的回覆。
網頁狀態碼 401 是跟授權有關,建議檢查帳號與應用程式密碼是否輸入正確。
另外也可以考慮暫時關閉安全防護性的插件並再次執行程式碼。
祝一切順利。
在此感謝你的用心回覆,真的給予我很大的幫助,在聽了你的建議之後,我嘗試將所有的外掛關閉,並且再次去個人資料重新換一個新密碼(這動作之前也是一直重複做),結果就順利的將程式執行成功!!!後續我將所有外掛又重新開啟,依然可以執行,在這過程我只做了關閉外掛,重新換一個密碼。這裡也感謝你提供除了發文以外的其他程式碼,真的非常有幫助,我會在嘗試更多的功能。感謝你,你的網站提供很好的價值
哈哈,那太好了。
很高興能幫上忙。