Sugree

Main menu

  • About
    • Self
  • Project
    • GT200
    • GeoPin
    • Mitter
    • Red Mob
    • Thairath Breaking News
    • 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)
by sourcode (not verified) on Thu, 07/10/2008 - 01:57 #358

Great work, my master.

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

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

:)

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

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

  • reply
by sugree on Sat, 07/12/2008 - 03:15 #364

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

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

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

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

  • reply
by sugree on Sat, 07/12/2008 - 03:15 #363

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

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

Work great on my hardy.

  • reply

Post new comment

The content of this field is kept private and will not be shown publicly.
Input format
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockcode> <pre>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <html>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <html>. Beside the tag style "<foo>" it is also possible to use "[foo]".
  • You can use Markdown syntax to format and style the text. Also see and Markdown Extra for tables, footnotes, and more.
  • Twitter-style @usersnames are linked to their Twitter account pages.
  • Twitter-style #hashtags are linked to search.twitter.com.

More information about formatting options

Popular Tags

Android BarCamp BarCampBangkok BarCampBangkok2 Book Django Drupal Education Family Google Hardware Hardy Health Interview 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