Tag Archive for 'php'

Twitter2Renren PHP同步脚本(20100828更新)

又更新了一下,使用m.renren.com进行状态发布

脚本名称正式定为twitter2renren.php

使用方法详见这篇日志

代码:

< ?php
 
//
//twitter2renren.php
//By @yegle, yegle.net
//Licensed under CC by-nc-sa
//Version:20100828
//
 
$file = '/home/yegle/.twitter2renren';
$cookie_file = '/home/yegle/.twitter2renren.cookie';
$twitter_username = '';
$twitter_pwd = '';
$hashtag = '';
$renren_username = '';
$renren_password = '';
 
//配置完毕,请停止编辑文件!
if(file_exists($file)){
    $lastid = intval(file_get_contents($file));
}
else{
    touch($file);
    $lastid = 0;
}
 
 
$timeline_url = 'http://'.$twitter_username.':'.$twitter_pwd.'@twitter.com/statuses/user_timeline.rss?count=200';
if($lastid!==0) $timeline_url.='&since_id='.$lastid;
 
 
$timeline = file_get_contents($timeline_url);
 
$obj = simplexml_load_string($timeline);
 
$items = $obj->channel->item;
if(empty($items)){
    echo "no newer tweet\n";
    exit();
}
if(sizeof($items)==1){
    $new_id = preg_replace('/.*\/([0-9]*)$/','$1',strval($items->link));
}
else{
    $new_id = preg_replace('/.*\/([0-9]*)$/','$1',strval($items[0]->link));
}
if($new_id == ''){
    echo "error\n";
    exit();
}
file_put_contents($file,$new_id);
$post_arr = array();
foreach($items as $tweet){
    $text = substr($tweet->title,strlen($twitter_username)+2);
    if(strpos($text,'@')!==0 && ( empty($hashtag) || strpos($text,$hashtag)!==FALSE)){
        $text = str_replace("RT: @","转自",$text);
         $post_arr[] = $text.' [twitter]';
    }
}
 
if(empty($post_arr)){
    echo "no need.\n";
    exit();
}
 
$post_arr = array_reverse($post_arr);
 
foreach($post_arr as $item){
    $post = 'sour=home&status='.urlencode($item).'&update=发布';
 
    $renren_login = "http://3g.renren.com/login.do?fx=0&autoLogin=true";
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_file);
    curl_setopt($ch,CURLOPT_URL,$renren_login);
    curl_setopt($ch,CURLOPT_POST,TRUE);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,TRUE);
    curl_setopt($ch,CURLOPT_POSTFIELDS,'email='.$renren_username.'&password='.$renren_password.'&login=登录');
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
    #curl_setopt($ch,CURLOPT_VERBOSE,TRUE);
    $str = curl_exec($ch);
    curl_close($ch);
    $pattern = '/action="([^"]*)"/';
    preg_match($pattern,$str,$matches);
 
 
    $ch = curl_init($matches[1]);
    curl_setopt($ch,CURLOPT_POST,TRUE);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
    curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_file);
    //curl_setopt($ch,CURLOPT_FOLLOWLOCATION,TRUE);
    //curl_setopt($ch,CURLOPT_REFERER,'http://status.renren.com/ajaxproxy.htm');
    $ret = curl_exec($ch);
    curl_close($ch);
}
?>

使用PHP进行HTTP重定向

在Google里搜“PHP 重定向”,这篇日志的排名在第四。但是这篇写得实在太烂了…重写一篇…

什么是HTTP重定向?

当你访问www.yegle.net时,地址栏的地址会自动变成yegle.net。当你访问ye.gl的时候,地址栏的地址会变成yegle.net。这就是HTTP重定向

一个HTTP请求,返回的HTTP Response Header里,第一行是HTTP的状态码。正常情况下,HTTP请求返回的状态码是200 OK。
正常的HTTP请求,返回200 OK:

< HTTP/1.1 200 OK
< Date: Fri, 16 Jul 2010 11:21:10 GMT
< Server: Apache
< X-Powered-By: PHP/5.2.4-2ubuntu5.10
< Set-Cookie: PHPSESSID=7f86ed2e5a4750275e98971773ac88ab; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Set-Cookie: wassup=ZjVjMWExMjZjNmIxNzU1NDBhZjU0MmM5MzhmYjllZDQ6OjEyNzkyODE5NzE6Ojo6MjAwMTozODg6ZjAwMDo6ZTZmOjoyMDAxOjM4ODpmMDAwOjplNmY%253D; expires=Fri, 16-Jul-2010 12:11:11 GMT; path=/
< X-Pingback: http://yegle.net/xmlrpc.php
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<

其他的比较知名的还有例如:

  • 404 Not Found
  • 301 Moved Permanently
  • 302 Found
  • 500 Internal Server Error

HTTP重定向就是通过301和302两种状态码来实现的。

302是临时重定向的意思。表示被访问页面因为各种需要被临时跳转到其他页面。具体的例子是访问 http://yegle.net/recursion.php

< HTTP/1.1 302 Found
< Date: Fri, 16 Jul 2010 11:26:48 GMT
< Server: Apache
< X-Powered-By: PHP/5.2.4-2ubuntu5.10
< Location: http://yegle.net/recursion.php
< Cache-Control: max-age=600
< Expires: Fri, 16 Jul 2010 11:36:48 GMT
< Vary: Accept-Encoding
< Content-Length: 0
< Content-Type: text/html
<

浏览器在收到302 Found的状态码之后会在返回的HTTP Response Header中查找Location字段,然后访问对应地址。在这个例子中,浏览器就会访问 http://yegle.net/recursion.php (嗯这是一个递归,你懂的…)

301是永久重定向。这样的例子很好找。例如 http://google.com

< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Date: Fri, 16 Jul 2010 11:29:07 GMT
< Expires: Sun, 15 Aug 2010 11:29:07 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 219
< X-XSS-Protection: 1; mode=block
<

同样,浏览器在发现301的状态码之后会查找Location字段,然后访问那个地址。

Location字段的格式很随意,既可以是绝对地址,也可以是相对地址,还可以是相对根目录的地址。以下Location字段都是合法的:

Location: http://yegle.net/
Location: /test/index.php
Location: index.php
Location: ../index.php

301重定向和302重定向在SEO以及缓存上是有非常大区别的。

对于SEO也就是搜索引擎优化,一个页面302重定向到另一个页面,新页面的PageRank不会受原页面影响。而一个页面301重定向到另一个页面,原页面的PageRank会被传递到新页面。所以对于一个网站进行域名转换,最好的方法就是使用301重定向,在经过一段时间之后可以不损失PR地将全站转移到新域名下。

对于HTTP代理服务器例如squid来说,如果一个页面是302重定向到新页面并且没有指定Expire HTTP头,squid将不缓存这个信息,也就是说每次用户通过代理请求时都会重新获取一遍。而对于301重定向,squid可以将结果缓存以便快速响应下一个请求相同页面的用户。

PHP里的302重定向非常简单,只要在返回的HTTP Response Header里添加Location字段,PHP将自动返回302状态码。例如:

< ?php
header("Location: http://yegle.net/recursion.php");
?>

这段代码将自动重定向到http://yegle.net/recursion.php

而301重定向则稍微有点复杂,需要直接将301状态码用header函数返回给用户。例如:

< ?php
    header( "HTTP/1.1 301 Moved Permanently" );
    header( "Location: http://yegle.net/" );
?>

注意的是,跳转不是在收到response header的时候马上进行,也就是说页面的剩余内容会被下载来之后浏览器才会跳转。新手常犯的一个错误是,在逻辑判断时对符合条件的情况进行header跳转之后,忘了在之后加上exit(),导致错误。例如,用user_login()判断用户是否进行了登录,如果未登录则跳转到登录页面。代码如下:

if(!user_login()){
    header("Location:login.php");
}
//display contents for login users.

这里,容易以为header之后这段代码就结束了,没有在header之后使用exit()。后面的代码继续被执行,导致未登录用户看到了已登录用户才能看到的内容。

PHP cURL代码举例

上次贴出来的twitter同步到人人的代码,很多人留言说看不懂。其实这个代码从总体上说还是比较简单的,可能大家对curl相关函数不太了解导致抱怨说看不懂。这里写篇简单的日志介绍一下curl的使用。

注意:如果你需要深入学习,请在线查看php.net的文档,本文仅仅是对不了解PHP curl函数族的用户的入门简介。代码没有经过严格检查,如有错误请留言指出。同样,全文及以下代码以CC by-nc-sa释出,转载请注明出处。
Continue reading ‘PHP cURL代码举例’

twitter同步到renren的php脚本

声明:脚本以CC by-nc-sa协议公布,如需转载请给出原文链接并保留脚本头部的版权声明。

声明:本人不对可能发生的您的renren.com好友被刷屏、脚本错误反复刷屏、您的好友解除与你的好友关系、您的renren.com帐号被举报等等任何不良后果负责~

100129:修正脚本的bug

网上已经有一个twitter2renren的同步网站了,地址在这里:http://twitter2renren.appspot.com/
问题有两个,一个是据说现在已经无法同步了,另一个是这个网站需要输入twitter用户名密码,不支持OAuth,这让我很不放心。于是决定自己写个脚本。

自己动手丰衣足食,不过也有问题,一是一般只用于解决自己的问题,其他人可能还需要修改才能用,二是一般都是无比quick and dirty,懒得写注释和注意排版。这次这个代码好像好多人想用,所以已经尽量考虑比较多的特殊情况,排版也稍微好看一点了……

使用说明:
根据代码中的提示,修改几个变量的值
然后尝试运行一遍脚本,如果没有报错的话,你会看到最近的推显示在屏幕上。这是转发twitter到renren.com后根据renren返回的json解码得到的信息。
根据你执行脚本时的速度选择crontab的时间间隔。我这里选的是5分钟。执行crontab -e
添加以下代码:

*/5 * * * * /path/to/twitter2renren.php 2>&1 >>/path/to/logfile

Done!

以下为代码:

< ?php
 
//
//twitter2renren.php
//By @yegle, yegle.net
//Licensed under CC by-nc-sa
//
 
$file = '用于记录你最后一次同步tweet id的文件路径。注意不要删除并让脚本能读取!';
$cookie_file = '保留curl模拟登陆renren.com的cookie文件路径。';
$name_pwd = '你的twitter用户名密码。格式为:yourusername:yourpassword';
$hashtag = '如果你希望在你的推里包含特殊字符串时才转过去,请设置该变量,否则只转发不是以@开头的推';
$renren_username = 'renren.com登录用户名';
$renren_password = 'renren.com登录密码';
 
//配置完毕,请停止编辑文件!
//That's it!Stop editing anything below unless you know what you are doing!
if(file_exists($file)){
    $lastid = intval(file_get_contents($file));
}
else{
    touch($file);
    $lastid = 0;
}
 
 
$timeline_url = 'http://'.$name_pwd.'@twitter.com/statuses/user_timeline.json?count=200';
if($lastid!==0) $timeline_url.='&since_id='.$lastid;
 
 
$timeline = file_get_contents($timeline_url);
$arr = json_decode($timeline,TRUE);
if(empty($arr)) exit();
$new_id = $arr[0]['id'];
if($new_id == '') exit();
file_put_contents($file,$new_id);
$post_arr = array();
foreach($arr as $tweet){
    if(strpos($tweet['text'],'@')!==0){
        if($hashtag!=='' && strpos($tweet['text'],$hashtag)!==FALSE){
            $post_arr[] = $tweet['text'].' [twitter]';
        }
    }
}
 
 
$post_arr = array_reverse($post_arr);
 
$renren_login = 'http://passport.renren.com/PLogin.do';
$ch = curl_init($renren_login);
curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_file);
curl_setopt($ch,CURLOPT_POST,TRUE);
curl_setopt($ch,CURLOPT_FOLLOWLOCATION,TRUE);
curl_setopt($ch,CURLOPT_POSTFIELDS,'email='.$renren_username.'&password='.$renren_password.'&autoLogin=true&origURL=http://www.renren.com/Home.do&domain=renren.com');
curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
curl_exec($ch);
curl_close($ch);
 
$renren_status = 'http://status.renren.com/doing/update.do';
foreach($post_arr as $item){
    $post = 'c='.urlencode($item).'&raw='.urlencode($item).'&isAtHome=0';
 
    $ch = curl_init($renren_status);
    curl_setopt($ch,CURLOPT_POST,TRUE);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$post);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
    curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_file);
    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,TRUE);
    curl_setopt($ch,CURLOPT_REFERER,'http://status.renren.com/ajaxproxy.htm');
    $ret = curl_exec($ch);
    curl_close($ch);
    $ret = json_decode($ret,TRUE);
    echo $ret['msg']."\n";
}
 
?>

使用tweetr架设twitter api proxy

twitter被墙了

估计很多人知道了http://nest.onedd.net/api这个twitter api proxy,在某些支持twitter api地址更换的软件(例如twitterfoxspaz以及symbian s60上的gravity),使用这个api proxy即可翻墙继续使用,和用穿墙代理以及修改hosts之类的方式比有非常明显的优势。

但是birdnest这个项目需要在Google App Engine上架设,众所周知GFW对GAE一直虎视眈眈,在GAE上架设twitter api proxy各种不靠谱。而我自己有php环境的虚拟主机空间,所以我一直在找一个php架设twitter api proxy的办法。

昨天经过@paveo的提醒,知道了tweetr这个项目。折腾半天后终于搞定了php环境下twitter api proxy的架设。

如何架设的办法在tweetr项目主页的wiki上有说明,英文过关的同学请自行阅读原文,其他同学请看本人的翻译:

环境需求:

>=PHP5

PHP包括curl支持

允许修改.htaccess文件

(译注:绝大多数虚拟主机空间都满足以上要求)

安装指南:

1、下载解压tweetr_php_proxyXXXX.zip,将其中的proxy/文件夹放到web目录下任意位置

2、这条请自行看原文,似乎是说,在flex程序里使用这个twitter api proxy,并且程序和api proxy不在同一域,需要将解压得到的crossdomain.xml放在api proxy所在域的web根目录下。这条基本无关主题,请无视……

3、修改index.php,将其中的$twitterOptions['baseURL']修改为你的proxy文件夹相对web根的路径。例如你将proxy文件夹重命名为twitterapi放在http://yegle.net/twitter/twitterapi下,这里就填写’/twitter/twitterapi’

=========================分割线

安装完实际使用中发现twitterfox和spaz都提示cannot authencation,看了一下代码,原来是部分请求没有发送验证用的用户名密码,猜测是因为这个api proxy本身只是为了跨域“读”twitter上的数据方便,没有考虑到需要“写”twitter数据。更改Tweetr.php,修改function parseRequest其中的一部分,具体位置在94行左右。

在其中加入2行:

strpos($this->url['path'], “statuses/replies.”) != false ||

strpos($this->url['path'], “account/verify_credentials.”) != false ||

即可

PS.这里的strpos(blablabla)!=false,双重否定太发指了!还有互相之间的或关系……各种逻辑混乱……

PS2.不要直接复制粘贴代码……wordpress会把双引号和单引号转换成其他字符……谁能告诉我有什么简单的在wordpress里粘贴代码的方法?

php识别Google的爬虫

给byrbt稍微加点SEO,遇到一个问题是让google可以访问一些原本必须登录之后才能访问的页面。

google了一个晚上无果……这里有一个帖子从来没有人回答过……其他地方找到的方法就是用UA来识别google bot

参考了谷歌中文网站管理员博客上的一篇日志这个帖子写了一个函数判断是否为googlebot

懒得排版了……

function isgooglebot(){
$ua=strtolower($_SERVER['HTTP_USER_AGENT']);
$ip=$_SERVER['REMOTE_ADDR'];
if(strpos($ua,"googlebot")!==false){
$hostname=gethostbyaddr($ip);
if(strpos($hostname,"googlebot.com") !==false ){
$ip_reversed=gethostbyname($hostname);
if($ip==$ip_reversed){
return true;
}else return false;
}else return false;
}else return false;
}

BTW:我依稀记得google提供了一个网页,提交用户名密码以及对应的字段名,google可以自己post用户名密码来完成登录再抓取需要登录才能看到的网页……谁知道这个页面在哪……

使用PHP重定向网页

本网站本来曾经一个网页代理但是由于流量取消一直知道为什么这个网页代理为什么带来这么流量后来发现这个页面知道原因居然迅雷…… Continue reading ‘使用PHP重定向网页’