+
+
+class VKWallPostIE(VKBaseIE):
+ IE_NAME = 'vk:wallpost'
+ _VALID_URL = r'https?://(?:(?:(?:(?:m|new)\.)?vk\.com/(?:[^?]+\?.*\bw=)?wall(?P<id>-?\d+_\d+)))'
+ _TESTS = [{
+ # public page URL, audio playlist
+ 'url': 'https://vk.com/bs.official?w=wall-23538238_35',
+ 'info_dict': {
+ 'id': '23538238_35',
+ 'title': 'Black Shadow - Wall post 23538238_35',
+ 'description': 'md5:3f84b9c4f9ef499731cf1ced9998cc0c',
+ },
+ 'playlist': [{
+ 'md5': '5ba93864ec5b85f7ce19a9af4af080f6',
+ 'info_dict': {
+ 'id': '135220665_111806521',
+ 'ext': 'mp3',
+ 'title': 'Black Shadow - Слепое Верование',
+ 'duration': 370,
+ 'uploader': 'Black Shadow',
+ 'artist': 'Black Shadow',
+ 'track': 'Слепое Верование',
+ },
+ }, {
+ 'md5': '4cc7e804579122b17ea95af7834c9233',
+ 'info_dict': {
+ 'id': '135220665_111802303',
+ 'ext': 'mp3',
+ 'title': 'Black Shadow - Война - Негасимое Бездны Пламя!',
+ 'duration': 423,
+ 'uploader': 'Black Shadow',
+ 'artist': 'Black Shadow',
+ 'track': 'Война - Негасимое Бездны Пламя!',
+ },
+ 'params': {
+ 'skip_download': True,
+ },
+ }],
+ 'skip': 'Requires vk account credentials',
+ }, {
+ # single YouTube embed, no leading -
+ 'url': 'https://vk.com/wall85155021_6319',
+ 'info_dict': {
+ 'id': '85155021_6319',
+ 'title': 'Sergey Gorbunov - Wall post 85155021_6319',
+ },
+ 'playlist_count': 1,
+ 'skip': 'Requires vk account credentials',
+ }, {
+ # wall page URL
+ 'url': 'https://vk.com/wall-23538238_35',
+ 'only_matching': True,
+ }, {
+ # mobile wall page URL
+ 'url': 'https://m.vk.com/wall-23538238_35',
+ 'only_matching': True,
+ }]
+
+ def _real_extract(self, url):
+ post_id = self._match_id(url)
+
+ wall_url = 'https://vk.com/wall%s' % post_id
+
+ post_id = remove_start(post_id, '-')
+
+ webpage = self._download_webpage(wall_url, post_id)
+
+ error = self._html_search_regex(
+ r'>Error</div>\s*<div[^>]+class=["\']body["\'][^>]*>([^<]+)',
+ webpage, 'error', default=None)
+ if error:
+ raise ExtractorError('VK said: %s' % error, expected=True)
+
+ description = clean_html(get_element_by_class('wall_post_text', webpage))
+ uploader = clean_html(get_element_by_class(
+ 'fw_post_author', webpage)) or self._og_search_description(webpage)
+ thumbnail = self._og_search_thumbnail(webpage)
+
+ entries = []
+
+ for audio in re.finditer(r'''(?sx)
+ <input[^>]+
+ id=(?P<q1>["\'])audio_info(?P<id>\d+_\d+).*?(?P=q1)[^>]+
+ value=(?P<q2>["\'])(?P<url>http.+?)(?P=q2)
+ .+?
+ </table>''', webpage):
+ audio_html = audio.group(0)
+ audio_id = audio.group('id')
+ duration = parse_duration(get_element_by_class('duration', audio_html))
+ track = self._html_search_regex(
+ r'<span[^>]+id=["\']title%s[^>]*>([^<]+)' % audio_id,
+ audio_html, 'title', default=None)
+ artist = self._html_search_regex(
+ r'>([^<]+)</a></b>\s*&ndash', audio_html,
+ 'artist', default=None)
+ entries.append({
+ 'id': audio_id,
+ 'url': audio.group('url'),
+ 'title': '%s - %s' % (artist, track) if artist and track else audio_id,
+ 'thumbnail': thumbnail,
+ 'duration': duration,
+ 'uploader': uploader,
+ 'artist': artist,
+ 'track': track,
+ })
+
+ for video in re.finditer(
+ r'<a[^>]+href=(["\'])(?P<url>/video(?:-?[\d_]+).*?)\1', webpage):
+ entries.append(self.url_result(
+ compat_urlparse.urljoin(url, video.group('url')), VKIE.ie_key()))
+
+ title = 'Wall post %s' % post_id
+
+ return self.playlist_result(
+ orderedSet(entries), post_id,
+ '%s - %s' % (uploader, title) if uploader else title,
+ description)