yegle做过一个同步twitter到人人网状态的PHP脚本,但要求有点高——必须有php-cli组件,估计大多数虚拟主机都没有。Shellex又做了一个用GAE实现的版本,这个可用性高一点,不过他的原版需要webpy和simplejson,需要上传很多东西,而且拼写有错。我改了一下,直接引用django里面的simplejson,再用webapp替换webpy,这样只需要一个文件就能实现了。
  纪念冯正虎成功回国特别更新:Retweet一并同步。
  脚本文件twitter2renren.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python2.6
#coding=utf8
 
import Cookie,urllib
from django.utils import simplejson
from google.appengine.api import urlfetch
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
 
renren_usr = '你的人人网用户名'
renren_passwd = '人人网密码'
twitter_usr = '推特用户名'
twitter_passwd = '推特密码'
last_non_sync_tweet = '最后一条不需要同步的tweet的id,比如:8726641859'
last_non_sync_retweet = '8883341324'
 
cookie_buf = Cookie.SimpleCookie();
 
class Record(db.Model):
	#key is twitter_usr
	last_tweet = db.StringProperty(required=True)
	last_retweet = db.StringProperty(required=True)
 
def make_cookie_header(cookie):
	ret = ''
	for v in cookie.values():
		ret += '%s=%s;' % (v.key, v.value)
	return ret
 
def get_tweets (usr, passwd):
	record = Record.get_or_insert(twitter_usr, last_tweet=last_non_sync_tweet, last_retweet=last_non_sync_retweet)
	new_timeline = []
	timeline_uri = 'http://%s:%s@twitter.com/statuses/user_timeline.json?count=10&since_id=%s' % (usr, passwd, record.last_tweet)
	timeline = simplejson.loads(urllib.urlopen(timeline_uri).read())
	retweets_uri = 'http://%s:%s@api.twitter.com/1/statuses/retweeted_by_me.json?count=10&since_id=%s' % (usr, passwd, record.last_retweet)
	retweets = simplejson.loads(urllib.urlopen(retweets_uri).read())
	if len(timeline) != 0:
		record.last_tweet = str(timeline[0]['id'])
	if len(retweets) != 0:
		record.last_retweet = str(retweets[0]['id'])
	record.put()
	for tweet in timeline:
		if tweet['text'][0] != '@' :
			new_timeline.append(tweet['text'].encode('utf8'))
	for tweet in retweets:
		new_timeline.append(tweet['text'].encode('utf8'))
	return new_timeline
 
def login2renren():
	verify_url = 'http://passport.renren.com/PLogin.do'
	verify_data= urllib.urlencode({
		'domain':'renren.com',
		'email':  renren_usr,
		'password': renren_passwd,
		'origURL':'http://home.renren.com/Home.do',
	})
	result = urlfetch.fetch(
		url=verify_url,
		headers={
			'Cookie':make_cookie_header(cookie_buf),
			'Content-Type': 'application/x-www-form-urlencoded',
			'user-agent':'Mozilla/5.0 (Linux; U; Linux i686; en-US) Gecko/20100115 Firefox/3.6',
		},
		method=urlfetch.POST,
		payload=verify_data,
		follow_redirects = False,
	)
	return result
 
def do_redirect(url, cookie):
	result = urlfetch.fetch(
		url=url,
		headers={
			'Cookie':make_cookie_header(cookie),
			'Content-Type': 'application/x-www-form-urlencoded',
			'user-agent':'Mozilla/5.0 (Linux; U; Linux i686; en-US) Gecko/20100115 Firefox/3.6',
		},
		method=urlfetch.GET,
		follow_redirects = False,
	)
	return result
 
def send_status(status, cookie):
	status_url = 'http://status.renren.com/doing/update.do'
	status_data = urllib.urlencode({
		'c': status,
		'raw': status,
		'isAtHome': 0,
	})
	result = urlfetch.fetch(
		url=status_url,
		headers={
			'Cookie':make_cookie_header(cookie),
			'Content-Type': 'application/x-www-form-urlencoded',
			'user-agent':'Mozilla/5.0 (Linux; U; Linux i686; en-US) Gecko/20100115 Firefox/3.6',
			'Referer': 'http://status.renren.com/ajaxproxy.htm'
		},
		method=urlfetch.POST,
		payload=status_data,
	)
	return result
 
class sync(webapp.RequestHandler):
	def get(self):
		global cookie_buf
		#get timeline
		timeline = get_tweets(twitter_usr, twitter_passwd)
		if len(timeline) == 0:
			return 'no tweets to sync.'
		#login to renren
		result = login2renren()
		cookie_buf = Cookie.SimpleCookie(result.headers.get('set-cookie', ''));
		callback_url = result.headers.get('location','xx');
		result = do_redirect(callback_url, cookie_buf)
		cookie_buf = Cookie.SimpleCookie(result.headers.get('set-cookie', ''))
		#post status
		for tweet in timeline:
			result = send_status(tweet, cookie_buf)
		return 'ok'
 
application = webapp.WSGIApplication([('/twitter2renren', sync)])
 
if __name__ == "__main__":
	run_wsgi_app(application)

  配置文件cron.yaml,每5分钟触发一次:

?Download cron.yaml
1
2
3
4
cron:
- description: twitter2renren
  url: /twitter2renren
  schedule: every 5 minutes

  配置文件app.yaml,限制只有管理员才能访问/twitter2renren:

?Download app.yaml
1
2
3
4
5
6
7
8
9
application: 你的app名字
version: 8
runtime: python
api_version: 1
 
handlers:
- url: /twitter2renren
  script: twitter2renren.py
  login: admin

  另:前天刚拿到一个SAE的帐号,不知道能干点什么用……有谁知道的,请悄悄告诉我……