回答編集履歴
10
修正
test
CHANGED
@@ -248,7 +248,7 @@
|
|
248
248
|
|
249
249
|
yesかnoかでいえばnoです。
|
250
250
|
|
251
|
-
convert_url(url)の引数urlには、
|
251
|
+
convert_url(url)の引数urlには、tweetcontent.json内に記載されている、googleドライブ上のファイルへのパス(img_url)が渡されます。
|
252
252
|
|
253
253
|
|
254
254
|
|
@@ -260,11 +260,11 @@
|
|
260
260
|
|
261
261
|
|
262
262
|
|
263
|
-
convert_url(url)の引数urlには、
|
263
|
+
convert_url(url)の引数urlには、tweetcontent.jsonに記載されている、googleドライブ上のファイルへのパスを渡すべきです。
|
264
|
-
|
265
|
-
|
266
|
-
|
264
|
+
|
265
|
+
|
266
|
+
|
267
|
-
|
267
|
+
回答のコードは「tweetcontent.jsonに記載されたgoogleドライブ上のファイルへのパス」をconvert_url関数に渡すようにしています。
|
268
268
|
|
269
269
|
|
270
270
|
|
9
修正
test
CHANGED
@@ -260,11 +260,11 @@
|
|
260
260
|
|
261
261
|
|
262
262
|
|
263
|
-
convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパス
|
263
|
+
convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパスを渡すべきです。
|
264
|
-
|
265
|
-
|
266
|
-
|
264
|
+
|
265
|
+
|
266
|
+
|
267
|
-
なお、回答のコードは
|
267
|
+
なお、回答のコードは「JSONに記載されたgoogleドライブへのパス」をconvert_url関数に渡すようにしています。
|
268
268
|
|
269
269
|
|
270
270
|
|
8
修正
test
CHANGED
@@ -260,9 +260,11 @@
|
|
260
260
|
|
261
261
|
|
262
262
|
|
263
|
-
引数には、JSONに記載
|
263
|
+
convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパス「JSONに記載したファイルパス」を渡すべきです。
|
264
|
+
|
265
|
+
|
266
|
+
|
264
|
-
|
267
|
+
なお、回答のコードは、元質問のコードをなるべく変えないように「JSONに記載されたgoogleドライブへのパス」をconvert_url関数に渡すようにしています。
|
265
|
-
|
266
268
|
|
267
269
|
|
268
270
|
|
7
修正
test
CHANGED
@@ -418,7 +418,7 @@
|
|
418
418
|
|
419
419
|
def add(a,b):
|
420
420
|
|
421
|
-
print("
|
421
|
+
print("add関数を呼び出しました")
|
422
422
|
|
423
423
|
return a + b
|
424
424
|
|
@@ -452,7 +452,7 @@
|
|
452
452
|
|
453
453
|
def add(a,b):
|
454
454
|
|
455
|
-
print("
|
455
|
+
print("add関数を呼び出しました")
|
456
456
|
|
457
457
|
return a + b
|
458
458
|
|
@@ -470,8 +470,8 @@
|
|
470
470
|
|
471
471
|
if __name__ == '__main__':
|
472
472
|
|
473
|
-
print('実行:__name__==__main__')
|
473
|
+
print('実行: IF __name__ = =__main__:')
|
474
|
-
|
475
|
-
|
476
|
-
|
474
|
+
|
475
|
+
|
476
|
+
|
477
|
-
```
|
477
|
+
```
|
6
修正
test
CHANGED
@@ -248,7 +248,7 @@
|
|
248
248
|
|
249
249
|
yesかnoかでいえばnoです。
|
250
250
|
|
251
|
-
convert_url(url)の引数urlは、JSONに記載
|
251
|
+
convert_url(url)の引数urlには、JSONに記載されている、googleドライブ上のファイルへのパス(img_url)が渡されます。
|
252
252
|
|
253
253
|
|
254
254
|
|
5
修正
test
CHANGED
@@ -276,13 +276,17 @@
|
|
276
276
|
|
277
277
|
コメントを追加しました。
|
278
278
|
|
279
|
-
回答コード全文には最初から、upload_media関数内に
|
279
|
+
回答コード全文には最初から、upload_media関数内にconvert_url(url)を呼び出すコードを入れておりましたが、
|
280
280
|
|
281
281
|
「# <----追加」というコメントを入れ忘れておりました。
|
282
282
|
|
283
283
|
|
284
284
|
|
285
|
+
main()からconvert_url(url)を呼ぶのではなく、
|
286
|
+
|
285
|
-
upload_media関数
|
287
|
+
upload_media関数の中からconvert_url(url)を呼び出しています。
|
288
|
+
|
289
|
+
|
286
290
|
|
287
291
|
|
288
292
|
|
@@ -296,7 +300,7 @@
|
|
296
300
|
|
297
301
|
回答コードは、自分のテスト環境用のjsonファイルパスを記載してしまっていたので、元質問のファイルパスに修正しました。
|
298
302
|
|
299
|
-
元質問のコードのように、jsonファイルのパスを直指定で問題ありません。
|
303
|
+
元質問のコードのように、jsonファイルのパスを直指定するやり方で問題ありません。
|
300
304
|
|
301
305
|
|
302
306
|
|
@@ -310,7 +314,7 @@
|
|
310
314
|
|
311
315
|
|
312
316
|
|
313
|
-
importを無視しての話になりますが
|
317
|
+
(importを無視しての話になりますが)pythonでは上から順番に読み取られ、実行できる部分があれば上から実行されます。
|
314
318
|
|
315
319
|
ただし、関数定義部分(def)やクラス定義部分(class)等は、読み取られるだけで実行されません。
|
316
320
|
|
4
追加
test
CHANGED
@@ -222,7 +222,7 @@
|
|
222
222
|
|
223
223
|
def main():
|
224
224
|
|
225
|
-
json_file_path = 'contents.json'
|
225
|
+
json_file_path = '/content/sample_data/tweetcontent.json' # ファイルパスを修正しました。
|
226
226
|
|
227
227
|
tweet_content = get_tweet_content(json_file_path)
|
228
228
|
|
@@ -237,3 +237,237 @@
|
|
237
237
|
main()
|
238
238
|
|
239
239
|
```
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
> ・convert_url(url)の引数urlはreturnされた「"https://drive.google.com/uc?export=view&id=%s" % a.group(1)」の値が記載されている認識でよろしいでしょうか。
|
246
|
+
|
247
|
+
|
248
|
+
|
249
|
+
yesかnoかでいえばnoです。
|
250
|
+
|
251
|
+
convert_url(url)の引数urlは、JSONに記載したgoogleドライブへのパス(url)が渡されます。
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
> 認識が間違っている場合、引数にはどの値(ファイルパス指定、JSONに記載したファイルパスの変数を指定など)を定義するべきでしょうか。
|
260
|
+
|
261
|
+
|
262
|
+
|
263
|
+
引数には、JSONに記載したgoogleドライブへのパス(url)が渡されていればよいので、元質問のコードから変える必要はありません。
|
264
|
+
|
265
|
+
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
|
271
|
+
|
272
|
+
|
273
|
+
> ・main()関数にはconvert_url(url)を呼び出す関数がないようですが、こちらの関数はどのように呼び出せばよろしいでしょうか。
|
274
|
+
|
275
|
+
|
276
|
+
|
277
|
+
コメントを追加しました。
|
278
|
+
|
279
|
+
回答コード全文には最初から、upload_media関数内に、convert_url(url)を呼び出すコードを入れておりましたが、
|
280
|
+
|
281
|
+
「# <----追加」というコメントを入れ忘れておりました。
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
upload_media関数内に、convert_url(url)を呼び出していますので、main()で呼ぶ必要はありません。
|
286
|
+
|
287
|
+
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
> ・main()関数に記載したjson_file_pathにjsonファイルのパスを直指定しているのですが、こちらはjsonファイル名を記載するのが正しいのでしょうか。
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
回答コードは、自分のテスト環境用のjsonファイルパスを記載してしまっていたので、元質問のファイルパスに修正しました。
|
298
|
+
|
299
|
+
元質問のコードのように、jsonファイルのパスを直指定で問題ありません。
|
300
|
+
|
301
|
+
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
> ・Pythonの実行方法として、定義された関数をmainから実行していくという認識であっているのでしょうか。※初歩的な質問で申し訳ございません
|
306
|
+
|
307
|
+
|
308
|
+
|
309
|
+
特にmainから実行していくという制約はありません。
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
importを無視しての話になりますが、pythonでは上から順番に読み取られ、実行できる部分があれば上から実行されます。
|
314
|
+
|
315
|
+
ただし、関数定義部分(def)やクラス定義部分(class)等は、読み取られるだけで実行されません。
|
316
|
+
|
317
|
+
(※importを読み取ったときの挙動等、細かい点まで考慮すると上記の説明は完全に正確というわけではありませんが、雰囲気としてそういうものだと考えてくだされば結構です)
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
例:
|
322
|
+
|
323
|
+
|
324
|
+
|
325
|
+
[1]
|
326
|
+
|
327
|
+
|
328
|
+
|
329
|
+
```
|
330
|
+
|
331
|
+
def sub(a,b):
|
332
|
+
|
333
|
+
print("sub関数を呼び出しました")
|
334
|
+
|
335
|
+
return a - b
|
336
|
+
|
337
|
+
|
338
|
+
|
339
|
+
def main(a,b):
|
340
|
+
|
341
|
+
print("main関数を呼び出しました")
|
342
|
+
|
343
|
+
return a + b
|
344
|
+
|
345
|
+
|
346
|
+
|
347
|
+
# 関数等定義以外で一番最初に現れる行なので、ここから実行される。
|
348
|
+
|
349
|
+
if __name__ == '__main__':
|
350
|
+
|
351
|
+
# main()が最初でなくてよい
|
352
|
+
|
353
|
+
print(sub(1,2))
|
354
|
+
|
355
|
+
print(main(1,2))
|
356
|
+
|
357
|
+
|
358
|
+
|
359
|
+
```
|
360
|
+
|
361
|
+
|
362
|
+
|
363
|
+
[2]
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
```
|
368
|
+
|
369
|
+
def sub(a,b):
|
370
|
+
|
371
|
+
print("sub関数を呼び出しました")
|
372
|
+
|
373
|
+
return a - b
|
374
|
+
|
375
|
+
|
376
|
+
|
377
|
+
def main(a,b):
|
378
|
+
|
379
|
+
print("main関数を呼び出しました")
|
380
|
+
|
381
|
+
return a + b
|
382
|
+
|
383
|
+
|
384
|
+
|
385
|
+
# if __name__ == '__main__':がなくても
|
386
|
+
|
387
|
+
# 関数定義以外で一番最初に現れる行なので、ここから実行される。
|
388
|
+
|
389
|
+
print(sub(1,2))
|
390
|
+
|
391
|
+
print(main(1,2))
|
392
|
+
|
393
|
+
|
394
|
+
|
395
|
+
```
|
396
|
+
|
397
|
+
|
398
|
+
|
399
|
+
[3]
|
400
|
+
|
401
|
+
|
402
|
+
|
403
|
+
```
|
404
|
+
|
405
|
+
def sub(a,b):
|
406
|
+
|
407
|
+
print("sub関数を呼び出しました")
|
408
|
+
|
409
|
+
return a - b
|
410
|
+
|
411
|
+
|
412
|
+
|
413
|
+
# mainという名前の関数は存在する必要はない
|
414
|
+
|
415
|
+
def add(a,b):
|
416
|
+
|
417
|
+
print("main関数を呼び出しました")
|
418
|
+
|
419
|
+
return a + b
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
|
424
|
+
|
425
|
+
if __name__ == '__main__':
|
426
|
+
|
427
|
+
print(sub(1,2))
|
428
|
+
|
429
|
+
print(add(1,2))
|
430
|
+
|
431
|
+
```
|
432
|
+
|
433
|
+
|
434
|
+
|
435
|
+
[4]
|
436
|
+
|
437
|
+
|
438
|
+
|
439
|
+
```
|
440
|
+
|
441
|
+
def sub(a,b):
|
442
|
+
|
443
|
+
print("sub関数を呼び出しました")
|
444
|
+
|
445
|
+
return a - b
|
446
|
+
|
447
|
+
|
448
|
+
|
449
|
+
def add(a,b):
|
450
|
+
|
451
|
+
print("main関数を呼び出しました")
|
452
|
+
|
453
|
+
return a + b
|
454
|
+
|
455
|
+
|
456
|
+
|
457
|
+
# 関数定義以外で一番最初に現れる行なので、ここから実行される。
|
458
|
+
|
459
|
+
print(sub(1,2))
|
460
|
+
|
461
|
+
print(add(1,2))
|
462
|
+
|
463
|
+
|
464
|
+
|
465
|
+
# ここより下は上の2行が実行された後評価され、実行される。
|
466
|
+
|
467
|
+
if __name__ == '__main__':
|
468
|
+
|
469
|
+
print('実行:__name__==__main__')
|
470
|
+
|
471
|
+
|
472
|
+
|
473
|
+
```
|
3
追加
test
CHANGED
@@ -70,7 +70,7 @@
|
|
70
70
|
|
71
71
|
import json
|
72
72
|
|
73
|
-
import random
|
73
|
+
import random # <-------回答追加時当初から追加しています
|
74
74
|
|
75
75
|
import re # <-------追加
|
76
76
|
|
@@ -170,9 +170,9 @@
|
|
170
170
|
|
171
171
|
def upload_media(img_url): #===========================
|
172
172
|
|
173
|
-
# urlを変換する
|
173
|
+
# urlを変換する # <-------回答追加時当初から追加しています
|
174
|
-
|
174
|
+
|
175
|
-
img_url = convert_url(img_url)
|
175
|
+
img_url = convert_url(img_url) # <-------回答追加時当初から追加しています
|
176
176
|
|
177
177
|
#urlをオープンする
|
178
178
|
|
2
コメントを追加
test
CHANGED
@@ -172,7 +172,7 @@
|
|
172
172
|
|
173
173
|
# urlを変換する
|
174
174
|
|
175
|
-
img_url = convert_url(img_url)
|
175
|
+
img_url = convert_url(img_url) # <-------追加
|
176
176
|
|
177
177
|
#urlをオープンする
|
178
178
|
|
1
追記
test
CHANGED
@@ -3,3 +3,237 @@
|
|
3
3
|
import random
|
4
4
|
|
5
5
|
とすればよいのではないでしょうか。
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
------------
|
10
|
+
|
11
|
+
追記
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
まず、上記のコードで正常に動かないところを修正します。
|
16
|
+
|
17
|
+
具体的には、
|
18
|
+
|
19
|
+
```
|
20
|
+
|
21
|
+
def upload__media(img_url):
|
22
|
+
|
23
|
+
```
|
24
|
+
|
25
|
+
を
|
26
|
+
|
27
|
+
```
|
28
|
+
|
29
|
+
def upload_media(img_url):
|
30
|
+
|
31
|
+
```
|
32
|
+
|
33
|
+
に変えます。(uploadとdataの間のアンダーバーを2つから1つに変える。)
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
その上で、/content/sample_data/tweetcontent.json の中の "img_url":の「対象ファイルのURL」を、
|
38
|
+
|
39
|
+
ネット上の自由に使用可能な素材へのリンクに変えてテストしたところ、
|
40
|
+
|
41
|
+
自分の環境では正常に画像ツイートできました。
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
ためしに「対象ファイルのURL」を自分のGoogle Drive上の画像ファイルへのリンクに変えたところ、
|
46
|
+
|
47
|
+
質問者さんと同じ
|
48
|
+
|
49
|
+
Image upload failed: %s {"request":"/1.1/media/upload.json","error":"media type unrecognized."}
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
というエラーが出ました。
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
したがって、Google Driveの「リンクの取得」で取得したリンクそのままでは、twitter APIからは画像データを正常に取得できないと推測されます。
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
そこで下のコードでは、[stackoverrun](https://stackoverflow.com/questions/10311092/displaying-files-e-g-images-stored-in-google-drive-on-a-website) の内容を参考に、urlを取得できる形に変換する関数(convert_url)を追加しています。
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
全文
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
```
|
70
|
+
|
71
|
+
import json
|
72
|
+
|
73
|
+
import random
|
74
|
+
|
75
|
+
import re # <-------追加
|
76
|
+
|
77
|
+
from requests_oauthlib import OAuth1Session
|
78
|
+
|
79
|
+
#urlを使用するためのモジュール
|
80
|
+
|
81
|
+
import urllib.request
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
# url変換に使用する正規表現
|
86
|
+
|
87
|
+
pattern = re.compile(r".*/file/./(.*)/.*") # <-------追加
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
#下記TwitterのAPIキー、アクセスキーのため記載しておりません
|
92
|
+
|
93
|
+
CONSUMER_KEY = '****************************'
|
94
|
+
|
95
|
+
CONSUMER_SECRET = '****************************'
|
96
|
+
|
97
|
+
ACCESS_TOKEN = '****************************'
|
98
|
+
|
99
|
+
ACCESS_TOKEN_SECRET = '****************************'
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
#Twitterアクセスキーを変数へ格納
|
104
|
+
|
105
|
+
twitter = OAuth1Session(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_TOKEN,ACCESS_TOKEN_SECRET)
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
#メディアアップロードに使用するURL
|
110
|
+
|
111
|
+
url_media = "https://upload.twitter.com/1.1/media/upload.json"
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
#テキストアップロードに使用するURL
|
116
|
+
|
117
|
+
url_text = "https://api.twitter.com/1.1/statuses/update.json"
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
# Googleドライブ上のリンクを、twitter API等で直接取得できるurlに変換する関数 <-------追加
|
124
|
+
|
125
|
+
def convert_url(url):
|
126
|
+
|
127
|
+
a = re.search(pattern, url)
|
128
|
+
|
129
|
+
try:
|
130
|
+
|
131
|
+
return "https://drive.google.com/uc?export=view&id=%s" % a.group(1)
|
132
|
+
|
133
|
+
except (AttributeError, IndexError) as e:
|
134
|
+
|
135
|
+
# パターンマッチしない場合はメッセージを出して、渡されたurlをそのまま返す。
|
136
|
+
|
137
|
+
print("[%s]はパターンにマッチしないため、そのまま返します。" % url)
|
138
|
+
|
139
|
+
return url
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
#jsonファイルからツイート本文と画像urlを取得
|
146
|
+
|
147
|
+
def get_tweet_content(json_file_path):
|
148
|
+
|
149
|
+
#テキストファイルを読み込む
|
150
|
+
|
151
|
+
file = open(json_file_path, 'r', encoding='utf-8')
|
152
|
+
|
153
|
+
#開いたファイルをjson.load関数でJSONとして読み込む
|
154
|
+
|
155
|
+
json_data = json.load(file)
|
156
|
+
|
157
|
+
#JSONとして読み込んだfile変数が格納されたjson_data変数に、jsonデータを格納
|
158
|
+
|
159
|
+
#random.choice()でリストからランダムに要素を一つ取得
|
160
|
+
|
161
|
+
return random.choice(json_data["contents"])
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
#画像をTwitterにアップロードし、media_idをリターン
|
168
|
+
|
169
|
+
#img_urlはJSONで指定した画像オブジェクト
|
170
|
+
|
171
|
+
def upload_media(img_url): #===========================
|
172
|
+
|
173
|
+
# urlを変換する
|
174
|
+
|
175
|
+
img_url = convert_url(img_url)
|
176
|
+
|
177
|
+
#urlをオープンする
|
178
|
+
|
179
|
+
res = urllib.request.urlopen(img_url) #=========================
|
180
|
+
|
181
|
+
img_data = res.read()
|
182
|
+
|
183
|
+
img_files = {'media': img_data}
|
184
|
+
|
185
|
+
res_media = twitter.post(url_media, files=img_files)
|
186
|
+
|
187
|
+
|
188
|
+
|
189
|
+
if res_media.status_code == 200:
|
190
|
+
|
191
|
+
return json.loads(res_media.text)['media_id']
|
192
|
+
|
193
|
+
else:
|
194
|
+
|
195
|
+
print('Image upload failed: %s', res_media.text)
|
196
|
+
|
197
|
+
exit()
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
#ツイート本文とアップロード済みの画像のmedia_idを引数にツイート
|
204
|
+
|
205
|
+
def post_tweet(tweet_text, media_id):
|
206
|
+
|
207
|
+
params = {'status': tweet_text, 'media_ids': media_id}
|
208
|
+
|
209
|
+
res = twitter.post(url_text, params=params)
|
210
|
+
|
211
|
+
if res.status_code == 200:
|
212
|
+
|
213
|
+
print('Auto Tweet Succeeded.')
|
214
|
+
|
215
|
+
else:
|
216
|
+
|
217
|
+
print('Failed. : %d' % res.status_code)
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
def main():
|
224
|
+
|
225
|
+
json_file_path = 'contents.json'
|
226
|
+
|
227
|
+
tweet_content = get_tweet_content(json_file_path)
|
228
|
+
|
229
|
+
media_id = upload_media(tweet_content['img_url'])
|
230
|
+
|
231
|
+
post_tweet(tweet_content['tweet_text'], media_id)
|
232
|
+
|
233
|
+
|
234
|
+
|
235
|
+
if __name__ == '__main__':
|
236
|
+
|
237
|
+
main()
|
238
|
+
|
239
|
+
```
|