Home>

I described the process for posting the content described in JSON in Python to Twitter, but the following error occurred.
It is a situation that cannot be executed well.

I'm new to my program, so I don't understand Python and JSON. (There are some parts that I do not understand in this program)
We apologize for the inconvenience, but we would appreciate it if you could let us know.

Postscript (2020/11/18):
Since an additional error has occurred, it would be very helpful if you could teach us that as well.
We apologize for the inconvenience, but thank you.

Addendum 2 (2020/11/19):
We have added the content I want to check and the script you taught us to the script, so sorry to trouble you.
I would appreciate it if you could teach me.
* The script you taught is described as it is. I tried writing or trying the img_url that defines the url of convert_url (url) in JSON and the path of the file.
Image upload failed could not be resolved.

Execution environment

■ Google Colaboratory
■ JSON-Define tweet content and images here
■ Python-Processing to Tweet using JSON

* Both JSON and Python files are described in Google Colaboratory, and Google Drive is not mounted.

JSON content

JSON file name: tweetcontent.json
File path: /content/sample_data/tweetcontent.json

JSON content * Since the file path is the file path of the drive, we will describe it as the URL of the target file.

{
    "contents": [
                {
                    "img_url": "URL of target file",
                    "tweet_text": "image name"
                },


                {
                    "img_url": "URL of the target file",
                    "tweet_text": "image name"
                },


                {
                    "img_url": "URL of the target file",
                    "tweet_text": "image name"
                },


                {
                    "img_url": "URL of the target file","tweet_text": "image name"
                }
    ]
}
Python content

Python file name: TwitterBot.ipynb * It is not .py because it is in Colaboratory.

import json
from requests_oauthlib import OAuth1Session
Module for using #url
import urllib.request
import re #<------- added
#The following Twitter API key and access key are not listed.
CONSUMER_KEY ='****************************'
CONSUMER_SECRET ='****************************'
ACCESS_TOKEN ='****************************'
ACCESS_TOKEN_SECRET ='****************************'
#Twitter access key stored in variable
twitter = OAuth1Session (CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
#Regular expression used for url conversion
pattern = re.compile (r ". * \/File \ /. \/(. *) \ /. *") #<------- Added
#URL used for media upload
url_media = "https://upload.twitter.com/1.1/media/upload.json"
#URL used for text upload
url_text = "https://api.twitter.com/1.1/statuses/update.json"

#Added a function to convert a link on Google Drive to a url that can be obtained directly with twitter API etc.<-------
def convert_url (url):
    a = re.search (pattern, url)
    try: try:
        return "https://drive.google.com/uc?export=view&id=%s"% a.group (1)
    except (AttributeError, IndexError) as e:
        # If the pattern does not match, a message is issued and the passed url is returned as it is.
        print ("[% s] does not match the pattern, so it is returned as is."% Url)
        return url

Get tweet body and image url from #json file
def get_tweet_content (json_file_path):
  #Read a text file
  file = open (json_file_path,'r', encoding ='utf-8')
  #Load the opened file as JSON with the json.load function
  json_data = json.load (file)
  Store json data in the json_data variable that stores the file variable read as #JSON
  Get one element randomly from the list with # random.choice ()return random.choice (json_data ["contents"])

#Upload the image to Twitter and return media_id
#img_url is the image object specified in JSON
def upload__media (img_url):
  Open #url
  res = unllib.request.urlopen (img_url)
  img_data = res.read ()
  img_files = {'media': img_data}
  res_media = twitter.post (url_media, files = img_files)
  if res_media.status_code == 200:
      return json.loads (res_media.text) ['media_id']
  else: else:
      print ('Image upload failed:% s', res_media.text)
      exit ()

#Tweet with the body of the tweet and the media_id of the uploaded image as arguments
def post_tweet (tweet_text, media_id):
    params = {'status': tweet_text,'media_ids': media_id}
    res = twitter.post (url_text, params = params)
    if res.status_code == 200:
        print ('Auto Tweet Succeeded.')
    else: else:
        print ('Failed .:% d'% res.status_code)

def main ():
    json_file_path ='/content/sample_data/tweetcontent.json'
    tweet_content = get_tweet_content (json_file_path)
    media_id = upload_media (tweet_content ['img_url'])
    post_tweet (tweet_content ['tweet_text'],

 media_id)

* An error occurs during the following execution
if __name__ =='__main__':
  main ()
### error contents

* I think that the content described in JSON cannot be read.

NameError Traceback (most recent call last)
in()
1 ifname=='main':
---->2 main ()

1 frames
in main ()
1 def main ():
2 json_file_path ='/content/sample_data/tweetcontent.json'
---->3 tweet_content = get_tweet_content (json_file_path)
4 media_id = upload_media (tweet_content ['img_url'])
5 post_tweet (tweet_content ['tweet_text'], media_id)

in get_tweet_content (json_file_path)
6 Store json data in the json_data variable that stores the file variable read as #JSON.
7 Randomly get one element from the list with # random.choice ()
---->8 return random.choice (json_data ["contents"])

NameError: name'random' is not defined

Reference link

Automate tweets with images in Python and JSON

Additional errors

The above error "Name Error: name'random' is not defined" was resolved, and the tweet was successful as a text tweet.

However, the image tweet fails due to the following error.
We apologize for the inconvenience, but we would appreciate it if you could continue to teach us.
Thank you.

■ First execution
Image posting failure log:
Mounted Google Drive → Session crashed

↓ The following log is output

Image upload failed:% s {"request": "\/1.1 \/media \ /upload.json", "error": "media type unrecognized."}
Auto Tweet Succeeded.

■ Second execution
If i re-execute after the first execution, the following error will occur and it will reoccur.


NameError Traceback (most recent call last)
in()
1 ifname=='main':
---->2 main ()

NameError: name'main' is not defined

I want to check

-The argument url of convert_url (url) is the recognition that the value of the returned "" https://drive.google.com/uc?export=view&id=%s "% a.group (1)" is described. is this good. If the recognition is wrong, which value should be defined for the argument (file path specification, file path variable specified in JSON, etc.)?
-It seems that the main () function does not have a function to call convert_url (url). How should I call this function?
-The path of the json file is directly specified in the json_file_path described in the main () function. Is it correct to describe the json file name here?
-Is it the recognition that the defined function is executed from main as the execution method of Python? * Sorry for the introductory question

We apologize for the inconvenience, but thank you.

  • Answer # 1

    Since it is an error message that there is no random module, at the beginning
    import random
    Isn't it good to say?


    Postscript

    First, fix the part that doesn't work properly with the above code.
    In particular,

    def upload__media (img_url):


    To

    def upload_media (img_url):


    Change to. (Change the underscore between upload and data from two to one.)

    After that, change the "URL of the target file" of "img_url": in /content/sample_data/tweetcontent.json.
    When I changed it to a link to a freely usable material on the net and tested it,
    I was able to tweet images normally in my environment.

    When I changed the "URL of the target file" to a link to the image file on my Google Drive,
    Same as the questioner
    Image upload failed:% s {"request": "\/1.1 \/media \ /upload.json", "error": "media type unrecognized."}

    I got the error.

    Therefore, it is presumed that the image data cannot be obtained normally from the twitter API with the link obtained by "Getting the link" of Google Drive as it is.

    Therefore, in the code below, referring to the contents of stackoverrun, a function (convert_url) that converts the url into a form that can be obtained is added.

    Full text

    import json
    import random #<----------- Added from the beginning when answer was added
    import re #<------- added
    from requests_oauthlib import OAuth1Session
    Module for using #url
    import urllib.request
    #Regular expression used for url conversion
    pattern = re.compile (r ". * \/File \ /. \/(. *) \ /. *") #<------- Added
    #The following Twitter API key and access key are not listed.
    CONSUMER_KEY ='****************************'
    CONSUMER_SECRET ='****************************'
    ACCESS_TOKEN ='****************************'
    ACCESS_TOKEN_SECRET ='****************************'
    #Twitter access key stored in variable
    twitter = OAuth1Session (CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
    #URL used for media upload
    url_media = "https://upload.twitter.com/1.1/media/upload.json"
    #URL used for text upload
    url_text = "https://api.twitter.com/1.1/statuses/update.json"
    #Added a function to convert a link on Google Drive to a url that can be obtained directly with twitter API etc.<-------def convert_url (url):
        a = re.search (pattern, url)
        try: try:
            return "https://drive.google.com/uc?export=view&id=%s"% a.group (1)
        except (AttributeError, IndexError) as e:
            # If the pattern does not match, a message is issued and the passed url is returned as it is.
            print ("[% s] does not match the pattern, so it is returned as is."% Url)
            return url
    Get tweet body and image url from #json file
    def get_tweet_content (json_file_path):
      #Read a text file
      file = open (json_file_path,'r', encoding ='utf-8')
      #Load the opened file as JSON with the json.load function
      json_data = json.load (file)
      Store json data in the json_data variable that stores the file variable read as #JSON
      Get one element randomly from the list with # random.choice ()
      return random.choice (json_data ["contents"])
    #Upload the image to Twitter and return media_id
    #img_url is the image object specified in JSON
    def upload_media (img_url): # ===========================
      # Convert url #<------- Added from the beginning when answer is added
      img_url = convert_url (img_url) #<------- Added from the beginning when answer was added
      Open #url
      res = urllib.request.urlopen (img_url) # =========================
      img_data = res.read ()
      img_files = {'media': img_data}
      res_media = twitter.post (url_media, files = img_files)
      if res_media.status_code == 200:
          return json.loads (res_media.text) ['media_id']
      else: else:
          print ('Image upload failed:% s', res_media.text)
          exit ()
    #Tweet with the body of the tweet and the media_id of the uploaded image as arguments
    def post_tweet (tweet_text, media_id):
        params = {'status': tweet_text,'media_ids': media_id}
        res = twitter.post (url_text, params = params)
        if res.status_code == 200:
            print ('Auto Tweet Succeeded.')
        else: else:
            print ('Failed .:% d'% res.status_code)def main ():
        json_file_path ='/content/sample_data/tweetcontent.json' # Fixed file path.
        tweet_content = get_tweet_content (json_file_path)
        media_id = upload_media (tweet_content ['img_url'])
        post_tweet (tweet_content ['tweet_text'],
     media_id)
    if __name__ =='__main__':
        main ()

    -The argument url of convert_url (url) is the recognition that the value of the returned "" https://drive.google.com/uc?export=view&id=%s "% a.group (1)" is described. is this good.

    Yes or no is no.
    The path (img_url) to the file on the google drive described in tweetcontent.json is passed to the argument url of convert_url (url).

    If the recognition is wrong, which value should be defined for the argument (file path specification, file path variable specified in JSON, etc.)?

    In the argument url of convert_url (url), you should pass the path to the file on google drive as described in tweetcontent.json.

    The code of the answer is to pass "the path to the file on the google drive described in tweetcontent.json" to the convert_url function.

    -It seems that the main () function does not have a function to call convert_url (url). How should I call this function?

    Added a comment.
    From the beginning, the full answer code included the code to call convert_url (url) in the upload_media function.
    I forgot to put the comment "#<---- Add".

    Instead of calling convert_url (url) from main ()
    We are calling convert_url (url) from within the upload_media function.

    -The path of the json file is directly specified in the json_file_path described in the main () function. Is it correct to describe the json file name here?

    The answer code had the json file path for my test environment, so I modified it to the file path of the original question.
    There is no problem if you specify the path of the json file directly like the code of the original question.

    -Is it the recognition that the defined function is executed from main as the execution method of Python? * Sorry for the introductory question

    There is no particular restriction to execute from main.

    In python, it is read in order from the top (though it is a story ignoring import), and if there is a part that can be executed, it will be executed from the top.
    However, the function definition part (def) and class definition part (class) are only read and not executed.
    (* The above explanation is not completely accurate considering the details such as the behavior when import is read, but it is okay if you think that it is such an atmosphere)

    Example:

    [1]

    def sub (a, b):
      print ("Called sub function")
      return a --bdef main (a, b):
      print ("Called main function")
      return a + b
    #Since it is the first line to appear except for the definition of functions, etc., it is executed from here.
    if __name__ =='__main__':
       #main () does not have to be the first
       print (sub (1,2))
       print (main (1,2))

    [2]

    def sub (a, b):
      print ("Called sub function")
      return a --b
    def main (a, b):
      print ("Called main function")
      return a + b
    #if __name__ == Even without'__main__':
    #Because it is the first line to appear except for the function definition, it is executed from here.
    print (sub (1,2))
    print (main (1,2))

    [3]

    def sub (a, b):
      print ("Called sub function")
      return a --b
    The function named #main does not have to exist
    def add (a, b):
      print ("Called the add function")
      return a + b
    if __name__ =='__main__':
       print (sub (1,2))
       print (add (1,2))

    [Four]

    def sub (a, b):
      print ("Called sub function")
      return a --b
    def add (a, b):
      print ("Called the add function")
      return a + b
    #Because it is the first line to appear except for the function definition, it is executed from here.
    print (sub (1,2))
    print (add (1,2))
    # Below this is evaluated and executed after the above two lines are executed.
    if __name__ =='__main__':
       print ('execution: IF __name__ = = __ main__ :')