@shellex说: 对对,他们上辈子都是折翼的新奥尔良鸡翅

Pages

Topics

随便看看

路边社评论员

  • Keith:
    还能用不. »
  • deepblue:
    测试一下浏览器和系统 »
  • abettor:
    “就和CPU特权级别一样”——这的哥难道是Linus的表弟?! »
  • 董英男:
    为什么总提示确认是相册首页呢 到底哪个才是相册首页啊 »
  • kendisk:
    作为一个轻度Linuxer,刚分手后,感觉木有鸭梨。 »
  • MS IE:
    THIS SITE REALLY SUCK! »
  • Alex:
    gnome-women... »
  • liangsuilong:
    GNOME 自己也有鼓励女性参与项目的计划啊.. »
  • infinte:
    对不起,你的“解ban”版本算得有点问题,可以下(9)pp4 测试。ACID3可有95分啊……另外同... »
  • Alex:
    »
  • Randee Saadat:
    Glad you solved your problem, but what is your que... »
  • LinuxRock:
    没想到你也有一台和我一样的破机子......还好现在高三没怎么用,受不了它的发热量.. »

用GAE同步推特到人人网状态

Google App Engine
事情是这样的。死狐狸@yegle做了个脚本,专门用来刷人人网上各位同学的屏幕。Shellex很赞赏这样的精神,但是Shellex不能整天开着Linux跑crontab吧。

而且Shellex也不是@yegle这样的土豪,买个VPS上面装了虚拟的私人网大发国难财,也不像@showfom那样的土豪,买个VPS在上面跑5个bash。唉唉,穷人。

为了达到去人人网恶心各位同学、增加Shellex的上镜率、提高Shellex的知名度的目的,Shellex在GAE的第一次就献给了这个脚本。

这个东西用到了webpy(居然用到了webpy!我坦白!Shellex当时想挖坑,但是考虑Shellex的人身安全还是不挖为妙…),其实没必要的哈,但是无所谓嘛,拿出来就好了。

写得有点乱七八糟的,见谅见谅,这是code.py:

#!/usr/bin/env python2.6
#coding=utf8
import web
import Cookie,urllib
import simplejson as json

from google.appengine.api import urlfetch
from setting import app
from google.appengine.ext import db
from google.appengine.api import users

renren_usr = '你的人人网用户名'
renren_passwd = '人人网密码'
twitter_usr = '推特用户名'
twitter_passwd = '推特密码'

cookie_buf = Cookie.SimpleCookie();

class LastTweetRecord(db.Model):
    id = db.StringProperty(multiline=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):
    last_tweet_id = 0
    last_tweet_record = None
    last_tweet_records = db.GqlQuery('SELECT * FROM LastTweetRecord');
    for record in last_tweet_records:
        try:
            last_tweet_id = int(record.id)
            last_tweet_record = record
        except Exception, e:
            last_tweet_id = 1

    if last_tweet_records.count() == 0:
        last_tweet_id = 1
        last_tweet_record = LastTweetRecord()
        last_tweet_record.put()

    new_timeline = []
    timeline_uri = 'http://%s:%s@twitter.com/statuses/user_timeline.json?count=100&since_id=%d' % (usr, passwd, last_tweet_id)
    timeline = urllib.urlopen(timeline_uri).read();

    timeline = json.loads(timeline)

    if len(timeline) == 0:
        return []
    new_id = timeline[0]['id']
    if new_id == '' :
        return []

    last_tweet_record.id = str(new_id)
    db.put(last_tweet_record)

    for tweet in timeline:
        if tweet['text'][0] != '@' :
            new_timeline.append((tweet['text'].encode('utf8')+' via 唧唧'));
    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) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.4.2.80 Safari/525.13',},
        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) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.4.2.80 Safari/525.13',},
        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) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.4.2.80 Safari/525.13',
            'Referer': 'http://status.renren.com/ajaxproxy.htm'
        },
        method=urlfetch.POST,
        payload=status_data,
        )
    return result

class sync:
    def GET(s):
        global cookie_buf
    #get timeline
        timeline = get_tweets(twitter_usr, twitter_passwd)
        if len(timeline) == 0:
            return 'no tweet 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', ''))
        for tweet in timeline:
            result = send_status(tweet, cookie_buf)
        return 'ok'

if __name__ == "__main__":
    app.cgirun();
    #app.run();

然后是设置,为了防止被misuse,建议把url改得奇怪一些:

import web

urls = (
    '/task/sync', 'code.sync',
    )
app = web.application (urls, globals())

接下来是cron.yaml,每5分钟触发一次:

cron:
- description: every 5 minutes
  url: /task/sync
  schedule: every 5 minutes

接下来是app.yaml:

application: 你的app名字
version: 6
runtime: python
api_version: 1

handlers:
- url: /.*
  script: code.py

对了,如果需要技术支持的话,直接找我就好,5金一人,童叟无欺。

  1. On December 22, 2009 at 9:59 pm
    shellex: Google Chrome 4.0.249.11 / Linux

    搞了两天才出来,因为对gae不熟悉,urllib2的支持有限,所以只能fetchurl来提取cookies; 最囧的是版本…版本…今天捣鼓了一个下午才发现我一直在错误的version 2上纠结…而不是正确的version 6…

  2. On December 22, 2009 at 10:04 pm
    pjq: Mozilla 1.9.1.4 / Gentoo Linux

    这招确实狠,发多了,应该会招来很多人的反感,偶尔发发,应该还不错。

  3. On December 22, 2009 at 10:19 pm
    alswl: Mozilla Firefox 3.5.6 / Windows XP

    好东西啊,Mark…

  4. On December 23, 2009 at 1:36 am
    Black-Xstar: Internet Explorer 7.0 / Windows 7

    围观土豪

  5. On December 23, 2009 at 11:14 pm
    flashclouds: Google Chrome 4.0.249.30 / Linux

    非常棒,请问你是如何尝试出这种方法的呢?

    我在本地能个取得cookie,但是在gae上就取不到。用了你的方法终于能在gae上取到了。请问,你的思路是如何来的?是抓包分析,然后模拟整个过程吗?

  6. On December 24, 2009 at 7:35 am
    WindyWinter: Mozilla 1.9.1.7pre / Ubuntu Linux

    yegle明明是在发民难财。

  7. On December 24, 2009 at 2:00 pm
    shellex: Google Chrome 4.0.249.11 / Linux

    @flashclouds,
    额,用urllib2+cookie得不到cookies的。
    因为在GAE环境下,urllib2的功能是通过urlfetch来实现的。
    而cookies相关的能力貌似没法正常工作。
    所以得用urlfetch手工提取HTTP头部set-cookies的内容

  8. On December 24, 2009 at 5:07 pm
    liufeng: Google Chrome 4.0.249.43 / Mac OS X

    cody.py里面的“from setting import app” 这一行中的setting是什么啊?名字太普通了我也没搜到,加上去后在GAE中会提示找不到,我把它注释到了后却正常,也没看出有什么不同来。

  9. On December 24, 2009 at 5:45 pm
    flashclouds: Google Chrome 4.0.249.30 / Linux

    我当时在gae上用urllib失败后,也尝试了urlfetch结果也失败了,得到的cookie为空,看你的代码里面登录成功之后进行了重定向操作,然后就取得了cookie:
    do_redirect(callback_url, cookie_buf)

    我比较奇怪的是为什么我在本地不用重定向就能取得cookie,到了gae之后就需要程序自己来重定向呢?

    是不是urllib能够在本地自己进行重定向啊,多谢,多谢!!

  10. On December 24, 2009 at 8:26 pm
    shellex: Google Chrome 4.0.249.11 / Linux

    @liufeng,
    shellex在文章中把setting翻译成“设置”了..

  11. On December 25, 2009 at 3:19 am
    liufeng: Google Chrome 4.0.249.43 / Mac OS X

    @shellex,

    原来如此。不知道能不能把tweet-archive发送到日志上呢,这样子太水了。手机版的人人好像有点门。

  12. On December 25, 2009 at 9:55 pm
    pjq: Mozilla 1.9.1.4 / Gentoo Linux

    上传后,不能运行,好像是提示不能 import web和simplejson.
    在本地也是同样的提示,请问需要另外怎样的配置吗,对python和gae都不太懂。

  13. On December 26, 2009 at 12:59 pm
    pjq: Mozilla 1.9.1.4 / Gentoo Linux

    @pjq,
    弄好了,还要把webpy和simplejson上传上去。

  14. On January 4, 2010 at 11:08 am
    qubic: Google Chrome 4.0.289.0 / Linux

    改url那段放到哪个文件下

  15. On February 6, 2010 at 10:39 pm
    hzq: Google Chrome 4.0.302.2 / Windows XP

    对我这样的人并不是完整的攻略,放弃了。

  16. On February 20, 2010 at 6:11 pm
    小米: Mozilla Firefox 3.6 / Windows XP

    冲着这个教程,先订阅了你再说~~

  17. On July 12, 2010 at 5:53 pm
    sunnylqm: Mozilla Firefox 3.6.2 / Windows 7

    LZ你好
    我最近在做一个同步qq签名到人人网状态的
    基于GAE for java
    原先考虑用XMPP更新状态,后来发现GAE的XMPP API几乎是个摆设,于是还是用传统的urlfetch,虽然本地调试一点问题都没有,可是上传后登录就失败
    怀疑GAE的java SDK和实际实现中对于redirect和cookie的处理出入很大 本地可以用wireshark慢慢抓包观察 远程的就束手无策了
    LZ有兴趣帮忙的话 愿意奉上50G(汗,或者5QB…)
    QQ34731408 先谢谢了

  18. On July 13, 2010 at 11:03 am
    shellex: Google Chrome 6.0.427.0 / Linux

    @sunnylqm 呃,那个什么,你urlfetch看看返回的报文,打印到页面上,或者在GAE后台里面看。我不知道你说的是登录人人网还是QQ时发生的错误。你看看吧。然后根据具体错误分析。

  19. On July 13, 2010 at 11:13 am
    sunnylqm: Mozilla Firefox 3.6.2 / Windows 7

    通过抓包分析,我发现主要有这样几个问题(javasdk 1.3.5):
    1、httpurlconnection不能连续post…什么意思呢?第一个post登录成功之后,第二个post提交签名数据时,抓包发现虽然设置了setRequestMethod(“POST”),但依然发出的是GET,准确的说,
    HttpURLConnection connection2 = (HttpURLConnection) url2.openConnection(); 对于connection2的所有set方法似乎都不能生效。
    2、在有重定向时需要手动处理cookie,但GAE似乎只能处理单行cookie,像人人网登陆时似乎会多次跳转返回多行set-cookie,GAE的API似乎每次只能get到一行。而且让我困惑的是,即便在本地我手动设置Cookie为”",抓包时发现发出的请求的Cookie仍然有多行(其中包含我设置为”"的那行),这个cookie的处理实在让我摸不着头脑

  20. On July 13, 2010 at 1:58 pm
    sunnylqm: Mozilla Firefox 3.6.2 / Windows 7

    发现问题所在了
    如果触发connection的方法是先调用inputsream的话,会变为只读的GET请求
    如果使用getResponse触发connection的话,对于connection的各种set才会生效

  21. On July 13, 2010 at 3:09 pm
    双引号: Mozilla Firefox 3.6.3 / Windows XP

    传后,不能运行,好像是提示不能 import web和simplejson.
    在本地也是同样的提示,请问需要另外怎样的配置吗,对python和gae都不太懂

  22. On July 14, 2010 at 10:01 am
    shellex: Google Chrome 6.0.427.0 / Linux
  23. On August 28, 2010 at 2:29 am
    Keith: Google Chrome 5.0.375.127 / Mac OS X

    还能用不.

Trackbacks

  1. Tweets that mention 用GAE同步推特到人人网状态 | ShelleX is Not ShelleXtend -- Topsy.com
  2. 梦.:如此短暂
  3. GReader分享到人人脚本 « 这里没有橄榄

Leave a Reply