【问题标题】:How to get all YouTube comments with Python's gdata module?如何使用 Python 的 gdata 模块获取所有 YouTube 评论?
【发布时间】:2012-10-01 08:34:36
【问题描述】:

希望从给定视频中获取所有 cmets,而不是一次只浏览一页。

from gdata import youtube as yt
from gdata.youtube import service as yts

client = yts.YouTubeService()
client.ClientLogin(username, pwd) #the pwd might need to be application specific fyi

comments = client.GetYouTubeVideoComments(video_id='the_id')
a_comment = comments.entry[0]

上面的代码可以让您抓取一条评论,可能是最近的评论,但我正在寻找一种方法来一次抓取所有 cmets。使用 Python 的 gdata 模块可以做到这一点吗?


comments 的 Youtube API 文档、评论提要 docs 和 Python API docs

【问题讨论】:

  • here 使用 PHP 的解决方案回答了这个问题,因为 YouTube PHP API 有一个允许它的调用。我认为没有纯 Python 的答案。
  • @KenB 我也看到了。真可惜。有问题的视频有 9k cmets,我不认为拨打 360 GetNextLink 电话是最好的方法。
  • 网址www.youtube.com/all_comments?v=video_id有一个可解析的评论列表,但是加载时间长。假设我可以试试。
  • 无论您使用什么方法,如果您一次返回 9k cmets,您将有很长的加载时间。我认为这就是 API 不提供它的原因;您通常不想一次完成所有操作。

标签: python youtube-api gdata


【解决方案1】:

以下使用Python YouTube API实现了您所要求的:

from gdata.youtube import service

USERNAME = 'username@gmail.com'
PASSWORD = 'a_very_long_password'
VIDEO_ID = 'wf_IIbT8HGk'

def comments_generator(client, video_id):
    comment_feed = client.GetYouTubeVideoCommentFeed(video_id=video_id)
    while comment_feed is not None:
        for comment in comment_feed.entry:
             yield comment
        next_link = comment_feed.GetNextLink()
        if next_link is None:
             comment_feed = None
        else:
             comment_feed = client.GetYouTubeVideoCommentFeed(next_link.href)

client = service.YouTubeService()
client.ClientLogin(USERNAME, PASSWORD)

for comment in comments_generator(client, VIDEO_ID):
    author_name = comment.author[0].name.text
    text = comment.content.text
    print("{}: {}".format(author_name, text))

很遗憾,API 将可检索的条目数限制为 1000。这是我尝试使用手工制作的GetYouTubeVideoCommentFeed URL 参数调整版本时遇到的错误:

gdata.service.RequestError: {'status': 400, 'body': 'You cannot request beyond item 1000.', 'reason': 'Bad Request'}

请注意,同样的原则应该适用于检索 API 的其他提要中的条目。

如果你想手工制作GetYouTubeVideoCommentFeed URL参数,它的格式是:

'https://gdata.youtube.com/feeds/api/videos/{video_id}/comments?start-index={sta‌​rt_index}&max-results={max_results}'

适用以下限制:start-index <= 1000max-results <= 50

【讨论】:

  • 太棒了。你知道是否有办法手动设置start_indexitems_per_page?在第一组 cmets 上设置它似乎没有任何作用。
  • 您只需将以下格式的 URL 传递给GetYouTubeVideoCommentFeedhttps://gdata.youtube.com/feeds/api/videos/{video_id}/comments?start-index={start_index}&max-results={max_results}。以下限制适用:start-index <= 1000max-results <= 50
  • 请注意,要传递 URI,您需要将 uri 作为 kwarg 传递:yt_service.GetYouTubeVideoCommentFeed(uri='https://gdata.youtube.com/feeds/...')
  • @Roshambo: uri 是第一个位置参数,因此将其指定为 kwarg 是多余的,不是必需的。是什么让你说它一定是 kwarg?
  • @PedroRomano 啊,没有意识到这是第一个参数。 PyDocs 太密集了,我一定错过了。
【解决方案2】:

我目前唯一的解决方案,但它没有使用 API,并且在有几千个 cmets 时会变慢。

import bs4, re, urllib2
#grab the page source for vide
data = urllib2.urlopen(r'http://www.youtube.com/all_comments?v=video_id') #example XhFtHW4YB7M
#pull out comments
soup = bs4.BeautifulSoup(data)
cmnts = soup.findAll(attrs={'class': 'comment yt-tile-default'})
#do something with them, ie count them
print len(cmnts)

请注意,由于 'class' 是一个内置的 python 名称,您不能通过正则表达式或 lambdas 定期搜索 'startwith',如 here 所示,因为您使用的是字典,而不是常规参数。由于 BeautifulSoup,它也变得很慢,但它需要被使用,因为 etreeminidom 由于某种原因找不到匹配的标签。即使在prettyfying()bs4 之后

【讨论】:

  • 嗨,有趣的答案,但我认为 html 结构已经改变。您是否使用替代标签而不是 comment yt-tile-default?谢谢!
  • @Thoth 我已经有一段时间没有使用它了,但是如果你发现了,请打开开发工具并编辑我的答案
猜你喜欢
  • 2020-10-25
  • 2013-11-26
  • 2012-03-08
  • 2021-05-07
  • 2017-07-12
  • 1970-01-01
  • 2014-05-31
  • 2012-12-17
  • 2014-05-14
相关资源
最近更新 更多