質問編集履歴

2

削除された内容の復元を行いました

2020/09/10 00:40

投稿

mongaa
mongaa

スコア2

test CHANGED
@@ -1 +1 @@
1
- 終了した質問です。。。。。
1
+ YouTube Liveのアーカイブからチャットを取得するコードを模写したが上手くいかない @Python
test CHANGED
@@ -1,3 +1,259 @@
1
- 回答ただきありがうございました。
2
-
3
- 解決してから時間が経ったため質問の文章変更いたました。
1
+ ### 前提・実現した
2
+
3
+ PythonでYoutube Liveのアーカイブからチャット取得したいです
4
+
5
+ こちらのサイトのコードをほぼそのまま使用しています。
6
+
7
+ https://github.com/geerlingguy/youtube_chat_crawler/blob/master/YoutubeChatReplayCrawler.py
8
+
9
+ コードは下記について変更しています。
10
+
11
+ →youtubeの動画IDを引数としてvideo_idに入れているのを、初めからtarget_urlに打ち込んでいます。したがって、引数の長さを判別する箇所もコメントアウトしています。
12
+
13
+ ### 発生している問題・エラーメッセージ
14
+
15
+ pyファイルを実行し作成されるテキストファイル(comment_data.txt)を開いても中身が空っぽです。
16
+
17
+ cmd,Visual Studio Code共にエラーメッセージは発生していません。
18
+
19
+ 指定した動画からコメントを取得する流れのどこかで想定通りに動いていないと思われますが、
20
+
21
+ 解決策が分からなくて困っています。
22
+
23
+ ### 該当のソースコード
24
+
25
+ ```Python
26
+
27
+ #!/usr/bin/env python3
28
+
29
+ from bs4 import BeautifulSoup
30
+
31
+ import ast
32
+
33
+ import requests
34
+
35
+ import re
36
+
37
+ import sys
38
+
39
+ # Verify user supplied a YouTube URL.
40
+
41
+ #if len(sys.argv) == 1:
42
+
43
+ # print("Please provide a YouTube URL (e.g. ./YoutubeChatReplayCrawler.py YOUTUBE_VIDEO_URL)")
44
+
45
+ # sys.exit(0)
46
+
47
+ # Produce a valid filename (from Django text utils).
48
+
49
+ def get_valid_filename(s):
50
+
51
+ s = str(s).strip().replace(' ', '_')
52
+
53
+ return re.sub(r'(?u)[^-\w.]', '', s)
54
+
55
+ # Set up variables for requests.
56
+
57
+ #target_url = sys.argv[1]
58
+
59
+ target_url = "https://www.youtube.com/watch?v=mOBvvwCosE4" #←適当に選んだ動画のURL
60
+
61
+ dict_str = ''
62
+
63
+ next_url = ''
64
+
65
+ comment_data = []
66
+
67
+ session = requests.Session()
68
+
69
+ headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
70
+
71
+ # Get the video page.
72
+
73
+ html = session.get(target_url)
74
+
75
+ soup = BeautifulSoup(html.text, 'html.parser')
76
+
77
+ # Retrieve the title and sanitize so it is a valid filename.
78
+
79
+ title = soup.find_all('title')
80
+
81
+ title = title[0].text.replace(' - YouTube', '')
82
+
83
+ title = get_valid_filename(title)
84
+
85
+ # Regex match for emoji.
86
+
87
+ RE_EMOJI = re.compile('[\U00010000-\U0010ffff]', flags=re.UNICODE)
88
+
89
+ # Find any live_chat_replay elements, get URL for next live chat message.
90
+
91
+ for iframe in soup.find_all("iframe"):
92
+
93
+ if("live_chat_replay" in iframe["src"]):
94
+
95
+ next_url = iframe["src"]
96
+
97
+ if not next_url:
98
+
99
+ print("Couldn't find live_chat_replay iframe. Maybe try running again?")
100
+
101
+ sys.exit(0)
102
+
103
+ # TODO - We should fail fast if next_url is empty, otherwise you get error:
104
+
105
+ # Invalid URL '': No schema supplied. Perhaps you meant http://?
106
+
107
+ # TODO - This loop is fragile. It loops endlessly when some exceptions are hit.
108
+
109
+ while(1):
110
+
111
+ try:
112
+
113
+ html = session.get(next_url, headers=headers)
114
+
115
+ soup = BeautifulSoup(html.text, 'lxml')
116
+
117
+ # Loop through all script tags.
118
+
119
+ for script in soup.find_all('script'):
120
+
121
+ script_text = str(script)
122
+
123
+ if 'ytInitialData' in script_text:
124
+
125
+ dict_str = ''.join(script_text.split(" = ")[1:])
126
+
127
+ # Capitalize booleans so JSON is valid Python dict.
128
+
129
+ dict_str = dict_str.replace("false", "False")
130
+
131
+ dict_str = dict_str.replace("true", "True")
132
+
133
+ # Strip extra HTML from JSON.
134
+
135
+ dict_str = re.sub(r'};.*\n.+</script>', '}', dict_str)
136
+
137
+ # Correct some characters.
138
+
139
+ dict_str = dict_str.rstrip(" \n;")
140
+
141
+ # TODO: I don't seem to have any issues with emoji in the messages.
142
+
143
+ # dict_str = RE_EMOJI.sub(r'', dict_str)
144
+
145
+ # Evaluate the cleaned up JSON into a python dict.
146
+
147
+ dics = ast.literal_eval(dict_str)
148
+
149
+ # TODO: On the last pass this returns KeyError since there are no more
150
+
151
+ # continuations or actions. Should probably just break in that case.
152
+
153
+ continue_url = dics["continuationContents"]["liveChatContinuation"]["continuations"][0]["liveChatReplayContinuationData"]["continuation"]
154
+
155
+ print('Found another live chat continuation:')
156
+
157
+ print(continue_url)
158
+
159
+ next_url = "https://www.youtube.com/live_chat_replay?continuation=" + continue_url
160
+
161
+ # Extract the data for each live chat comment.
162
+
163
+ for samp in dics["continuationContents"]["liveChatContinuation"]["actions"][1:]:
164
+
165
+ comment_data.append(str(samp) + "\n")
166
+
167
+ # next_urlが入手できなくなったら終わり
168
+
169
+ except requests.ConnectionError:
170
+
171
+ print("Connection Error")
172
+
173
+ continue
174
+
175
+ except requests.HTTPError:
176
+
177
+ print("HTTPError")
178
+
179
+ break
180
+
181
+ except requests.Timeout:
182
+
183
+ print("Timeout")
184
+
185
+ continue
186
+
187
+ except requests.exceptions.RequestException as e:
188
+
189
+ print(e)
190
+
191
+ break
192
+
193
+ except KeyError as e:
194
+
195
+ error = str(e)
196
+
197
+ if 'liveChatReplayContinuationData' in error:
198
+
199
+ print('Hit last live chat segment, finishing job.')
200
+
201
+ else:
202
+
203
+ print("KeyError")
204
+
205
+ print(e)
206
+
207
+ break
208
+
209
+ except SyntaxError as e:
210
+
211
+ print("SyntaxError")
212
+
213
+ print(e)
214
+
215
+ break
216
+
217
+ # continue #TODO
218
+
219
+ except KeyboardInterrupt:
220
+
221
+ break
222
+
223
+ except Exception:
224
+
225
+ print("Unexpected error:" + str(sys.exc_info()[0]))
226
+
227
+ # Write the comment data to a file named after the title of the video.
228
+
229
+ with open(title + ".json", mode='w', encoding="utf-8") as f:
230
+
231
+ f.writelines(comment_data)
232
+
233
+ print('Comment data saved to ' + title + '.json')
234
+
235
+ ```
236
+
237
+ ### 試したこと
238
+
239
+ ・実行時、すぐ"Couldn't find live_chat_replay iframe. Maybe try running again?"と表示されるので、while(1):のループに入る前を見ていけば良いと考えました。
240
+
241
+ ・そこで、デバッグによって各変数の状態を確認したところ、next_url=""のままでした。よって、>>if("live_chat_replay" in iframe["src"]):は一度もTrueにならなかったと考えています。(Trueなら何かしら代入されているため)
242
+
243
+ ・上記条件式で使用されるiframeの中にはいろんなタグが入っていました。"src"に関係ありそうな箇所(自信ないです)を載せておきます。
244
+
245
+ <iframe src="https://accounts.google.com/ServiceLogin?uilel=3&amp;hl=ja&amp;service=youtube&amp;passive=true&amp;continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Ffeature%3Dpassive%26next%3D%252Fsignin_passive%26hl%3Dja%26action_handle_signin%3Dtrue%26app%3Ddesktop" style="display: none"></iframe>
246
+
247
+ iframeを見ても何を確認してどうすれば良いかわからなくなり手詰まりの状態になっています。。
248
+
249
+ ### 補足情報(FW/ツールのバージョンなど)
250
+
251
+ python 3.6.5
252
+
253
+ beautifulsoup4 4.9.1
254
+
255
+ 使用PC:
256
+
257
+ Surface Pro 5
258
+
259
+ Windows 10

1

修正

2020/09/10 00:40

投稿

退会済みユーザー
test CHANGED
@@ -1 +1 @@
1
- YouTube Liveのアーカイブからチャットを取得するコードを模写したが上手くいかない @Python
1
+ 終了した質問です。。。。。
test CHANGED
@@ -1,329 +1,3 @@
1
- ### 前提・実現したいこと
1
+ 回答いただきありがとうございました
2
2
 
3
- PythonでYoutube Liveのアーカイブからチャット取得したいです
4
-
5
- こちらのサイトのコードをほぼそのまま使用しています。
6
-
7
- https://github.com/geerlingguy/youtube_chat_crawler/blob/master/YoutubeChatReplayCrawler.py
8
-
9
-
10
-
11
- コードは下記について変更しています。
12
-
13
- →youtubeの動画IDを引数としてvideo_idに入れているのを、初めからtarget_urlに打ち込んでいます。したがって、引数の長さを判別する箇所もコメントアウトしています。
14
-
15
-
16
-
17
- ### 発生している問題・エラーメッセージ
18
-
19
- pyファイルを実行し作成されるテキストファイル(comment_data.txt)を開いても中身が空っぽです。
20
-
21
- cmd,Visual Studio Code共にエラーメッセージは発生していません。
22
-
23
-
24
-
25
- 指定した動画からコメントを取得する流れのどこかで想定通りに動いていないと思われますが、
26
-
27
- 解決策が分からなくて困っています。
28
-
29
-
30
-
31
- ### 該当のソースコード
32
-
33
-
34
-
35
- ```Python
36
-
37
- #!/usr/bin/env python3
38
-
39
-
40
-
41
- from bs4 import BeautifulSoup
42
-
43
- import ast
44
-
45
- import requests
46
-
47
- import re
48
-
49
- import sys
50
-
51
-
52
-
53
- # Verify user supplied a YouTube URL.
54
-
55
- #if len(sys.argv) == 1:
56
-
57
- # print("Please provide a YouTube URL (e.g. ./YoutubeChatReplayCrawler.py YOUTUBE_VIDEO_URL)")
58
-
59
- # sys.exit(0)
60
-
61
-
62
-
63
- # Produce a valid filename (from Django text utils).
64
-
65
- def get_valid_filename(s):
66
-
67
- s = str(s).strip().replace(' ', '_')
68
-
69
- return re.sub(r'(?u)[^-\w.]', '', s)
70
-
71
-
72
-
73
-
74
-
75
- # Set up variables for requests.
76
-
77
- #target_url = sys.argv[1]
78
-
79
- target_url = "https://www.youtube.com/watch?v=mOBvvwCosE4" #←適当に選んだ動画のURL
80
-
81
-
82
-
83
- dict_str = ''
84
-
85
- next_url = ''
86
-
87
- comment_data = []
88
-
89
- session = requests.Session()
90
-
91
- headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
92
-
93
-
94
-
95
- # Get the video page.
96
-
97
- html = session.get(target_url)
98
-
99
- soup = BeautifulSoup(html.text, 'html.parser')
100
-
101
-
102
-
103
- # Retrieve the title and sanitize so it is a valid filename.
104
-
105
- title = soup.find_all('title')
106
-
107
- title = title[0].text.replace(' - YouTube', '')
108
-
109
- title = get_valid_filename(title)
110
-
111
-
112
-
113
- # Regex match for emoji.
114
-
115
- RE_EMOJI = re.compile('[\U00010000-\U0010ffff]', flags=re.UNICODE)
116
-
117
-
118
-
119
- # Find any live_chat_replay elements, get URL for next live chat message.
120
-
121
- for iframe in soup.find_all("iframe"):
122
-
123
- if("live_chat_replay" in iframe["src"]):
124
-
125
- next_url = iframe["src"]
126
-
127
-
128
-
129
- if not next_url:
130
-
131
- print("Couldn't find live_chat_replay iframe. Maybe try running again?")
132
-
133
- sys.exit(0)
134
-
135
-
136
-
137
- # TODO - We should fail fast if next_url is empty, otherwise you get error:
138
-
139
- # Invalid URL '': No schema supplied. Perhaps you meant http://?
140
-
141
-
142
-
143
- # TODO - This loop is fragile. It loops endlessly when some exceptions are hit.
144
-
145
- while(1):
146
-
147
-
148
-
149
- try:
150
-
151
- html = session.get(next_url, headers=headers)
152
-
153
- soup = BeautifulSoup(html.text, 'lxml')
154
-
155
-
156
-
157
- # Loop through all script tags.
158
-
159
- for script in soup.find_all('script'):
160
-
161
- script_text = str(script)
162
-
163
- if 'ytInitialData' in script_text:
164
-
165
- dict_str = ''.join(script_text.split(" = ")[1:])
166
-
167
-
168
-
169
- # Capitalize booleans so JSON is valid Python dict.
170
-
171
- dict_str = dict_str.replace("false", "False")
172
-
173
- dict_str = dict_str.replace("true", "True")
174
-
175
-
176
-
177
- # Strip extra HTML from JSON.
178
-
179
- dict_str = re.sub(r'};.*\n.+</script>', '}', dict_str)
180
-
181
-
182
-
183
- # Correct some characters.
184
-
185
- dict_str = dict_str.rstrip(" \n;")
186
-
187
-
188
-
189
- # TODO: I don't seem to have any issues with emoji in the messages.
190
-
191
- # dict_str = RE_EMOJI.sub(r'', dict_str)
192
-
193
-
194
-
195
- # Evaluate the cleaned up JSON into a python dict.
196
-
197
- dics = ast.literal_eval(dict_str)
198
-
199
-
200
-
201
- # TODO: On the last pass this returns KeyError since there are no more
202
-
203
- # continuations or actions. Should probably just break in that case.
204
-
205
- continue_url = dics["continuationContents"]["liveChatContinuation"]["continuations"][0]["liveChatReplayContinuationData"]["continuation"]
206
-
207
- print('Found another live chat continuation:')
208
-
209
- print(continue_url)
210
-
211
- next_url = "https://www.youtube.com/live_chat_replay?continuation=" + continue_url
212
-
213
-
214
-
215
- # Extract the data for each live chat comment.
216
-
217
- for samp in dics["continuationContents"]["liveChatContinuation"]["actions"][1:]:
218
-
219
- comment_data.append(str(samp) + "\n")
220
-
221
-
222
-
223
- # next_urlが入手できなくなったら終わり
224
-
225
- except requests.ConnectionError:
226
-
227
- print("Connection Error")
228
-
229
- continue
230
-
231
- except requests.HTTPError:
232
-
233
- print("HTTPError")
234
-
235
- break
236
-
237
- except requests.Timeout:
238
-
239
- print("Timeout")
240
-
241
- continue
242
-
243
- except requests.exceptions.RequestException as e:
244
-
245
- print(e)
246
-
247
- break
248
-
249
- except KeyError as e:
250
-
251
- error = str(e)
252
-
253
- if 'liveChatReplayContinuationData' in error:
254
-
255
- print('Hit last live chat segment, finishing job.')
256
-
257
- else:
258
-
259
- print("KeyError")
260
-
261
- print(e)
262
-
263
- break
264
-
265
- except SyntaxError as e:
266
-
267
- print("SyntaxError")
268
-
269
- print(e)
270
-
271
- break
272
-
273
- # continue #TODO
274
-
275
- except KeyboardInterrupt:
276
-
277
- break
278
-
279
- except Exception:
280
-
281
- print("Unexpected error:" + str(sys.exc_info()[0]))
282
-
283
-
284
-
285
- # Write the comment data to a file named after the title of the video.
286
-
287
- with open(title + ".json", mode='w', encoding="utf-8") as f:
288
-
289
- f.writelines(comment_data)
290
-
291
-
292
-
293
- print('Comment data saved to ' + title + '.json')
294
-
295
-
296
-
297
- ```
298
-
299
-
300
-
301
- ### 試したこと
302
-
303
- ・実行時、すぐ"Couldn't find live_chat_replay iframe. Maybe try running again?"と表示されるので、while(1):のループに入る前を見ていけば良いと考えました。
304
-
305
- ・そこで、デバッグによって各変数の状態を確認したところ、next_url=""のままでした。よって、>>if("live_chat_replay" in iframe["src"]):は一度もTrueにならなかったと考えています。(Trueなら何かしら代入されているため)
306
-
307
- ・上記条件式で使用されるiframeの中にはいろんなタグが入っていました。"src"に関係ありそうな箇所(自信ないです)を載せておきます。
308
-
309
- <iframe src="https://accounts.google.com/ServiceLogin?uilel=3&amp;hl=ja&amp;service=youtube&amp;passive=true&amp;continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Ffeature%3Dpassive%26next%3D%252Fsignin_passive%26hl%3Dja%26action_handle_signin%3Dtrue%26app%3Ddesktop" style="display: none"></iframe>
310
-
311
-
312
-
313
- iframeを見ても何を確認してどうすれば良いかわからなくなり手詰まりの状態になっています。。
314
-
315
-
316
-
317
- ### 補足情報(FW/ツールのバージョンなど)
318
-
319
- python 3.6.5
320
-
321
- beautifulsoup4 4.9.1
322
-
323
-
324
-
325
- 使用PC:
326
-
327
- Surface Pro 5
328
-
329
- Windows 10
3
+ 解決してから時間が経ったため質問の文章変更いたました。