]> jfr.im git - yt-dlp.git/blob - yt_dlp/extractor/weibo.py
bc9a71abe070f187500a487d954e7a4a0d016a91
[yt-dlp.git] / yt_dlp / extractor / weibo.py
1 from .common import InfoExtractor
2
3 import json
4 import random
5 import re
6
7 from ..compat import (
8 compat_parse_qs,
9 compat_str,
10 )
11 from ..utils import (
12 js_to_json,
13 strip_jsonp,
14 urlencode_postdata,
15 )
16
17
18 class WeiboIE(InfoExtractor):
19 _VALID_URL = r'https?://(?:www\.)?weibo\.com/[0-9]+/(?P<id>[a-zA-Z0-9]+)'
20 _TEST = {
21 'url': 'https://weibo.com/6275294458/Fp6RGfbff?type=comment',
22 'info_dict': {
23 'id': 'Fp6RGfbff',
24 'ext': 'mp4',
25 'title': 'You should have servants to massage you,... 来自Hosico_猫 - 微博',
26 }
27 }
28
29 def _real_extract(self, url):
30 video_id = self._match_id(url)
31 # to get Referer url for genvisitor
32 webpage, urlh = self._download_webpage_handle(url, video_id)
33
34 visitor_url = urlh.url
35
36 if 'passport.weibo.com' in visitor_url:
37 # first visit
38 visitor_data = self._download_json(
39 'https://passport.weibo.com/visitor/genvisitor', video_id,
40 note='Generating first-visit data',
41 transform_source=strip_jsonp,
42 headers={'Referer': visitor_url},
43 data=urlencode_postdata({
44 'cb': 'gen_callback',
45 'fp': json.dumps({
46 'os': '2',
47 'browser': 'Gecko57,0,0,0',
48 'fonts': 'undefined',
49 'screenInfo': '1440*900*24',
50 'plugins': '',
51 }),
52 }))
53
54 tid = visitor_data['data']['tid']
55 cnfd = '%03d' % visitor_data['data']['confidence']
56
57 self._download_webpage(
58 'https://passport.weibo.com/visitor/visitor', video_id,
59 note='Running first-visit callback',
60 query={
61 'a': 'incarnate',
62 't': tid,
63 'w': 2,
64 'c': cnfd,
65 'cb': 'cross_domain',
66 'from': 'weibo',
67 '_rand': random.random(),
68 })
69
70 webpage = self._download_webpage(
71 url, video_id, note='Revisiting webpage')
72
73 title = self._html_extract_title(webpage)
74
75 video_formats = compat_parse_qs(self._search_regex(
76 r'video-sources=\\\"(.+?)\"', webpage, 'video_sources'))
77
78 formats = []
79 supported_resolutions = (480, 720)
80 for res in supported_resolutions:
81 vid_urls = video_formats.get(compat_str(res))
82 if not vid_urls or not isinstance(vid_urls, list):
83 continue
84
85 vid_url = vid_urls[0]
86 formats.append({
87 'url': vid_url,
88 'height': res,
89 })
90
91 uploader = self._og_search_property(
92 'nick-name', webpage, 'uploader', default=None)
93
94 return {
95 'id': video_id,
96 'title': title,
97 'uploader': uploader,
98 'formats': formats
99 }
100
101
102 class WeiboMobileIE(InfoExtractor):
103 _VALID_URL = r'https?://m\.weibo\.cn/status/(?P<id>[0-9]+)(\?.+)?'
104 _TEST = {
105 'url': 'https://m.weibo.cn/status/4189191225395228?wm=3333_2001&sourcetype=weixin&featurecode=newtitle&from=singlemessage&isappinstalled=0',
106 'info_dict': {
107 'id': '4189191225395228',
108 'ext': 'mp4',
109 'title': '午睡当然是要甜甜蜜蜜的啦',
110 'uploader': '柴犬柴犬'
111 }
112 }
113
114 def _real_extract(self, url):
115 video_id = self._match_id(url)
116 # to get Referer url for genvisitor
117 webpage = self._download_webpage(url, video_id, note='visit the page')
118
119 weibo_info = self._parse_json(self._search_regex(
120 r'var\s+\$render_data\s*=\s*\[({.*})\]\[0\]\s*\|\|\s*{};',
121 webpage, 'js_code', flags=re.DOTALL),
122 video_id, transform_source=js_to_json)
123
124 status_data = weibo_info.get('status', {})
125 page_info = status_data.get('page_info')
126 title = status_data['status_title']
127 uploader = status_data.get('user', {}).get('screen_name')
128
129 return {
130 'id': video_id,
131 'title': title,
132 'uploader': uploader,
133 'url': page_info['media_info']['stream_url']
134 }