打印Tumblr API中的20多个帖子

时间:2017-11-15 15:54:37

标签: python tumblr pytumblr

下午好,

我对Python很陌生,但我正在尝试编写一个允许我下载所有帖子的代码(包括"笔记") 从指定的Tumblr帐户到我的电脑。

鉴于我没有编码经验,我试图找到一个预制的脚本,这将允许我这样做。我在GitHub上找到了几个精彩的脚本,但是没有一个真正从Tumblr帖子中返回笔记(据我所见,尽管如果有人知道那个,那么请纠正我。)。

因此,我试着编写自己的脚本。我在下面的代码中取得了一些成功。它打印出来自给定Tumblr的最新20个帖子(尽管格式相当丑陋 - 基本上数百行文本都打印在记事本文件的一行中):

#This script prints all the posts (including tags, comments) and also the 
#first 20notes from all the Tumblr blogs.

import pytumblr

# Authenticate via API Key
client = pytumblr.TumblrRestClient('myapikey')

#offset = 0

# Make the request
client.posts('staff', limit=2000, offset=0, reblog_info=True, notes_info=True, 
filter='html')
#print out into a .txt file
with open('out.txt', 'w') as f:
print >> f, client.posts('staff', limit=2000, offset=0, reblog_info=True, 
notes_info=True, filter='html')

但是,我希望脚本能够持续打印帖子,直到它到达指定博客的末尾。

我搜索了这个网站,发现了一个非常相似的问题(Getting only 20 posts returned through PyTumblr),已经被stackoverflow用户戳回答了。但是,我似乎无法实际实施poke的解决方案,以便它适用于我的数据。实际上,当我运行以下脚本时,根本不会产生任何输出。

import pytumblr

# Authenticate via API Key
client = pytumblr.TumblrRestClient('myapikey')
blog = ('staff')
def getAllPosts (client, blog):
offset = 0
while True:
    posts = client.posts(blog, limit=20, offset=offset, reblog_info=True, notes_info=True)
    if not posts:
        return

    for post in posts:
        yield post


    offset += 20

我应该注意到这个网站上有几篇关于Tumblr笔记的帖子(例如Getting more than 50 notes with Tumblr API),其中大多数都询问如何为每个帖子下载超过50个笔记。我非常满意每篇文章只有50个笔记,这是我希望增加的帖子数量。

另外,我已经将这篇文章标记为Python,但是,如果有更好的方法来获取我需要使用其他编程语言的数据,那就更好了。

非常感谢你的时间!

1 个答案:

答案 0 :(得分:3)

tl; dr如果你想看到答案,那么它位于标题更正版本

之后的底部

第二个代码片段是一个逐个生成帖子的生成器,所以你必须将它作为循环的一部分使用,然后对输出做一些事情。这是您的代码,其中包含一些额外的代码,这些代码遍历生成器并打印出它返回的数据。

import pytumblr

def getAllPosts (client, blog):
    offset = 0
    while True:
        posts = client.posts(blog, limit=20, offset=offset, reblog_info=True, notes_info=True)
        if not posts:
            return

        for post in posts:
            yield post

        offset += 20

# Authenticate via API Key
client = pytumblr.TumblrRestClient('myapikey')
blog = ('staff')

# use the generator getAllPosts
for post in getAllPosts(client, blog):
    print(post)

但是,该代码中有一些错误。 getAllPosts不会仅仅发布每个帖子,它也会返回其他内容,因为它将遍历API响应,正如您在此示例中看到的,我在ipython shell中运行。

In [7]: yielder = getAllPosts(client, 'staff')

In [8]: next(yielder)
Out[8]: 'blog'

In [9]: next(yielder)
Out[9]: 'posts'

In [10]: next(yielder)
Out[10]: 'total_posts'

In [11]: next(yielder)
Out[11]: 'supply_logging_positions'

In [12]: next(yielder)
Out[12]: 'blog'

In [13]: next(yielder)
Out[13]: 'posts'

In [14]: next(yielder)
Out[14]: 'total_posts'

这是因为posts中的getAllPosts对象是一个字典,其中不仅包含来自staff博客的每篇帖子 - 它还包含博客包含的帖子数量等项目,博客的描述,上次更新等等。代码原样可能会导致无限循环,因为以下条件:

if not posts:
    return

由于响应结构,永远不会成为现实,因为来自pytumblr的空Tumblr API响应如下所示:

{'blog': {'ask': False,
  'ask_anon': False,
  'ask_page_title': 'Ask me anything',
  'can_send_fan_mail': False,
  'can_subscribe': False,
  'description': '',
  'followed': False,
  'is_adult': False,
  'is_blocked_from_primary': False,
  'is_nsfw': False,
  'is_optout_ads': False,
  'name': 'asdfasdf',
  'posts': 0,
  'reply_conditions': '3',
  'share_likes': False,
  'subscribed': False,
  'title': 'Untitled',
  'total_posts': 0,
  'updated': 0,
  'url': 'https://asdfasdf.tumblr.com/'},
 'posts': [],
 'supply_logging_positions': [],
 'total_posts': 0}

if not posts将针对该结构进行检查,而不是posts字段(此处为空列表),因此条件永远不会失败,因为响应字典不为空(请参阅: Truth Value Testing in Python)。

更正版本

这里的代码(主要经过测试/验证)修复了getAllPosts实现中的循环,然后使用该函数检索帖子并将其转储到名为(BLOG_NAME)-posts.txt的文件中。

import pytumblr


def get_all_posts(client, blog):
    offset = 0
    while True:
        response = client.posts(blog, limit=20, offset=offset, reblog_info=True, notes_info=True)

        # Get the 'posts' field of the response        
        posts = response['posts']

        if not posts: return

        for post in posts:
            yield post

        # move to the next offset
        offset += 20


client = pytumblr.TumblrRestClient('secrety-secret')
blog = 'staff'

# use our function
with open('{}-posts.txt'.format(blog), 'w') as out_file:
    for post in get_all_posts(client, blog):
        print >>out_file, post
        # if you're in python 3.x, use the following
        # print(post, file=out_file)

这只是API的帖子回复的直接文本转储,所以如果你需要使它看起来更好或任何东西,那取决于你。