PhotoRobot之Sohu相册


这次的目标是sohu的相册, http://pp.sohu.com,免费相册,图片公园。它的首页,美女没有yahoo的那么多,但是比163的光秃秃好点,所以作为第二位。

Sohu使用的技术向来比较成熟稳健,而又有技术含量。例如很久以前,它的新闻和论坛就使用了CMS系统搭建,非常的规范。而博客则使用了Ajax技术,异步加载页面的不同部分,速度很快。所以在对它的相册动手之前,就做好了打硬仗的心理准备。

同样,先进入专辑的第一张图片,这样页面的图片信息比较明确,方便提取,随便找个美女相册进先

   
http://pp.sohu.com/photo.jhtml?method=view &id =74529157#74529157


1. 定位图片source

照例,view page source,先看看有没有图片部分的源代码,还好,正常

< id ="photoHref"  href ="javascript:gPhotoPage.nextPhoto(onPhotoChange);" >
    
< img  id ="photodisplay"  src ="http://img44.pp.sohu.com/images/2007/3/20/15/9/11205330d6b.jpg"  title ="点击图片查看下一张"
            alt
="post-3-1173601339.jpg_搜狐免费相册"  border =0  hspace =02  vspace =02  />
</ A >


没163那么变态,全部藏在javascript里面。这样还是比较简单,只要能够定位到翻页的代码,就可以比较简单和机械的提取相册图片了。

2.    定位上下页
   
        这里遇到了麻烦,sohu的页面尽管给出很好的注释,

                     <!-- 这里是导航区 --><!-- 导航区结束 -->
                    
<!-- 这里是面包屑目录区&管理模块区 --><!-- 面包屑目录区&管理模块区结束 -->


        但是都没能找到上下页的地方,怎么办?看看页面,发现有Ajax的踪迹,

        
< SCRIPT  LANGUAGE ="JavaScript"  type ="text/javascript" >
            
<!--
            
function  addContact(userId) {
                
var  url  =   " /relations.jhtml?m=add&userId= "   +  userId;
                
var  actionItem  =   new  ActionItem();
                
new  Ajax.Request(url,{method:'get', onLoading:actionItem.onLoading.bind(actionItem),onComplete:actionItem.jsonBack.bind(actionItem)});
            }
            
// -->
         </ SCRIPT >


        果然不好啃啊。

3.    下载js文件
        利用firefox的CacheViewer,过滤后排序,找到了pp.sohu.com的相关十几个js文件,果然是庞大啊。但是都是那种去掉分行的, 非常的难看,回头用python写个程序,专门把它们变回远样。据称最好的js编辑器,Aptana居然没有代码排版功能,感觉有点废啊。

        找了下gPhotoPage.nextPhoto,发现是都是在Photos.js中,这个js文件是个很重要的类,对photo的操作都是封装在里面,后面用到了一个地方,但是没有找到获得图片列表的操作。

4.    重新分析页面的源代码

        在源代码的最后一部分,找到

         < script  type ="text/javascript" >
            
function  loadPage() {
                
var  rpccall  =   new  JSONRpcClient( " /rpccall " , null , null " photoMgr " );
                photosList 
=  rpccall.getAllPhotos( 74529157 )
                gPhotoPage 
=   new  Photos(photosList.list,getPhotoIdFormUrl()  !=   null   ?  getPhotoIdFormUrl() :  74529157 );
                gLoginUser 
=  rpccall.getLoginUser();
                initRequestPhoto(gPhotoPage, gPhotoPage.photo);
            }
        
</ script >        
       

        该部分是在body load的时候调用,呵呵,看了这里是关键了,通过JSON RPC调用,获得所有的photo列表,得来不费功夫,果然是越高级的东西就越方便。

5.    JSON RPC

        如果把它的javascript全部跑起来,当然可以获得一样的效果,不过太麻烦。即然用python,当然要用python来进行这个调用。
        使用google,找到了jsonrpclib的开源项目,python和java一样,开源的支持就是多,这点我喜欢。

        jsonrpclib只有一个py,非常小巧,但是倚赖于simplejson的包,jsonrpc主要是对json的远程调用的封装,而simplejson则是对json数据的解析,两个模块各司其责,清晰明了。

        看看源代码的版权信息,寒一个

             #  a port of xmlrpclib to jsondot.gif.
             #
             #
             #  The JSON-RPC client interface is based on the XML-RPC client
             #
             #  Copyright (c) 1999-2002 by Secret Labs AB
             #  Copyright (c) 1999-2002 by Fredrik Lundh
             #  Copyright (c) 2006 by Matt Harrison


        原来这东西,国外99年就在研究了,自己现在才知道...

        对于Ajax我没有什么经验,JSON RPC也没有,不过凭着程序员的直觉,进行使用测试。

        网上例子不多,找到了两个例子

            一个python例子
                s  =  jsonrpclib.ServerProxy( " http://jsolait.net/services/test.jsonrpc " )
                reply 
=  s.echo( " foo bar " )
                
print  reply
       
            一个javaScript例子
                 var  jsonrpc  =   new   JSONRpcClient( " /<%=ApplicationHelper.getWebAppName(request)%>/JSON-RPC " );
                jsonrpc.myObject.setName(“Vince”);
       
        仔细研究这两个例子,再参考sohu的页面代码,猜到,其实
                 var  rpccall  =   new  JSONRpcClient( " /rpccall " , null , null " photoMgr " );
                photosList 
=  rpccall.getAllPhotos( 74529157 )

        是json rpc 的一种javascript写法,可以改成                   
                 var  jsonrpc  =   new  JSONRpcClient( " /rpccall " );
                photosList 
=  jsonrpc.photoMgr.getAllPhotos( 74529157 )
       
        那么换成python就是
                s  =  jsonrpclib.ServerProxy( " http://pp.sohu.com/rpccall " )
                reply 
=  s.photoMgr.getAllPhotos( 74529157 )
       
        当然了,这个写法也是改了好几次才得到的,结果是好长的一个dict对象,看到结果的时候,我得意的笑,得意的笑..

        动态语言的优势这个时候就体现了,同为动态语言的python和javascript,都是不需要什么类型强制转换,直接获得的对象,再调用方法就可以了,换成了严谨的java,要如何处理才好呢?恐怕要写长好几句了。

        得到后就简单了,分析一下reply的dict结构,提取出imgList
            imglist  =  reply.get( ' result ' ).get( ' list ' ))

        imglist是个dict的list,每个dict中,最主要的就是hosturl和imgNames属性,imgNames属性一般有3个图片名,全 部下载后,结合photos.js的_getImgeUrl方法的分析,知道最后一个非空的,就是最大的图片,这个就是我需要的啦,剩下的事情就简单了。

        imgSrcs 
=  []
        
for  imgurl  in  imglist:           
            hosturl 
=  imgurl[ " hosturl " ]
            imgNames 
=  imgurl[ " imgNames " ].split( " ; " )
           
            
for  i  in  range(len(imgNames) - 1 , 0,  - 1 ):
            
if  imgNames[i]:
                imgSrc 
=  hosturl  +  imgNames[i]
                
break
            imgSrcs.append(imgSrc)


        现在sohu的图片公园也没有防止外链了,直接用SimpleDownloader下载就可以了,至此,大功告成。

106691.html

龙舞九天 2007-03-27 16:19 发表评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值