transcript api implemented
This commit is contained in:
		
							parent
							
								
									119e694f3f
								
							
						
					
					
						commit
						55d76a158a
					
				|  | @ -1,2 +1,3 @@ | ||||||
| .idea | .idea | ||||||
| .venv | .venv | ||||||
|  | *.pyc | ||||||
|  | @ -1 +1 @@ | ||||||
| selenium==3.11.0 | requests==2.18.4 | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,72 @@ | ||||||
|  | from xml.etree import ElementTree | ||||||
|  | 
 | ||||||
|  | import re | ||||||
|  | 
 | ||||||
|  | import logging | ||||||
|  | 
 | ||||||
|  | import requests | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | logger = logging.getLogger(__name__) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class YouTubeTranscriptApi(): | ||||||
|  |     @staticmethod | ||||||
|  |     def get(*video_ids): | ||||||
|  |         data = {} | ||||||
|  | 
 | ||||||
|  |         for video_id in video_ids: | ||||||
|  |             try: | ||||||
|  |                 data[video_id] = _TranscriptParser(_TranscriptFetcher(video_id).fetch()).parse() | ||||||
|  |             except Exception: | ||||||
|  |                 logger.error( | ||||||
|  |                     'Could not get the transcript for the video {video_url}! ' | ||||||
|  |                     'Most likely subtitles have been disabled by the uploader or the video is no longer ' | ||||||
|  |                     'available.'.format( | ||||||
|  |                         video_url=_TranscriptFetcher.WATCH_URL.format(video_id=video_id) | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  | 
 | ||||||
|  |         return data | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class _TranscriptFetcher(): | ||||||
|  |     WATCH_URL = 'https://www.youtube.com/watch?v={video_id}' | ||||||
|  |     API_BASE_URL = 'https://www.youtube.com/api/{api_url}' | ||||||
|  | 
 | ||||||
|  |     def __init__(self, video_id): | ||||||
|  |         self.video_id = video_id | ||||||
|  | 
 | ||||||
|  |     def fetch(self): | ||||||
|  |         fetched_site = requests.get(self.WATCH_URL.format(video_id=self.video_id)).text | ||||||
|  | 
 | ||||||
|  |         timedtext_url_start = fetched_site.find('timedtext') | ||||||
|  | 
 | ||||||
|  |         return requests.get( | ||||||
|  |             self.API_BASE_URL.format( | ||||||
|  |                 api_url=fetched_site[ | ||||||
|  |                     timedtext_url_start:timedtext_url_start + fetched_site[timedtext_url_start:].find('"') | ||||||
|  |                 ].replace( | ||||||
|  |                     '\\u0026', '&' | ||||||
|  |                 ).replace( | ||||||
|  |                     '\\', '' | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         ).text | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class _TranscriptParser(): | ||||||
|  |     HTML_TAG_REGEX = re.compile(r'<[^>]*>', re.IGNORECASE) | ||||||
|  | 
 | ||||||
|  |     def __init__(self, plain_data): | ||||||
|  |         self.plain_data = plain_data | ||||||
|  | 
 | ||||||
|  |     def parse(self): | ||||||
|  |         return [ | ||||||
|  |             { | ||||||
|  |                 'text': re.sub(self.HTML_TAG_REGEX, '', xml_element.text), | ||||||
|  |                 'start': float(xml_element.attrib['start']), | ||||||
|  |                 'duration': float(xml_element.attrib['dur']), | ||||||
|  |             } | ||||||
|  |             for xml_element in ElementTree.fromstring(self.plain_data) | ||||||
|  |         ] | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -0,0 +1,10 @@ | ||||||
|  | #!./.venv/bin/python | ||||||
|  | 
 | ||||||
|  | import sys | ||||||
|  | 
 | ||||||
|  | import json | ||||||
|  | 
 | ||||||
|  | from src.transcript_api import YouTubeTranscriptApi | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     print(json.dumps(YouTubeTranscriptApi.get(*sys.argv[1:]))) | ||||||
		Loading…
	
		Reference in New Issue