質問するログイン新規登録

回答編集履歴

10

修正

2020/11/19 05:38

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -123,15 +123,15 @@
123
123
  > ・convert_url(url)の引数urlはreturnされた「"https://drive.google.com/uc?export=view&id=%s" % a.group(1)」の値が記載されている認識でよろしいでしょうか。
124
124
 
125
125
  yesかnoかでいえばnoです。
126
- convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパス(img_url)が渡されます。
126
+ convert_url(url)の引数urlには、tweetcontent.json内に記載されている、googleドライブ上のファイルへのパス(img_url)が渡されます。
127
127
 
128
128
 
129
129
 
130
130
  > 認識が間違っている場合、引数にはどの値(ファイルパス指定、JSONに記載したファイルパスの変数を指定など)を定義するべきでしょうか。
131
131
 
132
- convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパスを渡すべきです。
132
+ convert_url(url)の引数urlには、tweetcontent.jsonに記載されている、googleドライブ上のファイルへのパスを渡すべきです。
133
133
 
134
- なお、回答のコードは「JSONに記載されたgoogleドライブへのパス」をconvert_url関数に渡すようにしています。
134
+ 回答のコードは「tweetcontent.jsonに記載されたgoogleドライブ上のファイルへのパス」をconvert_url関数に渡すようにしています。
135
135
 
136
136
 
137
137
 

9

修正

2020/11/19 05:38

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -129,9 +129,9 @@
129
129
 
130
130
  > 認識が間違っている場合、引数にはどの値(ファイルパス指定、JSONに記載したファイルパスの変数を指定など)を定義するべきでしょうか。
131
131
 
132
- convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパス「JSONに記載したファイルパス」を渡すべきです。
132
+ convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパスを渡すべきです。
133
133
 
134
- なお、回答のコードは、元質問のコードをなるべく変えないように「JSONに記載されたgoogleドライブへのパス」をconvert_url関数に渡すようにしています。
134
+ なお、回答のコードは「JSONに記載されたgoogleドライブへのパス」をconvert_url関数に渡すようにしています。
135
135
 
136
136
 
137
137
 

8

修正

2020/11/19 05:32

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -129,8 +129,9 @@
129
129
 
130
130
  > 認識が間違っている場合、引数にはどの値(ファイルパス指定、JSONに記載したファイルパスの変数を指定など)を定義するべきでしょうか。
131
131
 
132
- 引数には、JSONに記載したgoogleドライブへのパス(url)がされていればよいの、元質問のコードから変える必要はありません
132
+ convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパス「JSONに記載したファイルパス」をすべき
133
133
 
134
+ なお、回答のコードは、元質問のコードをなるべく変えないように「JSONに記載されたgoogleドライブへのパス」をconvert_url関数に渡すようにしています。
134
135
 
135
136
 
136
137
 

7

修正

2020/11/19 03:57

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -208,7 +208,7 @@
208
208
 
209
209
  # mainという名前の関数は存在する必要はない
210
210
  def add(a,b):
211
- print("main関数を呼び出しました")
211
+ print("add関数を呼び出しました")
212
212
  return a + b
213
213
 
214
214
 
@@ -225,7 +225,7 @@
225
225
  return a - b
226
226
 
227
227
  def add(a,b):
228
- print("main関数を呼び出しました")
228
+ print("add関数を呼び出しました")
229
229
  return a + b
230
230
 
231
231
  # 関数定義以外で一番最初に現れる行なので、ここから実行される。
@@ -234,6 +234,6 @@
234
234
 
235
235
  # ここより下は上の2行が実行された後評価され、実行される。
236
236
  if __name__ == '__main__':
237
- print('実行:__name__==__main__')
237
+ print('実行: IF __name__ = =__main__:')
238
238
 
239
239
  ```

6

修正

2020/11/19 03:54

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -123,7 +123,7 @@
123
123
  > ・convert_url(url)の引数urlはreturnされた「"https://drive.google.com/uc?export=view&id=%s" % a.group(1)」の値が記載されている認識でよろしいでしょうか。
124
124
 
125
125
  yesかnoかでいえばnoです。
126
- convert_url(url)の引数urlは、JSONに記載したgoogleドライブへのパス(url)が渡されます。
126
+ convert_url(url)の引数urlは、JSONに記載されている、googleドライブ上のファイルへのパス(img_url)が渡されます。
127
127
 
128
128
 
129
129
 

5

修正

2020/11/19 03:52

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -137,24 +137,26 @@
137
137
  > ・main()関数にはconvert_url(url)を呼び出す関数がないようですが、こちらの関数はどのように呼び出せばよろしいでしょうか。
138
138
 
139
139
  コメントを追加しました。
140
- 回答コード全文には最初から、upload_media関数内にconvert_url(url)を呼び出すコードを入れておりましたが、
140
+ 回答コード全文には最初から、upload_media関数内にconvert_url(url)を呼び出すコードを入れておりましたが、
141
141
  「# <----追加」というコメントを入れ忘れておりました。
142
142
 
143
+ main()からconvert_url(url)を呼ぶのではなく、
143
- upload_media関数内に、convert_url(url)を呼び出していますので、main()で呼ぶ必要はありません
144
+ upload_media関数の中からconvert_url(url)を呼び出しています。
144
145
 
145
146
 
146
147
 
148
+
147
149
  > ・main()関数に記載したjson_file_pathにjsonファイルのパスを直指定しているのですが、こちらはjsonファイル名を記載するのが正しいのでしょうか。
148
150
 
149
151
  回答コードは、自分のテスト環境用のjsonファイルパスを記載してしまっていたので、元質問のファイルパスに修正しました。
150
- 元質問のコードのように、jsonファイルのパスを直指定で問題ありません。
152
+ 元質問のコードのように、jsonファイルのパスを直指定するやり方で問題ありません。
151
153
 
152
154
 
153
155
  > ・Pythonの実行方法として、定義された関数をmainから実行していくという認識であっているのでしょうか。※初歩的な質問で申し訳ございません
154
156
 
155
157
  特にmainから実行していくという制約はありません。
156
158
 
157
- importを無視しての話になりますがpythonでは上から順番に読み取られ、実行できる部分があれば上から実行されます。
159
+ importを無視しての話になりますがpythonでは上から順番に読み取られ、実行できる部分があれば上から実行されます。
158
160
  ただし、関数定義部分(def)やクラス定義部分(class)等は、読み取られるだけで実行されません。
159
161
  (※importを読み取ったときの挙動等、細かい点まで考慮すると上記の説明は完全に正確というわけではありませんが、雰囲気としてそういうものだと考えてくだされば結構です)
160
162
 

4

追加

2020/11/19 03:50

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -110,11 +110,128 @@
110
110
 
111
111
 
112
112
  def main():
113
- json_file_path = 'contents.json'
113
+ json_file_path = '/content/sample_data/tweetcontent.json' # ファイルパスを修正しました。
114
114
  tweet_content = get_tweet_content(json_file_path)
115
115
  media_id = upload_media(tweet_content['img_url'])
116
116
  post_tweet(tweet_content['tweet_text'], media_id)
117
117
 
118
118
  if __name__ == '__main__':
119
119
  main()
120
+ ```
121
+
122
+
123
+ > ・convert_url(url)の引数urlはreturnされた「"https://drive.google.com/uc?export=view&id=%s" % a.group(1)」の値が記載されている認識でよろしいでしょうか。
124
+
125
+ yesかnoかでいえばnoです。
126
+ convert_url(url)の引数urlは、JSONに記載したgoogleドライブへのパス(url)が渡されます。
127
+
128
+
129
+
130
+ > 認識が間違っている場合、引数にはどの値(ファイルパス指定、JSONに記載したファイルパスの変数を指定など)を定義するべきでしょうか。
131
+
132
+ 引数には、JSONに記載したgoogleドライブへのパス(url)が渡されていればよいので、元質問のコードから変える必要はありません。
133
+
134
+
135
+
136
+
137
+ > ・main()関数にはconvert_url(url)を呼び出す関数がないようですが、こちらの関数はどのように呼び出せばよろしいでしょうか。
138
+
139
+ コメントを追加しました。
140
+ 回答コード全文には最初から、upload_media関数内に、convert_url(url)を呼び出すコードを入れておりましたが、
141
+ 「# <----追加」というコメントを入れ忘れておりました。
142
+
143
+ upload_media関数内に、convert_url(url)を呼び出していますので、main()で呼ぶ必要はありません。
144
+
145
+
146
+
147
+ > ・main()関数に記載したjson_file_pathにjsonファイルのパスを直指定しているのですが、こちらはjsonファイル名を記載するのが正しいのでしょうか。
148
+
149
+ 回答コードは、自分のテスト環境用のjsonファイルパスを記載してしまっていたので、元質問のファイルパスに修正しました。
150
+ 元質問のコードのように、jsonファイルのパスを直指定で問題ありません。
151
+
152
+
153
+ > ・Pythonの実行方法として、定義された関数をmainから実行していくという認識であっているのでしょうか。※初歩的な質問で申し訳ございません
154
+
155
+ 特にmainから実行していくという制約はありません。
156
+
157
+ importを無視しての話になりますが、pythonでは上から順番に読み取られ、実行できる部分があれば上から実行されます。
158
+ ただし、関数定義部分(def)やクラス定義部分(class)等は、読み取られるだけで実行されません。
159
+ (※importを読み取ったときの挙動等、細かい点まで考慮すると上記の説明は完全に正確というわけではありませんが、雰囲気としてそういうものだと考えてくだされば結構です)
160
+
161
+ 例:
162
+
163
+ [1]
164
+
165
+ ```
166
+ def sub(a,b):
167
+ print("sub関数を呼び出しました")
168
+ return a - b
169
+
170
+ def main(a,b):
171
+ print("main関数を呼び出しました")
172
+ return a + b
173
+
174
+ # 関数等定義以外で一番最初に現れる行なので、ここから実行される。
175
+ if __name__ == '__main__':
176
+ # main()が最初でなくてよい
177
+ print(sub(1,2))
178
+ print(main(1,2))
179
+
180
+ ```
181
+
182
+ [2]
183
+
184
+ ```
185
+ def sub(a,b):
186
+ print("sub関数を呼び出しました")
187
+ return a - b
188
+
189
+ def main(a,b):
190
+ print("main関数を呼び出しました")
191
+ return a + b
192
+
193
+ # if __name__ == '__main__':がなくても
194
+ # 関数定義以外で一番最初に現れる行なので、ここから実行される。
195
+ print(sub(1,2))
196
+ print(main(1,2))
197
+
198
+ ```
199
+
200
+ [3]
201
+
202
+ ```
203
+ def sub(a,b):
204
+ print("sub関数を呼び出しました")
205
+ return a - b
206
+
207
+ # mainという名前の関数は存在する必要はない
208
+ def add(a,b):
209
+ print("main関数を呼び出しました")
210
+ return a + b
211
+
212
+
213
+ if __name__ == '__main__':
214
+ print(sub(1,2))
215
+ print(add(1,2))
216
+ ```
217
+
218
+ [4]
219
+
220
+ ```
221
+ def sub(a,b):
222
+ print("sub関数を呼び出しました")
223
+ return a - b
224
+
225
+ def add(a,b):
226
+ print("main関数を呼び出しました")
227
+ return a + b
228
+
229
+ # 関数定義以外で一番最初に現れる行なので、ここから実行される。
230
+ print(sub(1,2))
231
+ print(add(1,2))
232
+
233
+ # ここより下は上の2行が実行された後評価され、実行される。
234
+ if __name__ == '__main__':
235
+ print('実行:__name__==__main__')
236
+
120
237
  ```

3

追加

2020/11/19 03:47

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -34,7 +34,7 @@
34
34
 
35
35
  ```
36
36
  import json
37
- import random
37
+ import random # <-------回答追加時当初から追加しています
38
38
  import re # <-------追加
39
39
  from requests_oauthlib import OAuth1Session
40
40
  #urlを使用するためのモジュール
@@ -84,8 +84,8 @@
84
84
  #画像をTwitterにアップロードし、media_idをリターン
85
85
  #img_urlはJSONで指定した画像オブジェクト
86
86
  def upload_media(img_url): #===========================
87
- # urlを変換する
87
+ # urlを変換する # <-------回答追加時当初から追加しています
88
- img_url = convert_url(img_url) # <-------追加
88
+ img_url = convert_url(img_url) # <-------回答追加時当初から追加しています
89
89
  #urlをオープンする
90
90
  res = urllib.request.urlopen(img_url) #=========================
91
91
  img_data = res.read()

2

コメントを追加

2020/11/19 03:08

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -85,7 +85,7 @@
85
85
  #img_urlはJSONで指定した画像オブジェクト
86
86
  def upload_media(img_url): #===========================
87
87
  # urlを変換する
88
- img_url = convert_url(img_url)
88
+ img_url = convert_url(img_url) # <-------追加
89
89
  #urlをオープンする
90
90
  res = urllib.request.urlopen(img_url) #=========================
91
91
  img_data = res.read()

1

追記

2020/11/19 03:06

投稿

sfdust
sfdust

スコア1137

answer CHANGED
@@ -1,3 +1,120 @@
1
1
  random モジュールがないというエラーメッセージなので、冒頭で
2
2
  import random
3
- とすればよいのではないでしょうか。
3
+ とすればよいのではないでしょうか。
4
+
5
+ ------------
6
+ 追記
7
+
8
+ まず、上記のコードで正常に動かないところを修正します。
9
+ 具体的には、
10
+ ```
11
+ def upload__media(img_url):
12
+ ```
13
+  を
14
+ ```
15
+ def upload_media(img_url):
16
+ ```
17
+ に変えます。(uploadとdataの間のアンダーバーを2つから1つに変える。)
18
+
19
+ その上で、/content/sample_data/tweetcontent.json の中の "img_url":の「対象ファイルのURL」を、
20
+ ネット上の自由に使用可能な素材へのリンクに変えてテストしたところ、
21
+ 自分の環境では正常に画像ツイートできました。
22
+
23
+ ためしに「対象ファイルのURL」を自分のGoogle Drive上の画像ファイルへのリンクに変えたところ、
24
+ 質問者さんと同じ
25
+ Image upload failed: %s {"request":"/1.1/media/upload.json","error":"media type unrecognized."}
26
+
27
+ というエラーが出ました。
28
+
29
+ したがって、Google Driveの「リンクの取得」で取得したリンクそのままでは、twitter APIからは画像データを正常に取得できないと推測されます。
30
+
31
+ そこで下のコードでは、[stackoverrun](https://stackoverflow.com/questions/10311092/displaying-files-e-g-images-stored-in-google-drive-on-a-website) の内容を参考に、urlを取得できる形に変換する関数(convert_url)を追加しています。
32
+
33
+ 全文
34
+
35
+ ```
36
+ import json
37
+ import random
38
+ import re # <-------追加
39
+ from requests_oauthlib import OAuth1Session
40
+ #urlを使用するためのモジュール
41
+ import urllib.request
42
+
43
+ # url変換に使用する正規表現
44
+ pattern = re.compile(r".*/file/./(.*)/.*") # <-------追加
45
+
46
+ #下記TwitterのAPIキー、アクセスキーのため記載しておりません
47
+ CONSUMER_KEY = '****************************'
48
+ CONSUMER_SECRET = '****************************'
49
+ ACCESS_TOKEN = '****************************'
50
+ ACCESS_TOKEN_SECRET = '****************************'
51
+
52
+ #Twitterアクセスキーを変数へ格納
53
+ twitter = OAuth1Session(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_TOKEN,ACCESS_TOKEN_SECRET)
54
+
55
+ #メディアアップロードに使用するURL
56
+ url_media = "https://upload.twitter.com/1.1/media/upload.json"
57
+
58
+ #テキストアップロードに使用するURL
59
+ url_text = "https://api.twitter.com/1.1/statuses/update.json"
60
+
61
+
62
+ # Googleドライブ上のリンクを、twitter API等で直接取得できるurlに変換する関数 <-------追加
63
+ def convert_url(url):
64
+ a = re.search(pattern, url)
65
+ try:
66
+ return "https://drive.google.com/uc?export=view&id=%s" % a.group(1)
67
+ except (AttributeError, IndexError) as e:
68
+ # パターンマッチしない場合はメッセージを出して、渡されたurlをそのまま返す。
69
+ print("[%s]はパターンにマッチしないため、そのまま返します。" % url)
70
+ return url
71
+
72
+
73
+ #jsonファイルからツイート本文と画像urlを取得
74
+ def get_tweet_content(json_file_path):
75
+ #テキストファイルを読み込む
76
+ file = open(json_file_path, 'r', encoding='utf-8')
77
+ #開いたファイルをjson.load関数でJSONとして読み込む
78
+ json_data = json.load(file)
79
+ #JSONとして読み込んだfile変数が格納されたjson_data変数に、jsonデータを格納
80
+ #random.choice()でリストからランダムに要素を一つ取得
81
+ return random.choice(json_data["contents"])
82
+
83
+
84
+ #画像をTwitterにアップロードし、media_idをリターン
85
+ #img_urlはJSONで指定した画像オブジェクト
86
+ def upload_media(img_url): #===========================
87
+ # urlを変換する
88
+ img_url = convert_url(img_url)
89
+ #urlをオープンする
90
+ res = urllib.request.urlopen(img_url) #=========================
91
+ img_data = res.read()
92
+ img_files = {'media': img_data}
93
+ res_media = twitter.post(url_media, files=img_files)
94
+
95
+ if res_media.status_code == 200:
96
+ return json.loads(res_media.text)['media_id']
97
+ else:
98
+ print('Image upload failed: %s', res_media.text)
99
+ exit()
100
+
101
+
102
+ #ツイート本文とアップロード済みの画像のmedia_idを引数にツイート
103
+ def post_tweet(tweet_text, media_id):
104
+ params = {'status': tweet_text, 'media_ids': media_id}
105
+ res = twitter.post(url_text, params=params)
106
+ if res.status_code == 200:
107
+ print('Auto Tweet Succeeded.')
108
+ else:
109
+ print('Failed. : %d' % res.status_code)
110
+
111
+
112
+ def main():
113
+ json_file_path = 'contents.json'
114
+ tweet_content = get_tweet_content(json_file_path)
115
+ media_id = upload_media(tweet_content['img_url'])
116
+ post_tweet(tweet_content['tweet_text'], media_id)
117
+
118
+ if __name__ == '__main__':
119
+ main()
120
+ ```