• API爬虫--Twitter实战


    本篇将从实际例子出发,展示如何使用api爬取twitter的数据。


    1. 创建APP

    进入https://apps.twitter.com/,创建自己的app。只有有了app才可以访问twitter的api并抓取数据。只需创建最简单的app即可,各种信息随意填写,并不需要进一步的认证,我们要的只是app的Consumer Key (API Key), Consumer Secret (API Secret), Access Token 和 Access Token Secret。鉴于单app的爬取次数限制,可以申请很多app来提高总次数。


    2. 确定要使用的API

    twitter提供多种类型的api,其中常用的有REST APIStreaming API。前者是常见的api类型,后者则可以跟踪监视一个用户或者一个话题。

    REST API下面有很多的api,有价值爬取的有以下几个:

    • GET statuses/user_timeline:返回一个用户发的推文。注意twitter里回复也相当于发推文。
    • GET friends/ids:返回一个用户的followees。
    • GET followers/ids:返回一个用户的followers。
    • GET users/show:返回一个用户的信息。

    3. 官方类库

    下载twitter的类库。说实话,api爬虫好不好写,全看类库提供的功能强不强。twitter提供了多种语言的类库,本文选择java类库。


    4. 验证授权

    凡是访问api,都需要验证授权,也即:OAuth。一般流程为:以app的id和key,用户的用户名和密码为参数访问授权api,返回一个token(一个字符串),即算是授权完成,之后只需访问其他api时带上这个参数就行了。

    当然,不同的网站授权过程各有不同。较为繁琐的比如人人网需要先跳转至回调网页,用户登陆后再返回token。twitter的授权过程也不简单(需要多次http请求),但是幸运的是类库中已经帮我们实现了此过程。

    例,twitter的Auth1.1授权,其中需要设置的四个参数在app管理界面就能看到:

    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setOAuthAccessToken(accessToken);
    cb.setOAuthAccessTokenSecret(accessTokenSecret);
    cb.setOAuthConsumerKey(consumerKey);
    cb.setOAuthConsumerSecret(consumerSecret);
    OAuthAuthorization auth = new OAuthAuthorization(cb.build());
    Twitter twitter = new TwitterFactory().getInstance(auth);

    twitter还提供一种无需用户授权(需app授权)的选择,访问某些api时可用次数比Auth1.1授权的要多:

    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setApplicationOnlyAuthEnabled(true);
    Twitter twitter = new TwitterFactory(cb.build()).getInstance();
    twitter.setOAuthConsumer(consumerKey, consumerSecret);
    try {
        twitter.getOAuth2Token();
    } catch (TwitterException e) {
        e.printStackTrace();
    }

    5. 调用API

    授权之后,我们就可以真正地开始爬数据了。

    1. REST API

    爬取用户follower,getFollowersIDs方法每次返回最多5000个follower,cursor用户标记从哪开始:

    IDs iDs = twitter.getFollowersIDs(uid, cursor);

    爬取用户推文:

    ResponseList<Status> status = twitter.getUserTimeline(uid, page);
    1. Streaming API

    监视一个用户的所有行为,其中UserStreamListener太长了只截取了一部分:

    TwitterStream twitterStream;
    twitterStream = new TwitterStreamFactory(cb.build()).getInstance();
    twitterStream.addListener(listener);
    twitterStream.user();
    
    private static final UserStreamListener listener = new UserStreamListener() {
            @Override
            public void onStatus(Status status) {
                System.out.println("onStatus @" + status.getUser().getScreenName() + " - " + status.getText() + status.getCreatedAt());
            }
    
            @Override
            public void onDeletionNotice(StatusDeletionNotice statusDeletionNotice) {
                System.out.println("Got a status deletion notice id:" + statusDeletionNotice.getStatusId());
            }
    
            @Override
            public void onDeletionNotice(long directMessageId, long userId) {
                System.out.println("Got a direct message deletion notice id:" + directMessageId);
            }
    
            @Override
            public void onTrackLimitationNotice(int numberOfLimitedStatuses) {
                System.out.println("Got a track limitation notice:" + numberOfLimitedStatuses);
            }
    
            @Override
            public void onScrubGeo(long userId, long upToStatusId) {
                System.out.println("Got scrub_geo event userId:" + userId + " upToStatusId:" + upToStatusId);
            }
            ...

    6. 如何提速

    api都是有访问次数限制的,twitter中不少都是以15分钟为单位的。为了爬取能达到一定的速度,我申请了50个app,只要pc给力,那么我就有50倍于单app的速度了。

    那么我是单线程轮流用50个app还是50个线程一起呢?显然50个线程不可行,通常20个线程以上的时候花费在线程同步上的时间就很可观了,并且我们写的是爬虫,50个线程同时写数据库会严重拖慢速度。那么单线程呢?考虑到每个app用完其访问次数是需要一定时间的,特别要是网络状况不好的话次数用完可能会花费数分钟,那么15分钟显然无法让每个app都能访问api,造成了浪费。

    所以我选择了线程池。IO密集型任务,一般将线程数设置为cpu的核数的两倍。同时设置两个队列,分别供各个线程读取数据和写数据。n个线程同时跑爬虫,再分一个线程出来维护那两个队列。框架如下:

    好了,到这里应该能写twitter的api爬虫了。剩下的就是阅读各个api繁琐的文档,以及和各种bug搏斗的时间了╥﹏╥

  • 相关阅读:
    局部测试用例,日常笔记
    软件测试工程师素养(日常笔记)
    Java控件(日常笔记)
    开发大体流程
    sort学习 LeetCode #406 Queue Reconstruction by Height
    MySQL 变量
    [转帖]查看结构体成员的大小和偏移地址的方法
    [转帖]SQL99
    static静态类 静态函数 静态字段
    默认构造函数
  • 原文地址:https://www.cnblogs.com/zhangxiaolei521/p/5962055.html
Copyright © 2020-2023  润新知