I have a page that I need to periodically update the file location for a link to point at a new file. Trying to do this via a Python script using requests
.
I've got authentication set up via 'Application Passwords' plugin, and I'm able to download a json from the api for the page in question. I have a pre-built string that contains the new file location, ready to go. I extract the page content, specifically the 'rendered' version, as a string. I do a quick replace()
on that string between two known tags (<h4>
) and then reload the modified 'rendered' page content back into the json, and upload it back to the endpoint, again using requests()
.
When it's all said and done, I'm getting no errors from the script, a status code of 200... but nothing changes on the page.
Furthermore, I'm finding the following in the error log:
[21-Aug-2019 00:12:51 UTC] PHP Warning: Invalid argument supplied for foreach() in /home1/example/public_html/wp-includes/rest-api/class-wp-rest-request.php on line 778
Not exactly sure what that means, but I'm assuming it's not good.
import base64, json, requests
user = 'admin'
pythonapp = 'QUDM PYFn xfyK 9Hhe Ayf2 hk6k'
url = 'https://example.com/wp-json/wp/v2'
data_string = user + ':' + pythonapp
token = base64.b64encode(data_string.encode())
headers = {'Authorization':'Basic ' + token.decode('utf8')}
newsletterURL = 'http://www.example.com/wp-content/uploads/2019/08/lorem-ipsum.pdf'
oldH4 = '<h4><a href="http://www.example.com/wp-content/uploads/2019/08/NCWGC-2019-8.pdf" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">Click here to download the newsletter!!!</a></h4>'
newH4 = '<h4><a href="' + newsletterURL + '" target="_blank" rel="noreferrer noopener" aria-label=" (opens in a new tab)">Click here to download the newsletter!!!</a></h4>'
# Download the current Newsletter page
r = requests.get(url + '/pages/6', headers=headers)
tmp = r.json()
Pretty sure the code up to this point works as intended/expected; obviously it's been somewhat modified to be a stand-alone example vs. part of the larger script.
oldPageContent = tmp['content']['rendered']
# print(oldPageContent.partition('</h4>')[0])
newPageContent = oldPageContent.replace(oldH4, newH4)
# print(newPageContent.partition('</h4>')[0])
tmp['content']['rendered'] = newPageContent
# print(tmp['content']['rendered'].partition('</h4>')[0])
r = requests.post(url + '/pages/6', headers=headers, json=tmp)
# print(json.loads(r.content.decode('utf8'))['content']['rendered'].partition('</h4>')
Here I'm attempting to replace the specific URL inside the body content, reassemble things, and upload the whole thing back to the
"content": {
"rendered": "\n<h4><a href=\"http://www.example.com/wp-content/uploads/2019/08/NCWGC-2019-8.pdf\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Click here to download the newsletter!!!</a></h4>\n\n\n\n<p>Submissions for the newsletter are always welcome. Space is somewhat limited so keep \u2019em short and sweet!",
"protected": false
}
This is an example of the specific field that I'm trying to extract from the content of the page, update, and upload.
Kinda thinking maybe I should be using json.dumps/loads
to get at ['content']['rendered']
rather than just r.json()
? Though when I print out the resulting strings, they sure look like right...
Any ideas/suggestions for updating a page via the REST api? Or am I going about this completely wrong?
Update:
After the excellent help from @SallyCJ, this is the final form of what I ended up with, in case it helps anyone else down the road:
import base64, json, re, requests
user = 'admin'
pythonapp = 'QUDM PYFn xfyK 9Hhe Ayf2 hk6k'
url = 'https://example.com/wp-json/wp/v2'
data_string = user + ':' + pythonapp
token = base64.b64encode(data_string.encode())
headers = {'Authorization':'Basic ' + token.decode('utf8')}
# Temporary URL for the sake of testing
newsletterURL = 'http://www.example.com/wp-content/uploads/2019/08/lorem-ipsum.pdf'
# Download the current Newsletter page
r = requests.get(url + '/pages/6', headers=headers)
# Extract the actual page content from all the rest of the API data
data = r.json()
content = data['content']['rendered']
# Find the URL for the download in 'content', and replace it with the new URL
regex = r"(http(s)?)://(www.)?(example.com\/wp-content/uploads\/).+(pdf)"
newContent = re.sub(regex, newsletterURL,content)
# Create a new data payload using the updated 'content'
data = {"content": newContent}
# Upload it back to the site
r = requests.post(url + '/pages/6', headers=headers, json=data)