1:绪
最近在做一个音乐下载软件,通过搜索音乐名称,下载youtube上信息匹配度最高的视频,提取其中的音频,来获取音乐。开源软件youtube-dl已经完成了视频下载和音频提取的全部工作,我要做的就是,获取目标视频的id或者视频链接,然后调用youtube-dl下载。
2:接口
谷歌官方其实已经提供了获取YouTube搜索结果的api,直接调用即可。
1 2 3 4 5 6 7 8 9 10
| def get_video_url_in_youtube_form_api(appKey,music_name): print("从google api获取数据") url = "https://youtube.googleapis.com/youtube/v3/search?q="+music_name+"&key="+appKey resp = requests.get(url) resp_json = resp.json() if resp.status_code ==200: return "https://www.youtube.com/watch?v="+resp_json['items'][0]['id']['videoId'] else: return 500
|
但是,谷歌api是有调用上限的,也就是10000个单位,每次搜索将消耗100个单位。那么我们总共可以通过api获取搜索结果的次数就是100个。这对于个人来说,实际上已经足够了,但是,如果要向他人提供服务,就不够了。
那么就只能上手爬虫了。
3:爬取搜索结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def get_video_url_in_youtube_from_crawler(keyword): url="https://m.youtube.com/results?search_query="+keyword print("通过爬虫获取数据") resp = requests.get(url) if resp.status_code==200: result_json = re.findall(r'ytInitialData = (.*);</script>', resp.text)[0] result_obj = json.loads(result_json) try: video_url = "https://www.youtube.com/watch?v="+result_obj['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][0]['itemSectionRenderer']['contents'][0]['videoRenderer']['videoId'] except KeyError: return 500 return video_url else: return 500
|
通过url和搜索值,构造搜索链接。获取返回的html代码。对html格式化后,可以发现,有一串包含搜索结果的json数据,藏在一个js代码中间,通过正则,将它提取出来。
谷歌是有反爬虫的机制的,就是说,如果频繁通过上述程序请求数据,获取到的json不一定能获得想要的内容。这里需要使用Exception来避免报错,假如爬取失败,应当再调用api。如果有代理隧道,那么爬虫就更好了。