Sugree

Main menu

  • About
    • Self
  • Project
    • Barcode Generator / Reader
    • GT200
    • GeoPin
    • Mitter
    • Red Mob
    • Thairath Breaking News
    • Twitter Android SDK
    • jibjib
    • microblog-purple
    • English
    • Thai

Following all followers in NokNok

Submitted by sugree on Thu, 07/10/2008 - 00:12
  • NokNok
  • Python
  • Social Network
  • Twitter
  • Thai

สคริปต์ noknok.py เมื่อวันก่อนทำเอาหลายคนกลายเป็นสแปม เพราะพยายามจะเอาไปรันใน cron ยกตัวอย่างเช่น @pruet คราวนี้เลยแก้ตัวใหม่ ใส่ไฟล์คอนฟิกให้อันนึง อย่างน้อยก็เอาไว้เก็บว่าเคย sync ถึงไหนแล้ว และแถมด้วยการติดตามเพื่อนทุกคนของคนที่ต้องการ

เนื่องจาก NokNok ยังไม่มี APIs ผมก็ขี้เกียจทำ regexp สุดท้ายเลยตัดสินใจใช้ XPath ของ lxml ซะเลย ดูเหมือนว่าจะไม่มี lxml บนวินโดส์ ยังไม่รู้จะแก้ปัญหาให้ยังไง คำแนะนำตอนนี้คือ ลงลินุกซ์

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
 
from urllib import urlencode
from urllib2 import urlopen, HTTPCookieProcessor, build_opener, install_opener, Request
import re
import os
import getpass
from optparse import OptionParser
from ConfigParser import ConfigParser
 
import simplejson
 
cookie_processor = HTTPCookieProcessor()
opener = build_opener(cookie_processor)
install_opener(opener)
 
user_agent = 'noknok'
 
def confopt(conf, section, option, default=None):
    try:
        return conf.get(section, option)
    except:
        return default
 
def user_timeline(u, since_id=0):
    url = 'http://twitter.com/statuses/user_timeline/%s.json' % u
    data = {}
    if since_id > 0:
        data['since_id'] = since_id
    req = Request(url,
                  urlencode(data),
                  {'User-Agent': user_agent})
    fd = urlopen(req)
    results = simplejson.loads(fd.read())
    return filter(lambda x: x['id'] > since_id, results)
 
def summize(q, since_id=0):
    url = 'http://summize.com/search.json'
    req = Request(url,
                  urlencode({'q': q, 'since_id': since_id}),
                  {'User-Agent': user_agent})
    fd = urlopen(req)
    results = simplejson.loads(fd.read())['results']
    return results
 
class NokNok:
 
    url = 'http://www.noknok.in.th/'
 
    def __init__(self, username, password):
        self.username = username
        self.password = password
 
    def home(self):
        url = self.url+'myhome'
        fd = urlopen(url)
        fd.read()
 
    def login(self):
        #print 'logging in'
        url = self.url+'login/'
        fd = urlopen(url, urlencode({'username': self.username,
                                     'password': self.password,
                                     'remember_me': '1'}))
        content = fd.read()
        if fd.code != 200:
            print code, content
        #print fd.headers
        #print content
 
    def post(self, msg):
        #print 'posting %s' % msg
        url = self.url+'message/add'
        req = Request(url, urlencode({'msg_update': msg.encode('utf-8')}), {'Referer': self.url+'myhome'})
        fd = urlopen(req)
        content = fd.read()
        #print fd.headers
        #print content
        if fd.code != 200:
            print code, content
 
    def get_followers(self, user=None):
        from lxml import etree as ET
 
        user = user or self.username
        url = self.url+user+'/followers'
        followers = []
        while 1:
            fd = urlopen(url)
            content = fd.read()
            tree = ET.HTML(content.decode('utf-8'))
            node = tree.xpath("//ul[@class='list_friends_follow']")[0]
            for item in node:
                d = {'screen_name': item.findtext('h3'),
                     'links': {}}
                links = item.xpath('./ul/li[3]/span/a')
                for i in links:
                    title = i.attrib['title']
                    if title == u'ติดตาม':
                        d['links']['follow'] = i.attrib['href']
                    elif title == u'บล็อค':
                        d['links']['block'] = i.attrib['href']
                followers.append(d)
            next = tree.xpath("//span[@class='next-page']")[0].find('a')
            if next is None:
                break
 
            url = next.attrib['href']
        return followers
 
def runonce(nok, q, query, since_id=0, cb_save=None):
    try:
        results = query(q, since_id=since_id)
    except Exception, why:
        print why
        results = []
    results.reverse()
    for item in results:
        nok.post(item['text'])
        since_id = item['id']
    if cb_save:
        cb_save(since_id)
    return since_id
 
def run(nok, q, query, since_id=0, interval=30, cb_save=None):
    import time
 
    if since_id == 0:
        since_id = query(q)[0]['id']
    while 1:
        since_id = runonce(nok, q, query, since_id, cb_save)
        time.sleep(interval)
 
class App:
    def __init__(self):
        usage = '''usage: %prog [options] followall|twitteronce|twitterforever
 
Commands:
  followall [screen_name]
  twitteronce
  twitterforever'''
        parser = OptionParser(usage=usage)
        parser.add_option('-c', '--config',
                          default='noknok.cfg', dest='config',
                          help='configuration file')
        self.options, self.args = parser.parse_args()
 
    def run(self):
        if len(self.args) > 0:
            command = self.args[0]
        else:
            command = 'twitterforever'
        method = getattr(self, 'do_%s' % self.args[0])
        if not method:
            print 'unknown command'
            return
 
        self.conf = ConfigParser()
        self.conf.read([self.options.config, 'noknok.cfg', os.path.expanduser('~/.noknok.cfg')])
 
        username = confopt(self.conf, 'noknok', 'username')
        if username is None:
            username = raw_input('noknok user: ')
        password = confopt(self.conf, 'noknok', 'password')
        if password is None:
            password = getpass.getpass('noknok password: ')
        self.nok = NokNok(username, password)
        self.nok.login()
 
        return method()
 
    def do_followall(self):
        if len(self.args) > 1:
            user = self.args[1]
        else:
            user = self.nok.username
        for user in self.nok.get_followers(user):
            if 'follow' in user['links']:
                print 'following %s' % user['screen_name']
                fd = urlopen(user['links']['follow'])
                fd.read()
 
    def do_twitterforever(self):
        q = confopt(self.conf, 'twitter', 'query')
        if q is None:
            q = raw_input('twitter user: ')
        query = confopt(self.conf, 'twitter', 'source', 'user_timeline')
        since_id = int(confopt(self.conf, 'twitter', 'since_id', '0'))
        interval = int(confopt(self.conf, 'twitter', 'interval', '30'))
        run(self.nok, q, eval(query), since_id, interval, self._save_since_id)
 
    def do_twitteronce(self):
        q = confopt(self.conf, 'twitter', 'query')
        if q is None:
            q = raw_input('twitter user: ')
        query = confopt(self.conf, 'twitter', 'source', 'user_timeline')
        since_id = int(confopt(self.conf, 'twitter', 'since_id', '0'))
        runonce(self.nok, q, eval(query), since_id,self._save_since_id)
 
    def _save_since_id(self, since_id):
        self.conf.set('twitter', 'since_id', str(since_id))
        self.conf.write(open(self.options.config, 'w'))
 
if __name__ == '__main__':
    app = App()
    app.run()

ยาวขึ้นเยอะเหมือนกัน คราวนี้ฉลาดขึ้น ควรใช้ไฟล์คอนฟิกให้เป็นประโยชน์ด้วย หน้าตาประมาณนี้

[twitter]
source = user_timeline
since_id = 0
query = sugree
 
[noknok]
username = sugree
password = xxxxxx

ถ้าอยากใช้ summize ก็แก้ตรง source วางไฟล์นี้ไว้ที่เดียวกับ noknok.py หรือจะไว้ที่ ~/.noknok.py ก็ด้ ตอนนี้มี 3 คำสั่ง

python noknok.py twitterforever

อันนี้ทำเหมือนรุ่นเก่า รันไปเรื่อย

python noknok.py twitteronce

จะอ่านรอบเดียว ส่งรอบเดียว

python noknok.py followall

ค้นหาว่าใครที่ติดตามเราแล้วเรายังไม่ได้ติดตามกลับ ก็ติดตามซะ

python noknok.py followall sugree

แบบนี้จะติดตามทุกคนที่ติดตาม sugree กรุณาใช้ด้วยความระวัง

เตือนแล้วนะ_

ว่าแล้วก็เตรียมทำ python-noknok ดีกว่า

Roti (alpha) thinks you may like these:
  • (no links yet)
  • Login to post comments
by sourcode (not verified) on Thu, 07/10/2008 - 01:57 #358

Great work, my master.

  • Login to post comments
by kong (not verified) on Thu, 07/10/2008 - 18:26 #359

Works like a charm on Cygwin (I mean, on Windows)

:)

  • Login to post comments
by mk (not verified) on Thu, 07/10/2008 - 20:08 #360

ตั้งโต๊ะลง linux กันดีกว่า สร้าง factor ให้คนจำต้องใช้แบบนี้เยอะๆ แล้วก็นัดกัน ยกโน้ตบุ๊กมาหักดิบลง linux กันเลย

  • Login to post comments
by sugree on Sat, 07/12/2008 - 03:15 #364

เอา mac มาลงก่อนเลย

  • Login to post comments
by EscRiBiTioNiSt® (not verified) on Fri, 07/11/2008 - 08:56 #361

T_T" copy ไปแปะเลยไม่ได้เหรอ? ลอง copy จากกล่องใหญ่ๆ แล้วมันเปิดไม่ได้.. (ประจำ.. ลองอะไรแล้วได้เรื่องประจำเลย)

อ๊าาาาาาาาาา ทำไม ทำไม

  • Login to post comments
by sugree on Sat, 07/12/2008 - 03:15 #363

ถ้าอ่านแล้วทำตามได้เมื่อไหร่จะให้ประกาศนียบัตร

  • Login to post comments
by jackz (not verified) on Fri, 07/11/2008 - 19:29 #362

Work great on my hardy.

  • Login to post comments

Popular Tags

Android BarCamp BarCampBangkok Book Django Drupal Education Family Google Hardware Hardy Health Interview Intrepid Java jibjib Joke Life microblog-purple OpenOffice.org OpenSource Podcast Python Review SoC Social Network Trip Twitter Ubuntu Weekly Suki
more tags

Powered By

debian
apache
drupal
drupal.in.th
openfreehost
inox
feedburner

© 2007-2008 Sugree Phatanapherom. Creative Commons [Feed Content / Comment]
RoopleTheme