Loading...

饭否/做啥应用之共同的好友

Filed under: 编程, 网络 — 深柳堂主 @ 2008-11-22 09:00:38 Comments

饭友布丁丁丁提过这样一则饭否应用的创意:找出自己和另外任一饭友之间共同的好友。今天我使用php将其粗略地实现了。步骤如下。

  1. 假设两位饭友分别为ffA和ffB。
  2. 通过饭否API得到ffA的好友列表,保存每个好友的ID至数组friendIDsA中,备用。
  3. 同理,得到ffB的好友列表ID数组friendIDsB中,备用。
  4. 求friendIDsA和friendIDsB的交集,保存至数组friendsList表中。
  5. 输出列表friendsList。

在实现时,具体细节:

  1. 使用GET的方法将需要处理的饭否ID传递给程序,而不是使用对话框、文本框的方式。
  2. 下载饭否好友列表,用到了curl函数。curl作为下载利器,很好用。
  3. 分析、获取好友信息,用到了xpath函数。xpath在xml中快速定位,很好用。另外可参阅《饭否消息解析之从minidom到xpath》一文。
  4. 获取A和B的交集时,使用了array_intersect函数。本函数是求两数组的交集。
  5. 在处理时,遇到“仅对好友公开类型”的饭友,将其略过。
  6. 输出列表时,界面仍然比较粗糙。本人对于网页的框架、CSS都知之甚少,也就不献丑了。

使用方法:先查一下两个人的饭否ID,然后修改下面的链接:
http://iregex.org/fanfou/friends.php?a=zhasm&b=passingby,更换其中的zhasm和passingby为您感兴趣的饭否ID。

另,”做啥”的也做出来了,格式如http://iregex.org/zuosa/friends.php?a=rexxer&b=alex

显示效果:如下图。


  1. Tears


  2. 令糊葱

  3. 如小果

  4. 妖娆男

  5. 流连

  6. 小北Roy

  7. 饭而不否

  8. 蛮子

  9. 如是如来

  10. 撕烤者

  11. 程小秸

  12. 王金牙儿

源代码:

<?php
function getFriendList($id)
{
    $url="http://api.fanfou.com/users/friends.xml?id=".$id; 
    //print $url;
    $ch = curl_init($url); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    $output = curl_exec($ch); 
    curl_close($ch);
    $xml=simplexml_load_string($output);
    $result=$xml->xpath("//id");
    return $result;
}
 
function myGenerate($id)
{
    $url="http://api.fanfou.com/users/show.xml?id=".$id; 
    //print $url;
    $ch = curl_init($url); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    $output = curl_exec($ch); 
    curl_close($ch);
    if ($output=="验证失败")
    {
        return;
    }
    $xml=simplexml_load_string($output);
    $name=$xml->xpath("//user/name");
    $img=$xml->xpath("//profile_image_url"); 
    $line="<li><a href=\"http://fanfou.com/$id\"><img src=\"$img[0][0]\" style=\"margin:0px 10 px 10px; border: 1px solid rgb(255, 255, 255); \"><br />$name[0]</a><br /><br /></li>";
    print $line; 
}
 
function myPrint($list)
{
    print "<ol>";
    foreach ($list as $value) 
    {
        myGenerate($value);
    }
    print "</ol>";
}
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />";
//to ensure the encoding system to be utf-8.
$a=$_GET["a"];
$b=$_GET["b"];
$my=getFriendList($a);
$his=getFriendList($b);
$our=array_intersect($my,$his);
myPrint($our);
?>

有多少人在收听你的广播

Filed under: 编程, 网络 — 深柳堂主 @ 2008-10-21 00:19:11 Comments

MS之前已经引用过一次了,我再不厌其烦地引用一次——

“譬如咱们这次同船的许多人,没有一个认识的。不知道他们的来头,为什么不先不后也乘这条船,以为这次和他们聚在一起是出于偶然。假使咱们熟悉了他们的情形和目的,就知道他们乘这只船并非偶然,和咱们一样有非乘不可的理由。这好像 开无线电。你把针在面上转一圈,听见东一个电台半句京戏,西一个电台半句报告,忽然又是半句外国歌啦,半句昆曲啦,鸡零狗碎,凑在一起,莫名其妙。可是每 一个破碎的片段,在它本电台广播的节目里,有上文下文并非胡闹。你只要认定一个电台听下去,就了解它的意义。我们彼此往来也如此,相知不深的陌生人——”柔嘉打个面积一寸见方的大呵欠。像一切人,鸿渐恨旁人听自己 ” 说话的时候打呵欠,一年来在课堂上变相催眠的经验更增加了他的恨,他立刻闭嘴。柔嘉道歉道:“我累了,你讲下去呢。”鸿渐道:“累了快去睡,我不讲了。”柔嘉怨道:“好好的讲咱们两个人的事,为什么要扯到全船的人,整个人类?”鸿渐恨恨道:“跟你们女人讲话只有讲你们自己,此外什么都不懂!你先去睡罢,我还要坐一会呢。”柔嘉佯佯不睬地走了。鸿渐抽了一支烟,气平下来,开始自觉可笑。

其实大家不论是在twitter,饭否,还是做啥,都像方鸿渐说的那样,都只是一句句支离破碎的电台广播而已。在频繁换台的陌生人耳朵里,随意泛听时,或许会有只言片语引起注意;只有认定你的频道收听下去,才能连贯地读懂你的心脉,理解你的悲欢。今天我的话题就是,在blog上显示你的饭否或“做啥”听众数量。

这本不是我的创意。是前天我无谓中浏览一位饭友的博客时,发现了http://twittercounter.com/提供了这样的服务,能将你在twitter中的followers的数量以图像形式显示出来,例如本人的图片是TwitterCounter for @zhasm。可是我最常用的饭否却没有类似网站提供类似服务。我思考了一下,觉得不太难,自己也可以实现。

实现思路:

  1. 通过现有的饭否API http://api.fanfou.com/users/show.xml?id=zhasm 来获得当前饭否用户的信息,其中的ID就是所要统计的用户的ID,听众数量在followers_count节点中。其结构是:<followers_count>(\d+)</followers_count>。
  2. 使用网页语言(我用的是PHP)来获得该数值,并将其转换成图片。基本要求是即时更新,即,不是只生成当前听众数量统计,当数量有变动时,还能随时更新。
  3. 提供在线的图片输出服务。

由于饭否的API比较完备,第一步没问题;第二步我没有使用php的xml解析函数,而是使用了比较顺手的正则表达式来获取该数值;生成图片的模板,我参考了feedsky的。其三维效果是通过明暗的线条来实现的。为省事,将中文改为英文了。至于在线的图片输出,我慷慨地使用了自己博客所在的cph空间,将网页放在http://zhasm.com/fanfou/里面。效果如图:

饭否听众统计图片使用方法很简单,因为功能也很简单:)。具体如下:

  1. 取得你的饭否ID。如果你的饭否链接是http://fanfou.com/regex,而你的饭否用户名是正泽,则你的ID是regex,而不是正泽。值得一提的是,我写的听众统计功能,暂时还不支持中文ID。
  2. 取得图片。图片位置在
    http://zhasm.com/fanfou?id=regex


    http://iregex.org/fanfou?id=regex
    推荐国内的用户使用前者(zhasm对应cph主机),国外的用户使用后者(iregex.org对应dreamhost主机)。
  3. 您可以在blog中这样调用(请酌情将YourfanfouID换成相应值):
    <a href="http://fanfou.com/YourfanfouID" title="个性提示语,例如hello world,当鼠标移动到链接上时显示的文字" target="_blank">
    <img src="http://zhasm.com/fanfou?id=YourfanfouID" />
    </a>

实现此功能后,我将此消息群发到fanfou、twitter、jiwaide、zuosa、plurk上。zuosa的老大alex发现了我的消息,委托我为zuosa也写一个。

我阅读了zuosa的api文档,发现对应的函数并没有提供followers_count功能;与alex沟通,zuosa两天后就在http://api.zuosa.com/users/show.xml加上了本功能。而我原有的php脚本也无需改动太多,只需要修改两行就能服务于zuosa,一条是api接口,另一条是正则式解析的位置。根据alex要求,将followers修改为粉丝;同时去掉了原来数值的前导0。现在效果如下:

类似,做啥听众统计图片使用方法如下:

  1. 取得你的做啥ID。如果你的做啥链接是http://zuosa.com/rexxer,而你的饭否用户名是zhasm,则你的ID是rexxer,而不是zhasm。值得一提的是,我写的听众统计功能,暂时还不支持中文ID。
  2. 取得图片。图片位置在
    http://zhasm.com/
    zuosa?id=rexxer

    http://iregex.org/zuosa?id=rexxer
    推荐国内的用户使用前者(zhasm对应cph主机),国外的用户使用后者(iregex.org对应dreamhost主机)。
  3. 您可以在blog中这样调用(请酌情将YourZuosaID换成相应值):
    <a href="http://zuosa.com/YourZuosaID" title="个性提示语,例如hello world,当鼠标移动到链接上时显示的文字" target="_blank">
    <img src="http://zhasm.com/zuosa.com?id=YourZuosaID" />
    </a>

目前的不足之处是,不支持中文ID;没有提供更详细的定制功能。还有什么不足之处呢,请留言告之。

2008.10.23更新:
应alex要求,新增一种风格,如图所示:,使用方法不变,图片路径改为http://zhasm.com/zuosa/2?id=YOUR_ZUOSA_ID。

2008.10.27更新:
将alex要求的方式做为默认,格式如,使用方法不变,图片路径改为http://zhasm.com/zuosa?id=YOUR_ZUOSA_ID。

关于饭否消息打包下载的限制以及对于饭否分享功能的建议

Filed under: 编程 — 深柳堂主 @ 2008-07-01 21:48:19 Comments

真是多事之秋。也罢,莫谈国是。说一说饭否得了。

今天与饭否的官方沟通过饭否服务器的限制问题。起因是,本人正在写的饭否应用程序,是①,通过抓取饭否页面;②,使用正则表达式解析所需要内容实现的。最近在读取饭否页面的过程中, 发现读取一定数量的fanfou页面之后,就无法登录fanfou了。今天得到的答复是,在10分钟内抓取不得超过100页。这个确定的答案让我很满意。我不是说,10分钟100页是多是少,而是说,有定量的标准可以参考时,觉得更加有把握。

既然10分钟100页,折合每6秒1页。这个数字还是有些保守。因为我每10秒读取1页连续抓100页时,仍然会被封IP。现在我每下载1页,就sleep(15),居然可以长时间下载。替一位朋友下载了所有的饭否公信和分享,合计300多页,这个过程很顺畅,当然,也很漫长。鉴于饭否消息的特点,第一次抓取的时间,是无法快起来的。但是,一旦第一次已经把之前所有的消息下载过后,再次下载就会很快,只需“同步”一下即可,只下载最新消息,而无需重新下载全部消息。这样就能在本地完整保留所有的饭否消息,从而进行诸如查询、导出、统计之类的操作。

在没有得到饭否官方提供的最大负载数据之前,我是这样变通操作的:被封IP后重启一下ADSL猫,一分钟后即可再次登录饭否。原因是ADSL会重新获得随机IP。当然,现在可以合理地设置抓取间隔,不被封锁,才是更好的选择。

关于打包下载饭否消息的方法,其实不止使用专用程序一条途径。还见过使用其它工具(使用迅雷等批量下载网页,再使用textforever之类的工具析取的。对于这样饭友,我想和您握手。因为,咱们的思路是一样的,都是先下载,再析取。只不过使用的工具不同而已。

本人写的新版抓饭程序何时公布?对不起,暂缓。如果您对脚本感兴趣,我可以把脚本发给您,并告诉您怎么使用。完整的程序需要更长一段时间,包括脚本的完善、数据库操作、界面的更新……等等等等。

打包下载分享的数据库版本还没写出来,原因同上。

对于饭否分享,我有以下2条建议:

  1. 建议“已经删除”和“不公开”这两个属性分开。在批量删除时容易误伤不说,不公开的还有公开的可能,万一原消息主人再度公开,还可以再次下载。
    难度:低。
  2. 建议在分享中加入digg思想。这个意见,拂汗提过一次。我觉得很好。发布一条消息后,每当有人分享一次,该消息的digg计数就++,删除分享一次,该消息的digg计数就–。一个人的popularity权重与所有digg计数来挂钩,从而激励大家多发有意义的言论。同时,该digg计数也给想要删除该消息的主人以参考:当想删除时,会有提示:“该消息已被N个人分享,您真的要删除吗?”
    难度:较高。因为需要涉及原有表的alert操作,手术较大。再加上原有分享消息是否重新计算,等等。

关于本人编写的饭否应用的三言两语

Filed under: 随笔 — 深柳堂主 @ 2008-06-23 06:49:56 Comments
  1. 打包下载全部饭否消息

    该工具只适合下载任何公开消息的人的饭否消息。如果您的消息类型是“仅好友可见”,则程序无法读取您的饭否消息。你可以暂时改变为公开型再抓取自己的消息。

    如果您不想临时公开一下您的消息类型,变通的方法,是在抓取消息时加以验证。(使用cookie:curl -Dcookie.txt -d “loginname=youremail@domain.com&loginpass=*****&auto_login=on&action=login” http://fanfou.com/login,以后只需-b cookie.txt即可:

    curl -bcookie.txt -o#1.html http://fanfou.com/YOURFANFOUID/p.[1-100]

    但是这样抓取的网页,其结构与抓取出来的公开页面略有不同,因为相当于是登录状态,所以有了操作(分享、删除)的选项。这也不要紧。既然知道是哪里有变化,只要把正则表达式修改一下即可。

  2. 关于执行效率

    本程序经过数次改版,其运行效率曾经让我自豪。不过,随着饭否用户的增加,饭否服务器的表现越来越让人感到失望。原来我连续抓取1000页(确实有20000+消息的饭友!)程序依然运行没问题。现在,每当我连续抓取100页,本IP就被饭否给封锁了。在饭否服务器扩容之前,这确实是可以理解的做法。我也不该为了一己之利,对饭否服务器运行杀鸡取卵、涸泽而渔式地滥用。

  3. 本项目暂时搁置,一些程序取消下载。

    编写程序是我的业余爱好,它跟我的专业、现在的工作都毫无关系,我并不以编写程序来谋生。我只把它当成与看球赛、打电玩、练瑜珈一样。确实,它让我的业余生活很丰富多采。

    但是,我的工作、生活,最近发生了一些变化。明天要出个长差;回来面临找住处、搬家等琐事,搬家后能否继续像现在这样方便、便宜地上网,还是未知数。周末的时间,将去学开车,把以前的课时补完,争取一次通过,顺利加入马路杀手的行列。

    总之,可支配的时间是越来越少了。这几个饭否程序,我也想完善之。但是照目前的情况看来,遥遥无期。我曾经在饭否上说,“假老夫数周,则我于饭否、twitter、叽歪、做啥之类的微博客彬彬矣”。不过,这个前提是有自由支配的时间可假,呵呵。

    鉴于以上原因,本人的饭否项目就暂时搁置了。跟饭否抓取相关的程序,会取消下载。但是源码留着,为以后再续前缘留个根苗。

饭否,尚能饭否?

Filed under: 网络 — 深柳堂主 @ 2008-06-07 11:54:06 Comments

有饭友对饭否提出这样的建议,我谈谈我的看法:

作为一名忠诚度很高的饭否用户,……我现在想要的几个功能是(其中有一个以前提过):

  1. 按照发布日期排列的“顺序阅读”按钮;
  2. 针对发布内容的关键字搜索;
  3. “每日最热词”榜单——这个纯粹是为了好玩:统计每天海量文本中出现最多的词。

by StarKnight @ 02:40 2008-06-07

rex的看法:

  1. 按照发布日期排列的“顺序阅读”按钮;

    这是可以实现的,而且也不难。

    直接在饭否网上实现:

    只要在数据库查询时加上order=ASC(默认是DESC)选项,就能按照时间的顺序从old到new排序。

    正如前文所说,默认的顺序是降序,即DESC,这是为了让自己和饭友总是看到最新的动态,同时也是为了上搜索引擎抓取到最新的内容。同时,只要是总消息数大于20,则无论如何,饭否第一页总是20条消息,而不满20条的,总是把零头甩在最后一页。

    通过软件方式实现:

    这个更简单,我原来写的饭否消息打包程序已经实现了该功能,目前正在写新版。

  2. 针对发布内容的关键字搜索;

    这个功能无疑将极大地便利众多饭友。只是饭否官方迟迟没有提供该功能,而其同类产品,都通过自己或第三方实现了该功能。

    但是该便利的前提是,让服务器更玩儿命。每位饭友的所有消息,在饭否服务器中有两种可能的存储方式:一是每人一张表,饭否ID作为表名关键字,便于搜索个人的消息(小而快);一是所有人共用一张大表,饭否ID(或其对应的内部UID)作为关键字段之一,便于搜索所有人的消息(全而慢)。无论是哪一种方式,搜索都是比较耗费资源的,尤其考虑到饭否在中国用户群最庞大,鹅毛也能压死骆驼。

    因此,饭否官方这样做或许是为了避免让原本已几乎不堪重负的服务器再雪上加霜。近来饭否已经有步履蹒跚的迹象。昨天(2008年6月6日)上午出现了数小时的中断,晚21时又进行了1个半小时的服务器维护。按惯例,针对中国大陆网友的网络服务器,应该是在凌晨2:00左右维护,且应提前1至3天通知,这样才能把用户体验的影响降至最低。饭否挺住!饭否加油!

    题外话:饭否的盈利模式在哪里?饭否以及海内已经聚集了大量人气,应该不会甘于只做免费服务、公益服务。跟Google比较一下,Google提供的是有广告的服务,但是它的服务强大、全面,以致于让人觉得它的广告也不那么难以接受了——不细看不深究不点击就是了,这是老夫对广告一贯的态度。Google可以便利地搜索Billion级的网页而响应迅速,实在值得做互联网的人学习。我们需要的是一个功能强大、贴心的饭否,而不是一个病如西子胜三分的饭否。

    另外,使用软件的方式实现饭否消息的搜索,虽然可以定制(时间、顺序、关键词、正则式),灵活便捷,但是对一个人的消息来实现搜索不难,最多能辐射到好友,要想在茫茫饭海中打捞消息,就只能望饭兴叹了。

  3. “每日最热词”榜单——这个纯粹是为了好玩:统计每天海量文本中出现最多的词。

    StarKnight 提出的三个问题中,在技术上来说,这是最难的一个。这个问题在英语或类似语言中不成问题,因为单词的分隔很容易实现,只要将句子按照空格或标点来分隔,再综合统计每个单词出现的频率,去掉常规词汇(a,an,the,is…),理论上能够从海量文本中统计出热频词汇。只是理论上而已。

    具体到中文,单字好说,单词呢?老一辈的人可能记得生产队上的《小五更的故事》:

    我的心跳起来,可千万别碰上生字。我念:“棉田——灌——溉法。” 

      队长的手指往下指,我就往下念:“但是——如果——灌溉——不合理——对——棉田——反而有——害——多年连——读(续)——不合理——的灌溉——会把——好地——搞成——坏地”

    在处理中文断词断句时,程序可比“小五更”差远了,虽然小五更也够倒霉的。

    但是,就没有解决办法了吗?非也非也。解决之道就是老夫一直提倡饭友使用、一直希望饭否官方提供支持的万能无敌TAG术:

    • 在消息中使用[]或【】作为饭否tag标识符,中括号之内以“,”“,”或空格作为多tag的分隔符。
    • 然后对消息中的tag作出超链接,在点击时转到所有含该tag的消息列表中。不但可以在自己的消息中寻找,还可以在公共消息中寻找。

    • 还可以做成tag cloud,以出现次数排序,自然就是每日热榜词汇列表。
    • 使用tag就省去了无目的、低效率的数据库操作,转换成有针对性的高效操作。

    当我想到的时候,做啥已经实现该功能了。见截图:

    其中,“热门话题”中大部分tag是根据消息来源自动加上的,一小部分是出自用户的贡献。如果饭否也能加上相应功能,应该增色不少。昨晚的服务器维护时段之后,本以为会出现不少新功能,但是界面、功能一如其故。或许我们该庆幸,饭否还是如约回来了……

作为即将满一年的老饭友(2007年06月28日10点30通过发布了自己第一条饭否消息:读万卷无字书,行万里冤枉路。) ,对饭否的感情是复杂的。初识时的激情已退,之所以依然恋恋不舍,一方面是相知多时积攒下不少温存的回忆;一方面是习惯的力量,打开浏览器时不自觉ctrl+d,fanfou.com,回车;最重要的是,经饭否认识的若干老友都在那里,总是抱着关切、好奇、窥视的心态,察看老友的最新消息和动向。随意浏览时,看似你一言我一语,七嘴八舌不明所以,然而相知既久,自有其连贯性。引钱钟书的《围城》作结:

譬如咱们这次同船的许多人,没有一个认识的。不知道他们的来头,为什么不先不后也乘这条船,以为这次和他们聚在一起是出于偶然。假使咱们熟悉了他们的情形和目的,就知道他们乘这只船并非偶然,和咱们一样有非乘不可的理由。这好像开无线电。你把针在面上转一圈,听见东一个电台半句京戏,西一个电台半句报告,忽然又是半句外国歌啦,半句昆曲啦,鸡零狗碎,凑在一起,莫名其妙。可是每一个破碎的片段,在它本电台广播的节目里,有上文下文并非胡闹。你只要认定一个电台听下去,就了解它的意
义。我们彼此往来也如此,相知不深的陌生人——

希望饭否官方与时俱进,能推陈出新,“老者安之(维系老用户),少者怀之(吸引新用户)”。呵呵。