模拟Snap.com,支持js引入对链接预览的简单实现

    在前天的POST中,实现了通过IViewObject接口截浏览器的图象的类,今天改善了一下,修正了内部的资源释放问题。并且完善了WebPageSnapshot类,将目标页面的错误对话框和新窗口问题处理了一下。总之抓图速度过慢,还想不出什么改善的办法;Kai.Ma在它的代码中实现了一个很好的改善速度的办法,就是把抓的图直接存盘,只是还缺少一个更新机制,所以我在此基础上增加了一个Hashtable,它的key 存放原始url,value 保存抓取的时间,当产生抓取请求的时候,先访问该hashtable,如果不存在则记录一笔,否则就比较一下时间,是否超过1天,超过的话继续抓取,否则直接传递上次抓取的图象文件,为了简单,该hashtable未持久化处理。

简单的cache机制:

简单CACHE机制的实现


通过google搜索到一个脚本提示的实现代码,简单的改了改,将行为模拟成snap.com 提供的服务那样,把鼠标指到超级链接并停顿1秒后,显

示目标PAGE的图象。js脚本我只做了微小的调整,原作者我无法得知,比较遗憾。
有了前端JS的实现,那么后端与脚本之间的接口也很简单。

后端Snap_Preview.aspx页面只接收2个参数,分别为: href 和 domain

domain 是指当传递的url只是相对地址的时候,整合为完整地址。
href 则就是目标页的地址。

在snap_preview.aspx页的 Load 事件内写入:

    protected void Page_Load(object sender, EventArgs e)
    
{
        
///清空缓冲
        Response.Clear();
        
///目标地址
        string href = Request["href"];
        
///调用页域名称
        string domain = Request["domain"];
        
///是否显示空白页
        if (string.IsNullOrEmpty(href) || href.Equals("about:blank", StringComparison.CurrentCultureIgnoreCase))
        
{
            Response.TransmitFile(
                HttpContext.Current.Request.PhysicalApplicationPath 
+ "Caches\\loading.gif" 
            );
            
return;
        }

        
///处理url的简单办法
        if (href.IndexOf("http://"== -1)
            
if (!string.IsNullOrEmpty(domain))
                href 
= domain.TrimEnd('/'+ "/" + href;

        
if (href.IndexOf("http://"== -1)
            href 
= "http://" + href;

        
///传送图象
        Response.TransmitFile(SnapPreviewCache.CreateSnapPreviewFile(href));

    }

这样通过脚本代码的整合,即可简单的做成一个snap.com的功能雏形,不过它有很多的问题。其中最主要的就是速度慢的问题。

速度慢主要因为WebBrowser 的运行方式是;单线程单元模型 (STA):进程中一个或多个线程使用 COM ,并且 COM 对象的调用由 COM 进行同

步。在线程间对接口进行编组。单线程单元模型的退化情况(其中,在给定的进程中只有一个线程使用 COM)被称为单线程模型。以前的

Microsoft 信息与文档曾经将 STA 模型简单地称为“单元模型”。 它的运行线程应该是消息或用户界面 (UI) 线程。

而被封装到 web 组件里来隐含调用,则必须为它开辟一个STA线程,这样使它的性能大大降低,因为多次构造对象和释放对象都是非常浪费资

源的事情,初始化的速度太慢,是影响速度的最大原因。

另外,我将这次的工程代码全部发放出来,供各位研究,能有所改善则更好,也希望各位能发扬知识共享精神,让大家共同进步。

工程代码下载(含全部源码),可能有bug若干:
测试运行之前请确认Snap_Preview_Anywhere.js中的sServiceUrlRoot变量指向的是正确的地址。
/Files/Chinasf/SnapLibrary_With_WEB.rar

运行外观:

posted @ 2006-12-27 15:24 萧寒 阅读(2461) 评论(10)  编辑 收藏 所属分类: C# WinForms.NET WebForms

  回复  引用  查看    
#1楼 2006-12-27 15:49 | Cat Chen      
真正好像Snap.com那样高负载运作的,应该有一台专门的作业服务器负责抓取,有一台专门的文件服务器或群集负责存储所有抓取结果,接下来简单的反而是Web和数据库。
  回复  引用  查看    
#2楼 2006-12-27 16:14 | Kai.Ma      
不错,Snap.com那样的是分布式架构了。
  回复  引用  查看    
#3楼 2006-12-27 16:41 | skyover      
看过国外的一些提供类似服务的网站,应该是有一个队列处理,当请求某个URL之后,发现以前并未对此URL进行过抓取,则列入队列,则一个专门的Spider来做这个事情,这个Spider应该是winform或者是ConsoleApplication的,所以目前这样的实现已经是足够了。
  回复  引用  查看    
#4楼 2006-12-27 17:20 | U2U      
好东西,支持!
  回复  引用  查看    
#5楼 2006-12-28 12:16 | 数据绑定者      
我有个地址,不知道你那里可以不可以缩略出来,我这里总是出来红叉号。
难道是因为我后面的是加密后的字符?


http://new.angelala.cn/Pages/ShowPost.aspx?Showis=8AECDF34EBC63460
  回复  引用  查看    
#6楼 [楼主]2006-12-28 13:35 | 萧寒      
@数据绑定者

打开http://new.angelala.cn/Pages/ShowPost.aspx?Showis=8AECDF34EBC63460 本来就是错误地址啊
  回复  引用    
#7楼 2006-12-28 14:58 | aa[匿名] [未注册用户]
好,我找了几天的资料了.现在终于找到了,感激不尽

  回复  引用  查看    
#8楼 2006-12-28 15:20 | 数据绑定者      
sorry 居然服务器down掉了,现在修好了,您看看您那里可以不可以缩略出来啊?
我怀疑会被我后面的加密串影响
  回复  引用    
#9楼 2008-01-02 10:36 | 少伟 [未注册用户]
开了一个子线程,在捕捉大部分页面的图片是可以正常工作的,但是循环捕捉下面这些页面时
、会直接弹出
Visual Studio 实时调试器,说“发生了未处理的异常,不能执行已释放Script 的代码”,
这异常也无法 Try{}Catch{},无法捕捉,不怎么楼主是怎么处理的?

http://health.sohu.com/20071231/n254393304.shtml
http://health.sohu.com/20071231/n254393293.shtml
http://health.sohu.com/20071231/n254393261.shtml
http://health.sohu.com/20071231/n254393074.shtml
http://health.sohu.com/20071231/n254393058.shtml
  回复  引用    
#10楼 2008-01-27 17:06 | fish man [未注册用户]
似乎遇到部份轉頁時 會只抓到空白
不過應該可以解決的
等網頁完全呈現後 再抓依次url

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-12-30 11:36 编辑过


相关链接:

历史上的今天:
2005-12-27 发现了一个delphi的form的bug