现在的位置: 首页 > 综合 > 正文

转载:PhotoRobot之Sohu相册

2013年03月17日 ⁄ 综合 ⁄ 共 6859字 ⁄ 字号 评论关闭
文章目录
转载自:http://www.blogjava.net/andyyehoo/archive/2007/03/27/106691.aspx

PhotoRobot之Sohu相册

Posted on 2007-03-27 16:19 龙舞九天 阅读(181) 评论(0)  编辑 收藏 引用 所属分类: Python

这次的目标是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 json.
            #
            #
            # 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下载就可以了,至此,大功告成。



     
标题
姓名
主页  
验证码 *
内容(提交失败后,可以通过“恢复上次提交”恢复刚刚提交的内容)
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
[使用Ctrl+Enter键可以直接提交]
 

posts - 5, comments - 0, trackbacks - 0, articles - 1

Copyright © 龙舞九天

抱歉!评论已关闭.