Twitterのフォロワーをmechanizeを使って取得する

Twitterのfollower数の増減を数えたいと思った。最初はapiを使うつもりだったけど、follower数が多いせいかうまくいかなかったので、mechanizeを使ってスクレイピングするスクリプトを書いた。

以下ソース

ソース

#!/usr/bin/env python
#-*-coding:utf-8-*-

import re
import time

import mechanize as mc

from progressbar import *

URL = 'https://twitter.com/'
USERNAME = "USRENAME"
PASSWORD = "PASSWORD"

class FollowersCounter(object):
    def __init__(self, user, password):
        self.followers = []

        self._user = user
        self._password = password
        self._br = mc.Browser()
        
        self._br.set_handle_robots(False)
        #self._br.set_debug_http(True)
        self._br.open(URL)
        self._br.select_form(nr=1)
        self._br["session[username_or_email]"] = self._user
        self._br["session[password]"] = self._password
        self._br["remember_me"] = ["1"]
        self.res = self._br.submit()
        print "HTTP status code: " + str(self.res.code)

        self.num = self._count_followers()
        
    def check(self):
        print 'Followers : ' + str(self.num)
        #pages = (num%20 == 0) and num/20 or num/20+1
        self.pb = Progressbar(self.num)

        p = re.compile(r'<span class="label screenname">.*?</span>')
        p2 = re.compile(r'<.*?>')

        res = self._br.open(URL + "followers")
        body = res.read()
        pgcount = 0
        
        while(True):
            for m in p.finditer(body):
                s = m.group()
                self.followers.append(re.sub(p2, "", s))
            pgcount += 20
             self.pb.progress(pgcount)
                       
            try:
                req = self._br.click_link(text_regex=r"Next .+")
            except mc.LinkNotFoundError:
                break
            
            res = self._br.open(req)
            body = res.read()
            time.sleep(5)
            
        st = set(self.followers)
        if not len(st) == self.num:
            print "Something wrong happened!"

        f = open('following.txt', 'w')    
        for u in st:
            f.write(str(u) + '\n')
            
    def _count_followings(self):
        res = self._br.open(URL + "following")
        body = res.read()
        p = re.compile('<span>You follow \d+ people')
        m = p.search(body).group()
        
        return int(re.search('\d+', m).group())

    def _count_followers(self):
        """
        follower数と実際に取得したユーザ数が違う場合のためのデバッグ用
        """
        res = self._br.open(URL + "followers")
        body = res.read()
        p = re.compile('<span>Your \d+ followers')
        m = p.search(body).group()
        
        return int(re.search('\d+', m).group())
    
if __name__ == '__main__':
    fc = FollowersCounter(USERNAME, PASSWORD)
    fc.check()

プログレスバー

#!/usr/bin/env python
#-*-coding:utf-8-*-

import sys

class Progressbar(object):
    """progressbar on consol
    """

    def __init__(self, finalcount, block_char="*"):
        self.finalcount = finalcount
        self.block = block_char
        self.blockcount = 0
        self.out = sys.stdout
        if not self.finalcount: return
        
        self.out.write('\n------------------- %Progress -------------------1\n')
        self.out.write('    1    2    3    4    5    6    7    8    9    0\n')
        self.out.write('----0----0----0----0----0----0----0----0----0----0\n')

    def progress(self, count):
        count = min(count, self.finalcount)
        if self.finalcount:
            percentcomplete = int(round(100.0*count/self.finalcount))
            if percentcomplete < 1: percentcomplete = 1
        else:
            percentcomplete=100
        blockcount = int(percentcomplete//2)
        if blockcount <= self.blockcount:
            return
        for i in range(self.blockcount, blockcount):
            self.out.write(self.block)
        self.out.flush()
        self.blockcount = blockcount
        if percentcomplete == 100:
            self.out.write('\n')

if __name__ == '__main__':
    from time import sleep

    pb=Progressbar(8, '*')
    for c in range(1,9):
        pb.progress(c)
        sleep(0.2)

一応動くことは動くけど、大したエラー処理をしてないので動作中にフォローorリムーブされると取得漏れが出るみたい。(だけどあまり速く動かしすぎてもtwitterから怒られてしまう) フォロワーが多いと少し完了するまでに時間がかかります。ちなみに、プログレスバーを表示させる部分はPythonクックブックから取りました。

ザックリとしたスクレイピングをするだけならmechanizeは便利ですね。