質問編集履歴

2

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

2020/09/10 00:40

投稿

mongaa
mongaa

スコア2

title CHANGED
@@ -1,1 +1,1 @@
1
- 終了した質問です。。。。。
1
+ YouTube Liveのアーカイブからチャットを取得するコードを模写したが上手くいかない @Python
body CHANGED
@@ -1,2 +1,130 @@
1
- 回答いただきありがとうございました
2
- 解決してから時間が経ったため質問の文章変更いたました。
1
+ ### 前提・実現したいこと
2
+ PythonでYoutube Liveのアーカイブからチャット取得したいです
3
+ こちらのサイトのコードをほぼそのまま使用しています。
4
+ https://github.com/geerlingguy/youtube_chat_crawler/blob/master/YoutubeChatReplayCrawler.py
5
+ コードは下記について変更しています。
6
+ →youtubeの動画IDを引数としてvideo_idに入れているのを、初めからtarget_urlに打ち込んでいます。したがって、引数の長さを判別する箇所もコメントアウトしています。
7
+ ### 発生している問題・エラーメッセージ
8
+ pyファイルを実行し作成されるテキストファイル(comment_data.txt)を開いても中身が空っぽです。
9
+ cmd,Visual Studio Code共にエラーメッセージは発生していません。
10
+ 指定した動画からコメントを取得する流れのどこかで想定通りに動いていないと思われますが、
11
+ 解決策が分からなくて困っています。
12
+ ### 該当のソースコード
13
+ ```Python
14
+ #!/usr/bin/env python3
15
+ from bs4 import BeautifulSoup
16
+ import ast
17
+ import requests
18
+ import re
19
+ import sys
20
+ # Verify user supplied a YouTube URL.
21
+ #if len(sys.argv) == 1:
22
+ # print("Please provide a YouTube URL (e.g. ./YoutubeChatReplayCrawler.py YOUTUBE_VIDEO_URL)")
23
+ # sys.exit(0)
24
+ # Produce a valid filename (from Django text utils).
25
+ def get_valid_filename(s):
26
+ s = str(s).strip().replace(' ', '_')
27
+ return re.sub(r'(?u)[^-\w.]', '', s)
28
+ # Set up variables for requests.
29
+ #target_url = sys.argv[1]
30
+ target_url = "https://www.youtube.com/watch?v=mOBvvwCosE4" #←適当に選んだ動画のURL
31
+ dict_str = ''
32
+ next_url = ''
33
+ comment_data = []
34
+ session = requests.Session()
35
+ 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'}
36
+ # Get the video page.
37
+ html = session.get(target_url)
38
+ soup = BeautifulSoup(html.text, 'html.parser')
39
+ # Retrieve the title and sanitize so it is a valid filename.
40
+ title = soup.find_all('title')
41
+ title = title[0].text.replace(' - YouTube', '')
42
+ title = get_valid_filename(title)
43
+ # Regex match for emoji.
44
+ RE_EMOJI = re.compile('[\U00010000-\U0010ffff]', flags=re.UNICODE)
45
+ # Find any live_chat_replay elements, get URL for next live chat message.
46
+ for iframe in soup.find_all("iframe"):
47
+ if("live_chat_replay" in iframe["src"]):
48
+ next_url = iframe["src"]
49
+ if not next_url:
50
+ print("Couldn't find live_chat_replay iframe. Maybe try running again?")
51
+ sys.exit(0)
52
+ # TODO - We should fail fast if next_url is empty, otherwise you get error:
53
+ # Invalid URL '': No schema supplied. Perhaps you meant http://?
54
+ # TODO - This loop is fragile. It loops endlessly when some exceptions are hit.
55
+ while(1):
56
+ try:
57
+ html = session.get(next_url, headers=headers)
58
+ soup = BeautifulSoup(html.text, 'lxml')
59
+ # Loop through all script tags.
60
+ for script in soup.find_all('script'):
61
+ script_text = str(script)
62
+ if 'ytInitialData' in script_text:
63
+ dict_str = ''.join(script_text.split(" = ")[1:])
64
+ # Capitalize booleans so JSON is valid Python dict.
65
+ dict_str = dict_str.replace("false", "False")
66
+ dict_str = dict_str.replace("true", "True")
67
+ # Strip extra HTML from JSON.
68
+ dict_str = re.sub(r'};.*\n.+</script>', '}', dict_str)
69
+ # Correct some characters.
70
+ dict_str = dict_str.rstrip(" \n;")
71
+ # TODO: I don't seem to have any issues with emoji in the messages.
72
+ # dict_str = RE_EMOJI.sub(r'', dict_str)
73
+ # Evaluate the cleaned up JSON into a python dict.
74
+ dics = ast.literal_eval(dict_str)
75
+ # TODO: On the last pass this returns KeyError since there are no more
76
+ # continuations or actions. Should probably just break in that case.
77
+ continue_url = dics["continuationContents"]["liveChatContinuation"]["continuations"][0]["liveChatReplayContinuationData"]["continuation"]
78
+ print('Found another live chat continuation:')
79
+ print(continue_url)
80
+ next_url = "https://www.youtube.com/live_chat_replay?continuation=" + continue_url
81
+ # Extract the data for each live chat comment.
82
+ for samp in dics["continuationContents"]["liveChatContinuation"]["actions"][1:]:
83
+ comment_data.append(str(samp) + "\n")
84
+ # next_urlが入手できなくなったら終わり
85
+ except requests.ConnectionError:
86
+ print("Connection Error")
87
+ continue
88
+ except requests.HTTPError:
89
+ print("HTTPError")
90
+ break
91
+ except requests.Timeout:
92
+ print("Timeout")
93
+ continue
94
+ except requests.exceptions.RequestException as e:
95
+ print(e)
96
+ break
97
+ except KeyError as e:
98
+ error = str(e)
99
+ if 'liveChatReplayContinuationData' in error:
100
+ print('Hit last live chat segment, finishing job.')
101
+ else:
102
+ print("KeyError")
103
+ print(e)
104
+ break
105
+ except SyntaxError as e:
106
+ print("SyntaxError")
107
+ print(e)
108
+ break
109
+ # continue #TODO
110
+ except KeyboardInterrupt:
111
+ break
112
+ except Exception:
113
+ print("Unexpected error:" + str(sys.exc_info()[0]))
114
+ # Write the comment data to a file named after the title of the video.
115
+ with open(title + ".json", mode='w', encoding="utf-8") as f:
116
+ f.writelines(comment_data)
117
+ print('Comment data saved to ' + title + '.json')
118
+ ```
119
+ ### 試したこと
120
+ ・実行時、すぐ"Couldn't find live_chat_replay iframe. Maybe try running again?"と表示されるので、while(1):のループに入る前を見ていけば良いと考えました。
121
+ ・そこで、デバッグによって各変数の状態を確認したところ、next_url=""のままでした。よって、>>if("live_chat_replay" in iframe["src"]):は一度もTrueにならなかったと考えています。(Trueなら何かしら代入されているため)
122
+ ・上記条件式で使用されるiframeの中にはいろんなタグが入っていました。"src"に関係ありそうな箇所(自信ないです)を載せておきます。
123
+ <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>
124
+ iframeを見ても何を確認してどうすれば良いかわからなくなり手詰まりの状態になっています。。
125
+ ### 補足情報(FW/ツールのバージョンなど)
126
+ python 3.6.5
127
+ beautifulsoup4 4.9.1
128
+ 使用PC:
129
+ Surface Pro 5
130
+ Windows 10

1

修正

2020/09/10 00:40

投稿

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