Twitter作为数据存储

为什么没有人谈论Twitter作为数据存储呢?这是一个免费账户,它们大部分时间都在运行,你还可以轻松控制谁可以看到信息。如果你能在140个字符内完成(并且 很快将增加到10,000),那它就是一个存储数据的好方法。

@excellent_nums的推文

我这样做是为了我的 excellent numbers项目,该项目通过大量的计算来寻找具有特定属性的数字。这不是我存储数字的唯一方式,但当我找到这些数字时,我立即想到了将它们发推文,以防其他方法都失败了。如果我意外地删除了输出文件(我做到了),截断并覆盖了文件(我做到了),或者以其他某种方式搞砸了(我做到了),这些数字仍然会在Twitter上。

但我还有一个更有说服力的原因。我想在我程序找到另一个优秀数字时在我的手机上收到警报。不幸的是,我已经把我的车挂在iPhone上了。我有很多复杂的方法可以获得警报,但我已经使用Twitter并为此获得了警报。因此,我可以使用我已经安装的东西来备份存储和警报系统。我可以把更多的时间花在数学上,而不是花在安装和管理Redis(这也很简单,也值得在这里写一篇文章)上,然后再想出一种将新条目发送到我的手机的方法。

我在Mastering Perl中以非具体的方式描述了我的设置。我没有展示任何代码,尽管所有代码都在excellent_numbers GitHub仓库中。

在开始之前,你需要一些Twitter凭证来通过Net::Twitter模块使用他们的API。从Twitter应用程序管理开始,获取你需要的那四个特殊字符串(“如何在8个简单步骤中注册Twitter应用程序”有一个很好的步骤描述

消费者密钥(API密钥)

消费者密钥(API密钥)

访问令牌

访问令牌密钥

Net::Twitter模块需要这些字符串来创建其对象。该模块处理所有OAuth细节,而无需我思考

use Net::Twitter;

my $nt = Net::Twitter->new(
   traits   => [qw/OAuth API::RESTv1_1/],
   map { $_ => $ENV{"$_"} || die "ENV $_ not set" }
           qw(     
                consumer_secret
                consumer_key
                access_token
                access_token_secret
                )
   );

在我的优秀数字程序中,我想尽可能简单。我不想重发我已经发过的数字,所以我获取了我迄今为止的所有推文,并将它们存储在散列中。Twitter页面最多有200条推文,几个月前这似乎不会是个问题,但现在我已经超过了350个。

使用user_timeline方法很容易获取一堆状态。我需要告诉它从哪里开始(min_idsince_id)。Twitter返回包含大量信息的巨大JSON结构,但Net::Twitter将其转换为Perl数据结构。我导出他们发送的内容,并提取我想要的片段

my %tweets;
STATUSES: while( 1 ) {
  state $min_id = 1;
  state $fetch_size = 200;

  my $max_key = $min_id == 1 ? 'since_id' : 'max_id';

  my $statuses = $nt->user_timeline({
          count       => $fetch_size,
          screen_name => 'excellent_nums',
          $max_key    => $min_id,
          });     

  say { interactive } "Found " . @$statuses . " statuses";
  $min_id = $statuses->[-1]{id} - 1 if $min_id == 1;

  foreach my $status ( @$statuses ) {
          $min_id = $status->{id} - 1 if $min_id > $status->{id};
          my( $number ) = $status->{text} =~ m/(\d+)/;
          warn "[$number] has more than one tweet!\n" if exists $tweets{$number};
          $tweets{$number} = undef;
          unless( is_excellent( $number ) ) {
                  warn "Tweet for [$number] is an unexcellent error\n";
                  }       
          }       

  last if @$statuses < $fetch_size; # must be last page
  }

这部分之所以复杂,还有另一个原因。在项目开始时,我是按顺序生成优秀数字的。在这种情况下,我只需要查看上一条推文,看看它是否小于我刚刚发现的数字。当我到达大数字时,我扩大了范围,并行地在多个计算机上同时处理该范围的各个部分。我开始发现数字的顺序与推文的顺序不同。因此,需要分页。我可以在本地存储推文数字列表,但这也很麻烦,因为可能会出现不同步的情况。当这种方法耗尽时,我可能还会这样做。但我不太可能找到超过500个数字。

请注意,如果我发现一条推文中的数字我认为是重复的,我也会进行warn

warn "[$number] has more than one tweet!\n" if exists $tweets{$number};

如果这是一个更大的问题(现在已经不是了),我可以用destroy_status方法来自动删除它

$nt->destroy_status( $status->{id} ) if exists $tweets{$number};

我决定不在程序中自动删除。重复并不成问题。它有点乱,但删除我想保留的内容和转发它会更乱。这种风险让我觉得不值得。我不想再清理另一个可能的自动化混乱。

现在我知道了我之前发布的所有推文,并将它们放入了%tweets。下一步是推文我找到的但尚未存储的内容。我也将它们存储在本地文件中(但记住我想保留警报和备份!)这个文件被用来填充%numbers。我跳过了已经推文过的数字,并使用update来制作新的推文。存储新数字很简单,当我这么做时,我想按升序推文新数字

NUMBER: foreach my $number ( sort { $a <=> $b } keys %numbers ) {
  next NUMBER if exists $tweets{$number};

  $nt->update( "$number is excellent" );
  }

这曾经是程序的一部分,用于找到优秀数字,但为了性能的大幅提升,我切换到了C语言。我仍然想从Perl中推文,这很简单。Perl已经成为连接许多不同事物的胶水。

一旦我可以从Twitter中读取、发布和删除,其他应用程序(甚至真人)都可以跟随它。它可以公开也可以私密。它并不复杂。它的正常运行时间不会赢得任何奖项。但它是免费的,对我的小任务来说很简单。


这篇文章最初发布在PerlTricks.com

标签

brian d foy

brian d foy是一位Perl培训师和作家,同时也是Perl.com的高级编辑。他是《Mastering Perl》、《Mojolicious Web Clients》、《Learning Perl Exercises》的作者,也是《Programming Perl》、《Learning Perl》、《Intermediate Perl》和《Effective Perl Programming》的合著者。

浏览他们的文章

反馈

这篇文章有什么问题吗?请通过在GitHub上打开一个问题或拉取请求来帮助我们。