[转载]当jQuery遭遇CoffeeScript的时候——妙,不可言

mikel阅读(1008)

[转载][翻译]当jQuery遭遇CoffeeScript的时候——妙,不可言 – filod – 博客园.

原作:How CoffeeScript makes jQuery more fun than ever—— Stefan Buhrmester

翻译:filod

转载声明:请注明原作者、翻译者以及译文链接


译者前言:虽然对ruby不太了解,但是看到CoffeeScript诗一般的代码确实被怔住了,和JQuery之前给我的感觉是如此的相似——都是一个字,美,当JQuery遭遇到CoffeeScript时,会蹦出什么样的火花呢?

当我多年前初次接触jQuery时我感觉我来到了程序员的天堂。它极大简化了DOM操作。函数式编程变得如此容易,尽管更多适合RIA开发的框架近年来在浮现,但是我仍旧无法想象一个没有jQuery的程序人生是多么的罪恶,相信你也有同感~

而来到CoffeeScript的世界,同样的美妙故事再次上演。在写了几行代码后我相信你将不会再想念原生的JavaScript了。CoffeeScript包含了许多新特性,当将它与jQuery结合时,你会发现一片新天地。

本文的目的就在于展示CoffeeScript和jQuery协同工作时美妙场景。

像老板一样指挥你的代码

CoffeeScript提供了一堆酷毙了的数组迭代方法。最好的事莫过于这不仅仅能工作于数组,还能工作于jQuery对象了。来行诗一般的代码吧:

formValues = (elem.value for elem in $('.input'))

这行代码将会被翻译为如下的JavaScript

var elem, formValues;
formValues = (function() {
var _i, _len, _ref, _results;
_ref = $('.input');
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
elem = _ref[_i];
_results.push(elem.value);
}
return _results;
})();

老实说最初这样写代码确实让人提心吊胆的,但是一旦你开始拥抱CoffeeScript的魔法时,你会爱上它的。

飞一般的方法绑定

在jQuery的回调中使用”=>”将会大大减省你手动绑定方法到对象的麻烦。还是来看段代码吧:

object =
func: -> $('#div').click => @element.css color: 'red'

下面是编译输出的Javascript:

var object;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
object = {
func: function() {
return $('#div').click(__bind(function() {
return this.element.css({
color: 'red'
});
}, this));
}
};

代码中的@element指向了一个jQuery的对象,该对象是在其他地方指定的——比如object.element = $('#some_div').

任何使用”=>”所指定的回调函数都会自动绑定到原来的对象上,没错,这很酷。

在2011年函数是这样调用的

瞅一眼这个:

$.post(
"/posts/update_title"
new_title: input.val()
id: something
-> alert('done')
'json'
)

使用CoffeeScript,多个参数可以写成多行来调用,逗号和大括弧是可选的,这使得一些jQuery中签名比较长的方法比如$.post()$.animate() 等更加易读。这儿还有一个例子:

$('#thing').animate
width: '+20px'
opacity: '0.5'
2000
'eaSEOutQuad'

很美味的Coffee不是吗?要注意第一个参数是一个匿名的对象,你甚至可以省略调用函数的元括弧。

让初始化来的更性感吧

我最初开始使用jQuery时我是这样做页面初始化的:

$(document).ready(function() {
some();
init();
calls();
})

CoffeeScript和新版的jQuery使得上面的代码进化的如此性感:

$->
some()
init()
calls()

函数定义语法在CoffeeScript里本身已经非常酷了,能在上面这些场合使用使得其更酷了。你会发现所有需要回调的函数调用在CoffeeScript中都是如此简单。

更多关于CoffeeScript请访问其官网

注:已经有一本关于CoffeeScript的书在七月发行了,其中有一整章的内容是关于jQuery的。

[转载]《重构-改善既有代码的设计》读书笔记

mikel阅读(927)

[转载]《重构-改善既有代码的设计》读书笔记 – karoc – 博客园.

坏味道

特征

情况及处理方式

目标

重复代码

1.重复的表达式
2.
不同算法做相同的事
3.
类似代码

同一个类的两个函数有相同表达式

重复代码提取为方法

相同表达式只在一个类的一个方法出现,供其他方法调用

兄弟类含有相同表达式

重复代码提取为方法
提升方法到父类

不相干类含有相同代码

提取为独立类供调用

过长函数

1.代码前面有注释
2.
条件表达式
3.
循环

提取方法

每个方法只做一件事,方法要定义完善、命名准确

过大的类

1.一个类中有太多实例变量
2.
一个类中有太多代码

部分字段之间相关性高

相关的字段和方法提取为类

每个类负责一组具有内在的相互关联的任务

某些字段和方法只被某些实例用到

这些字段和方法移到子类中

过长参数列

1.参数列过长
2.
参数列变化频繁

方法可以通过其他方式获取该参数

让参数接受者自行获取该参数

只需要传给函数足够的、让其可以从中获取自己需要的东西就行了

同一对象的若干属性作为参数

在不使依赖恶化的情况下,使用整个对象作为参数

被调用函数使用了另一个对象的很多属性

将方法移动到该对象中

某些数据缺乏归属对象

首先创建对象

发散式变化

一个类受多种变化的影响

类经常因为不同的原因在不同的方向上发生变化

将特定原因造成的所有变化提取为一个新类

针对某一外界变化的所有修改,只应发生在单一类中,而这个类中所有的内容都应反映此变化

散弹式修改

一种变化引发多个类的修改

某种变化需要在许多不同的类中做出小修改

把所有需要修改的代码放进同一个类中

针对某一外界变化的所有修改,只应发生在单一类中,而这个类中所有的内容都应反映此变化

依恋情结

一个函数使用其他类属性比使用自身类属性还要多

某个函数从另一个对象调用了几乎半打的取值函数

将依恋代码提取为单独方法,移动到另一对象

将数据和对数据的操作行为包装在一起

数据泥团

同时使用的相关数据并未以类的方式组织
1.
两个类中相同的字段
2.
许多函数中相同的参数

先将字段提取为类,再缩减函数签名中的参数

总是绑在一起的数据应该拥有属于它们自己的对象

基本类型偏执

过多使用基本类型

总是被放在一起的基本类型字段

提取类

将单独存在的数据值转换为对象

参数列中有基本类型

提取参数对象

数组中容纳了不同的对象,需要从数组中挑选数据

用对象取代数组

基本数据是类型码

使用类替换类型码

带条件表达式的类型码

使用继承类替换类型码

Switch语句

相同的switch、case语句散布于不同地方

根据类型码进行选择的switch

使用多态替代switch

避免到处做相同的修改

单一函数中有switch

使用显式的方法取代参数

平行继承体系

1.为某个类增加子类时,必须为另一个类增加子类
2.
某个继承体系类名前缀和另一个继承体系类名前缀相同

一个继承体系中的实例引用另一个继承体系中的实例,然后迁移成员

避免到处做相同的修改

冗赘类

类无所事事

父类和子类无太大差别

将它们合为一体

某个类没有做太多事情

将这个类所有成员移到另一个类中,删除它

夸夸其谈未来性

某个抽象类没有太大作用

将父子类合并

不必要的委托

将这个类所有成员移到另一个类中,删除它

函数的某些参数未用上

移除参数

函数名称带有多余的抽象意味

重命名函数名

函数只被测试方法调用

连同测试代码一并删除

令人迷惑的暂时字段

1.某个实例字段仅为某种情况而设
2.
某些实例字段仅为某个函数的复杂算法少传参数而设

提取单独的类,封装相关代码

过度耦合的消息链

一长串的getThis或临时变量

客户类通过一个委托类来取得另一个对象

隐藏委托

消除耦合

中间人

某个类接口有大量的函数都委托给其他类,过度使用委托

有一半的函数

移除中间人

少数几个函数

直接调用

中间人还有其他行为

让委托类继承受托类

狎昵关系

某个类需要了解另一个类的私有成员

子类过分了解超类

将继承改为委托,把子类从继承体系移出

封装

类之间双向关联

去掉不必要的关联

类之间有共同点

提取新类

异曲同工的类

两个函数做同一件事,但是签名不同

合并

不完美的类库

类库函数构造的不够好,又不能修改它们

想修改一两个函数

在调用类增加函数

想添加一大堆额外行为

使用子类或包装类

幼稚的数据类

某个类除了字段,就是字段访问器、设置器

1.用访问器取代public字段
2.
恰当封装集合
3.
移除不需要的设置器
4.
搬移对访问器、设置器调用方法到此类
5.
隐藏访问器、设置器

封装

被拒绝的馈赠

派生类仅使用了基类很少一部分成员函数

子类拒绝继承超类接口

使用委托替代继承

过多的注释

一段代码有着长长的注释

消除各种坏味道

[转载]BlazeDS 整合 Flex HelloWorld 示例

mikel阅读(1205)

[转载]BlazeDS 整合 Flex HelloWorld 示例 – hoojo – 博客园.

开发环境:

System:Windows

WebBrowser:IE6+、Firefox3+

JavaEE Server:tomcat5.0.2.8、tomcat6

IDE:eclipse、MyEclipse 8

Flex IDE:Flash Builder 4

BlazeDS:4.5

开发依赖库:

JavaEE5、blazeDS 4.5

Email:hoojo_@126.com

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

一、准备工作

1、 首先要提供相关的jar包

Java服务器端需要提供BlazeDS相关的配置和jar包

下载地址:http://opensource.adobe.com/wiki/display/blazeds/download+blazeds+trunk

下载后,解压你可以看到这样的一个目录

clip_image002

Docs就是文档

Resource是源码

SampleDB是示例用的数据库,可以运行startdb.bat来启动数据库

Tomcat是内置的tomcat,如果你没有tomcat的话可以使用它,在tomcat的webapps目录中有samples示例

blazeds.war就是blazeDS的核心文件、库,你可以把这个war放到tomcat的webapps目录下,就会自动解压。当然你也可以自己手动解压。

Blazeds-spring.war是和spring整合的配置

Ds-console.war是blazeDS的控制台程序

Samples.war是官方提供的示例

Samples-spring.war是spring和blazeDS的整合示例

二、部署服务器端程序

1、新建一个JavaWeb Project工程,然后在WEB-INF/lib目录中添加如下jar包

clip_image004

这些jar包可以在blazeds.war包中的lib目录中可以找到

2、 然后你需要将blazeds.war包中的WEB-INF目录下的flex目录复制到当前工程的WEB-INF下

3、 将blazeds.war包中的WEB-INF目录下的web.xml的配置,添加到当前工程的web.xml文件中

4、 最后基本的样式如下

clip_image006

5、 最后你发布当前工程,如果没有错误就表明你服务器端部署成功了。

6、 编写一个HelloWorld的java程序。代码如下

package com.hoo.flex;

/**
 * <b>function:</b> HelloWorld Example
 * @author hoojo
 * @createDate 2011-8-31 下午06:11:27
 * @file HelloWorld.java
 * @package com.hoo.flex
 * @project BlazeDSServer
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class HelloWorld {

    public HelloWorld() {
    }

    public String sayHello(String name) {
        return "[" + name + "] say hello!";
    }
}

就一个sayHello方法,接收一个参数。

三、Flex客户端程序

1、创建一个Flex工程,在选择服务器技术的时候,你需要选择J2EE。然后勾上使用J2EE技术,然后选择BlazeDS。点击Next下一步

clip_image008

2、配置根文件夹,也就是JavaEE服务器端发布程序在tomcat中的位置。我这里是在tomcat的webapps的 BlazeDSServer中,BlazeDSServer是我的服务器端程序。根URL是访问服务器端程序的url;上下文目录对应工程名称;最后就是 输出文件夹目录,这个是Flex的文件最后在tomcat中保存的目录。

clip_image010

3、最后你需要设置服务器端的services-config.xml的路径到编译参数中,这个很重要!如果你不设置的话,那么你在后面用RemoteObject调用BlazeDS的时候,就需要设置endpoint。设置如下:

clip_image012

-services是参数键,后面的字符串是值。我这里是设置BlazeDSServer发布到tomcat目录中的services-config.xml的路径。

4、编译Flex前端代码,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="BlazeDSHelloWorld.mxml" layout="absolute" minWidth="955" minHeight="600">
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.rpc.AsyncToken;
            import mx.rpc.events.ResultEvent;

            private function faultHandler(event: Event): void {
                Alert.show(event.toString(), event.type);
            }

            private function resultHandler(event: ResultEvent): void {
                //event.result是服务器端返回对象
                result.text = "Message:" + event.result.toString();
            }

            private function sendHandler(): void {
                helloRemoteObject.sayHello(userName.text);
            }
        ]]>
    </mx:Script>

    <!-- 当工程没有设置编译器-service参数 或是-context-root等参数,就需要手动设置endpoint参数 -->
    <mx:RemoteObject
        id="helloRemoteObject"
        destination="helloWorld"
        fault="faultHandler(event)"
        result="resultHandler(event)"
        showBusyCursor="true"/>
    <mx:Panel x="10" y="10" width="272" height="148" layout="absolute" title="BlazeDS Remote HelloWorld Sample">
        <mx:Label x="10" y="22" text="请输入名称"/>
        <mx:TextInput x="70" y="19" id="userName"/>
        <mx:Button x="184" y="45" label="发送" click="sendHandler()"/>
        <mx:Text x="10" y="79" id="result"/>
    </mx:Panel>
</mx:Application>

首先你需要将Java服务器端的HelloWorld程序配置在flex的remoting-config.xml中,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
    class="flex.messaging.services.RemotingService">

    <adapters>
        <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>

    <default-channels>
        <channel ref="my-amf"/>
    </default-channels>

    <destination id="helloWorld">
        <properties>
            <source>com.hoo.flex.HelloWorld</source>
        </properties>
    </destination>
</service>

上面mxml代码中的RemoteObject的destination对应的就是remoting-config.xml配置文件中的 destination的id。这个是一一对应的,然后在sendHandler方法中,helloRemoteObject对应的就是 RemoteObject的id,而sayHello方法对应的就是配置在remoting-config.xml中的destination的 source的Java服务器端代码的公有方法。添加完配置后,需要重启tomcat。

运行上面的flex程序后,如果输入参数后,点击发送,可以看到服务器端返回的消息就说明BlazeDS整合Flex成功了。

[转载]百度地图API详解之地图标注

mikel阅读(1203)

[转载]百度地图API详解之地图标注 – jz1108 – 博客园.

详解系列

本文将向大家介绍百度地图API的标注(Marker)的使用方法和一些实现细节。

标注概述

标注(Marker)是用来表示一个点位置的可见元素,每个标注自身都包含地理信息。比如你在西单商场位置添加了一个标注,不论地图移动、缩放,标注都会跟随一起移动,保证其始终指向正确的地理位置。

从上面的图可以看出,不论地图如何变化标注始终指向“西单商场”的位置。

如何知道某个点的坐标?

上例中我们在西单商场位置添加了一个标注,那么我是如何知道它的坐标点呢?可以通过API的事件机制来获取:

map.addEventListener('click', function(e){
    console.log(e.point);
});

我们在map对象上添加了一个click事件的监听函数,当点击地图上某个位置时,监听函数通过控制台把当前点击的位置输出出来(注意需要有控制台 的支持,比如firebug,如果没有控制台则可使用alert把point的lng和lat属性输出出来)。此外,你也可以使用API提供的坐标拾取工 具来完成(http://dev.baidu.com/wiki/static/map/API/tool/getPoint/),它支持检索并且点击地图上任意位置时会出现该位置的坐标。

标注元素组成

从DOM元素构成角度看,一个完整的标注是由以下几个部分组成的:

  • 标注点击区域
  • 标注图标
  • 标注阴影

下面是示意图:

在地图API实现中,这三个DOM元素分别位于不同的容器中,这些容器可以通过map.getPanes()方法获得,其中 markerMouseTarget就是标注点击区域所在容器、markerPane为标注图标所在容器,markerShadow为标注阴影所在图层。 你可能会在自定义覆盖物时需要这些容器对象,这里只需要知道Marker的各个部分是如何放置的即可。

自定义标注图标

标注的图标是可以自定义的,通过Icon类可以自定义标注的图标,比如我希望使用下面这个图片作为标注图标:

已知这个图标大小为20×32。我们初始化地图,接着定义Icon,并赋给一个Marker实例:

var map = new BMap.Map('container');
map.centerAndZoom(new BMap.Point(116.380797, 39.918497), 18);

var icon = new BMap.Icon('pin.png', new BMap.Size(20, 32), {
    anchor: new BMap.Size(10, 30)
});

var mkr = new BMap.Marker(new BMap.Point(116.38075,39.918986), {
    icon: icon
});

map.addOverlay(mkr);

我们给定icon所需图片的url,接着是图片的尺寸,另外我们还增加了anchor属性,这个是干什么用的呢?在自定义标注图标时有一点需要注意 的就是标注的定位点(anchor),通俗的讲就是要指定图片的哪个位置是与标注真正的位置对应在一起。我们通过下面的图示来说明:

我们获取到地图上一个位置(上图中标注下端所在的黑色小方块),那么我也希望我标注中间下端指向这个位置,这个就需要通过anchor来调节。anchor的意义如下图所示:

即定位点距离图片左上角的偏移量。

如果不给anchor的话,API会自动获取图片中心点作为anchor位置:

我们看到标注图片中心的位置覆盖在那个小方块区域。

除了anchor之外,还有一个infoWindowAnchor属性,它是用来控制信息窗口开启的位置的(注意这里调用的是Marker的 openInfoWindow方法,而不是Map的openInfoWindow方法),默认情况下它和icon的anchor是一个位置:

标注被InfoWindow的底角挡住了,通过infoWindowAnchor属性就可以改变开启位置:

var icon = new BMap.Icon('pin.png', new BMap.Size(20, 32), {
    anchor: new BMap.Size(10, 30),
    infoWindowAnchor: new BMap.Size(10, 0)
})

再看看效果:

尖角位置已经发生了改变。

标注拖拽

标注支持拖拽,并且可以配置是否有动画效果,我们修改创建标注的代码:

var mkr = new BMap.Marker(new BMap.Point(116.38075,39.918986), {
    icon: icon,
    enableDragging: true,
    raiseOnDrag: true
});

这里开启了拖拽功能以及响应的动画效果。如果此时拖拽地图你会得到如下效果:

通过监听标注的dragend事件,你可以知道拖拽结束后标注的地理位置:

mkr.addEventListener('dragend', function(e){
    alert(e.point.lng + ', ' + e.point.lat);
})

标注阴影

为了增加立体感,可以单独给标注添加阴影,当然你也可以把阴影直接画在icon所用的图片上,但是由于阴影和标注本身在一起,所以就不建议使用任何 动画效果,否则会缺乏真实感。阴影可以通过MarkerOptions的shadow属性配置,类型也是一个Icon实例。具体使用方法和icon属性一 样,这里就不赘述了。

[原创]ASP.NET MVC IIS6上部署教程

mikel阅读(846)

部署步骤:

1.IIS 建立站点,设置 ASP.NET 版本为2.0

2.IIS站点权限属性设置ISUse_来宾账号为读取权限

3.在IIS6上建一个站点,然后在站点属性中的“主目录”–》“配置” ,将打开如下窗口:

在下方的“通配符应用程序映射”中插入一个映射,可执行文件交给.NET的“aspnet_isapi.dll”,默认地址一般在“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll”

4.查看IIS的Web扩展是否存在ASP.NET 2.0的扩展并启用,如果没有大概是因为IIS版本过低导致的,可以选中添加扩展,输入扩展名字

选择扩展文件为C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll

[转载]13 个 WordPress 提速技巧

mikel阅读(950)

[转载]13 个 WordPress 提速技巧.

性能是一个网站成功的非常关键因素,任何人都不喜欢访问速度超慢的网站。WordPress 的开放性造就 WordPress 有着成千上万的插件,使得 WordPress 比以其他 CMS 程序更受欢迎,但是开放也在一定程度上使得 WordPress 的性能不是很好,所以当你发现你的 WordPress 站点性能很差,你应该尝试通过下面的方式去优化它:

一些最基本,简单的提速方法

1. 更新 WordPress 到最新的发行版本

WordPress 每次版本的升级都有对性能的改进,所以升级到 WordPress 最新的发行版本是改进性能的第一步。

2. 删除没用的插件和更新正在使用的插件

删除任何你不再使用的插件,并从服务器上删除它们,这样会明显加速 WordPress 速度,因为 WordPress 运行的时候会检查每个插件是否被启用,并且导入激活的插件。

另外最好把现在使用的插件更新到最新版本,因为插件的开发者发布新版本一般来说他们应该是在某种程度上优化了插件工作效率。

3. 最小化 PHP 和数据库查询

如果每次导入你服务器上的一个页面,服务器都要执行 PHP 语句和数据库查询,这样速度是不会快的,如果你把一些 PHP 语句直接改成静态的 HTML 代码,这样每次导入页面,浏览器只要读取 HTML 就好了。

4. 使用 PHPmyAdmin 优化和修复数据库

我们至少应该每个星期登陆 PHPMyAdmin 去优化下数据库,选择 WordPress 数据库,选择所有的表,选择优化数据表和修复,你会惊奇的发现这个技巧的效果非常好,它节省了数据库的 10% 的空间,并且效率也提高了。

PHPMyAdmin Optimize Table
使用 PHPmyAdmin 优化和修复数据库

优化图片和其他静态文件

5. 使用可靠的图片存储服务

可以尝试把一些常用的网页图片,CSS,JavaScript 和其他一些静态文件存到 Amazon S3 这样的存储服务中,你会发现服务器的 CPU 时间和内存使用会下降很多,这里有一个 Amazon S3 的向导

Amazon S3
使用 Amazon S3 存储图片

不过 Amazon 的 S3 存储服务收费的,价格虽然比较低的,但是个人感觉还是不特别适合国内的 blogger。

6. 通过 Shrink O’Matic 这个工具来优化图片

Shrink O’Matic 是一个 AIR 程序,它能非常容易批量修改图片,并且支持 JPG, GIF 和 PNG 格式。只要简单的拖拉图片,它就能帮你修改图片的大小,另外它还有一些选项,让你能够选择输出大小,名字和格式。

Shrink O’Matic
Shrink O’Matic

全面提高性能

7. 安装 WP Super Cache 插件

关于 WP Super Cache 这个插件,我已经有详细的介绍。这里简单说,就是它能够产生静态的 HTML 文件,这些 HTML 文件产生之后,你的服务器就不用再去运行 PHP 脚本和数据库查询,所以它能够明显的加快你的博客速度。

8. PHP Speedy WP

PHP Speedy WP 能 够会自动把所有的 JS 和 CSS 文件组合成两个文件,这样就非常简单的加速 WordPress 站点和提高你的博客的响应时间。并且 CSS 的背景图片被转换成 data URIs,就大大降低了 HTTP 请求,并且重要的是,它和 IE 兼容,尽管 IE 不支持 data URIs。但是不幸的是,PHP speedy 还有一些缺陷,组装之后的 JavaScript 文件是放在页面顶部而不是底部,所以这个会在 WP Super Cache 开启的时候不工作,当然了已经有人提供了解决方案

PHP Speedy WP
PHP Speedy WP

9. WP CSS

这个插件会 GZIP 压缩和删除 CSS 文件中的空白,并且会把 style.css 文件中的 @import 直接放入,这个插件还可以设置 CSS 文件的缓存过期时间。

10. DB Cache

DB Cache 这个插件在给定的时间内可以缓存数据库的每一次查询,并且速度很快,而且只用到很少的磁盘空间用于缓存。

11. 使用 Google 的 AJAX Libraries API 来提速

AJAX Libraries API 就是 Google 把一些非常流行 Javsacript 框架(JQuery, prototype, script.aculo.us, MooTools, dojo)放到 Google 的服务器上,使得大家可以充分使用 Google 的服务器资源之外,更重要的是能够提高你的速度。另外WordPress 也有 AJAX Libraries 相关的插件

12. 显示页面导入时间和查询次数

这里有段代码能够让你插入到你的模板中让你知道页面导入的时间,和有多少数据库查询,这个技巧能够让你知道你博客优化的程度。

<?php timer_stop(1); ?>  秒钟有 <?php echo get_num_queries(); ?> 次查询。

13. Optimize DB

MySQL 是一个非常好的数据库,但是它不能自己整理和清理碎片和垃圾。Optimize DB 这个插件可以运行优化数据库的命令,加速你的 WordPress 数据库的速度,这里有一篇关于 Optimize DB 插件的详细介绍。

原文:link

[转载]最佳 WordPress 缓存插件:WP Super Cache

mikel阅读(753)

[转载]最佳 WordPress 缓存插件:WP Super Cache.

WP Super Cache 是 WordPress 官方开发人员 Donncha 开发,是当前最高效也是最灵活的 WordPress 静态缓存插件。它把整个网页直接生成 HTML 文件,这样 Apache 就不用解析 PHP 脚本,通过使用这个插件,能使得你的 WordPress 博客将显著的提速。

WP Super Cache 基本介绍

WP Super Cache 是基于 Ricardo Galli Granada 的 WP-Cache 2。WP-Cache 2 可以缓存你的 WordPress 博客使得不用再次访问数据库,但是它产生的是 PHP 文件而不是 HTML 文件,所以还需要 PHP 引擎去解析它们。而 WP Super Cache 则直接产生 HTML 文件,所以服务器不用解析甚至一行 PHP 代码,所以缓存之后的速度就和访问你服务器上的一张图片一样快。

WP Super Cache 是如何工作的

一半常规的缓存办法是手工把动态页面保存为 HTML 代码,WP Super Cache 也是通过同样的方式的,但是通过自动的方式完成这个过程。

当你一个访问者来的你的站点,他没有登入或者也没有留言,这样他得到是一个在 WordPress cache 文件夹下的 supercache 子文件夹下的纯静态文件,其实你都可以自己到上面的 supercache 目录下去查看同样的永久链接的 HTML 文件的备份。判断一个页面是否已经被缓存了,查看该页面的源代码,看看最后一行是否有 <!– super cache –> 或者 <!– super cache gz –>。

如果访问者已经登陆或者留了言,就会返回 WP Cache 函数生成的页面,并且最后一行会有 <!– Cached page served by WP-Cache — >

WP Super Cache 基本使用

上传 WP Super Cache 到插件目录,并在 Plugin 目录下激活之后,就可以到 Setting > WP Super Cache 进行详细配置。

WP Super Cache Status

首先是三个选项:

  • ON (WP Cache and Super Cache enabled)
  • HALF ON (Super Cache Disabled, only legacy WP-Cache caching.)
  • OFF (WP Cache and Super Cache disabled)

默认情况下,WP Super Cache 是没有开启的,所以在这里选择下,需按则第一个,就是 Super Cache,缓存为静态文件,如果第二种情况呢,则和 WP-Cache 一致。

Proudly tell the world your server is Digg proof! (places a message in your blog’s footer)
这个是说在你的 footer 显示一条信息告诉读者该博客已经缓存了,一般不要这样做。

Clear all cache files when a post or page is published. (This may significantly slow down saving of posts.)
这个是说发布新日志的时候清理所有缓存,这个肯定不能这么干了。

Super Cache Compression

启动这个则会成生 gzip 压缩,节省你的带宽。

Mod Rewrite Rules

WP Super Cache 是通过 Mod Rewrite 实现访问静态文件的,所以这里在是显示添加的 Mod Rewrite 规则。

Expiry Time and Garbage Collection

过期时间和垃圾收集,这里主要设置缓存文件过期时间,和多久删除一次过期的缓存文件。个人建议:一般缓存时间设置为1天(86400)左右,缓存删除时间为1个小时一次。

Accepted filenames, rejected URIs

这里设置一些链接不需要缓存,并且可以设置特例。

Rejected User Agents

这里设置某些 User Agents 来访问的时候不会缓存。比如 Google 和百度爬虫等。

Cache Contents

这里显示你博客缓存文件和过期文件的数量,你可以手工删除缓存文件和过期文件,因为 WP Super Cache 有垃圾回收机制,所以这里不帮不用手工删除,如果当你测试某个插件,看不到效果的时候,如果确定是缓存的原因,你可以到这里手工删除测试下。

Lock Down

一般情况下,某篇日志如果有了新留言,就会更新缓存文件,不过这篇日志是否已经到了缓存时间,但是在某种情况,你预料到你的博客可能会有很大流量和留言,候重复更新缓存文件可能并不是很好的选择,速度反而更慢,这个时候你就可以锁定缓存文件,新留言不再更新缓存日志。

插件作者也给出了一段代码,如果你的博客锁定了之后,可以通过判断一个变量 WPLOCKDOWN 是否存在告来诉读者,你博客已经锁定,待会才会更新,当然了,一般博客不建议使用。

Directly Cached Files

直接缓存文件,根据永久链接直接缓存,比如你的关于页面是不太更新,你就可以直接缓存它到你的 about 目录下(假如你的关于页面的 slug 是 about),这个直接缓存不会过期。适合一些经常性不更新的静态页面。

Configuration messed up?

因为上面那么多配置,你可能搞糊涂了,那么这里可以让你一键恢复到默认。

Cache Plugins

缓存插件还支持附加插件,比如作者自己就提供一个插件:No Adverts for Friends,不对朋友显示广告。

附加说明

  • 登陆了和留言之后是看不到静态缓存页面的,看到的效果和原来的 WP-Cache 插件一样的,一般来说留言的同学不是那么多。
  • 这个插件通过 Mod Rewrite 来是实现访问静态缓存页面,所以首先你的主机要支持 Mod Rewrite,然后你要在 WordPress 后台启动永久链接。
  • 一些动态的时时更细的插件,如 Recent Comments,Recent Posts 等,一个很好的解决方法是通过 JavaScript 来实现。所以同理 Sidebar 更新也只能在静态页面刷新的时候更新。我以后会讲解下如何实现 JS 实现 Recent Comment, Recent Post, 和 PostViews 。
  • 不要使用性能很差的主机,尽管缓存了,但是还是不行的,这里我个人推荐我和朋友一起搞的主机:WFANS 主机
  • 还有很多依赖于刷新数据的插件,如 SK2, Bad Behaviour 等可能不起作用。缓存总归会带来一点那个灵活性的不足。

[原创]Windows下版本服务器VisualSVN的迁移

mikel阅读(909)

最近换了台机器,需要把原机器上的VisualSVN迁移到新的机器上,为了保持原有修改日志不变,于是按如下步骤进行了迁移:

1.首先备份原VisualSVN的数据目录Repositories,一般在安装目录下

2.在新机器上安装VisualSVN服务器

3.恢复备份中的新机器上的Repositories文件夹下的项目文件夹,记住是项目文件夹而不是所有文件

4.在Visual Studio2008中,我用的是AnkhSvn-2.1.8420.8进行的SVN操作

右键选中需要更换SVN地址的项目,选择SubVersion->Swith Objects

输入新的SVN服务器的链接地址,类似:https://zlnc-js005:8443/svn/Test/trunk/NewTest/

点击确定更新完毕

[转载]腾讯开放平台中实现QQ登陆的功能

mikel阅读(990)

转载腾讯开放平台中实现QQ登陆的功能 – 小宇.net – 博客园.

这昨天为自己的网站实现了QQ登陆的功能,虽然,没有进行绑定,但是在技术层面上来说,已经了解了一点腾讯开放平台的协议.

具体什么是OAUTH,请您GG一下吧…

关于腾讯的开放平台,最主要的就是参数一定不能多,能有的要有,不能有的一定不能有.不然提交过去,就会提示什么什么错了.

最关键的就是签名的方式,下面就是我的签名的代码

1 /// <summary>
2 /// 每一步不同的生成签名的方式
3 /// </summary>
4 /// <returns></returns>
5 protected virtual String BuildSignature(String SignatureHost)
6 {
7 String PostMethodString = GET&;
8 StringBuilder ParamString = new StringBuilder();
9 this.CurrentStepParameters
10 .OrderBy(c => c.Key.ToString())
11 .ToList()
12 .ForEach(c =>
13 {
14 if (c.Key != OAuthParameterName.oauth_signature &&
15 c.Key != OAuthParameterName.timestamp)
16 {
17 if (ParamString.Length > 0)
18 {
19 ParamString.Append(&);
20 }
21 var p = c.Value;
22 ParamString.Append(p.OAuthOringinaName);
23 ParamString.Append(=);
24 ParamString.Append(p.Value);
25 }
26 }
27 );
28 StringBuilder SignData = new StringBuilder();
29 SignData.Append(PostMethodString);
30 SignData.Append(OAuthHelper.UrlEncode(SignatureHost));
31 SignData.Append(&);
32 SignData.Append(OAuthHelper.UrlEncode(ParamString.ToString()));
33
34 //密钥
35 String SecretKey = String.Format({0}&{1}, this.AppKey, this.AuthorizedTokenKey);
36 String SignContent = SignData.ToString();
37 String Signature = Convert.ToBase64String(OAuthHelper.HMACSHA1Code(SignContent, SecretKey));
38 return Signature;
39 }

这里的CurrentStepParameters是在构造方式里进行赋值,或者其它地方,签名里最关键的,就是oauth_signature和timestamp这两个参数,要记得去掉,在这里,我选择了过滤.

因为有的时候,CurrentStepParameters这个字典从querystring来生成的话会简单点还有能复用.

在所有参数中,有几个是经常会用到的.

所以,在此我建立了一个通用参数生成方法

1 protected virtual void AddCommonParameters()
2 {
3 if (this.CurrentStepParameters != null)
4 {
5 //增加通用参数
6 this.CurrentStepParameters.AddParam(OAuthParameterName.oauth_consumer_key, this.AppID);
7 this.CurrentStepParameters.AddParam(OAuthParameterName.oauth_nonce, DateTime.UtcNow.Ticks.ToString());
8 this.CurrentStepParameters.AddParam(OAuthParameterName.oauth_timestamp, OAuthHelper.GenerateTimestamp());
9 this.CurrentStepParameters.AddParam(OAuthParameterName.oauth_version, 1.0);
10 this.CurrentStepParameters.AddParam(OAuthParameterName.oauth_signature_method, HMAC-SHA1);
11 this.CurrentStepParameters.AddParam(OAuthParameterName.oauth_client_ip, 1);
12
13 if (this.CurrentStepParameters.ContainsKey(OAuthParameterName.oauth_token_secret))
14 {
15 this.AuthorizedTokenKey = CurrentStepParameters[OAuthParameterName.oauth_token_secret].Value;
16 }
17
18 if (this.CurrentStepParameters.ContainsKey(OAuthParameterName.oauth_signature))
19 {
20 CurrentStepParameters.Remove(OAuthParameterName.oauth_signature);
21 }
22
23 if (this.CurrentStepParameters.ContainsKey(OAuthParameterName.timestamp))
24 {
25 CurrentStepParameters.Remove(OAuthParameterName.timestamp);
26 }
27 }
28 }

下面是一个测试地址 :http://www.changshu.so/Tencent , 之后等完成绑定后,地址会删除

组件下载地址 : http://files.cnblogs.com/sam251/CSCMS.Secrity.OAuth.rar

后续还有绑定的需要自己去实现了.如果能有通用的方式,我会定时更新,另外,其它OAUTH,比如SINA的,正在研究.

本程序里的OAuthHelper.GenerateTimestamp()及OAuthHelper.UrlEncode都是来自网上其它朋友的方法.

源不源码也没有什么重要了.因为整合在自己的网站里,所以,只是给出了一个DLL,要源码的可以找我,我可以发你.

[转载]构建自己的购物搜索引擎一:写一个简单的

mikel阅读(1211)

[转载]构建自己的购物搜索引擎一:写一个简单的 – 小诺N – 博客园.

记得2010109号,淘宝全网搜索引擎一淘网上线,当时不怎么关注,只是在网站上看到过新闻而己,前两个月,觉得是时候走确定自己以后要走的方向了,于是决定以后加入到搜索的行列中,此时开始关注一淘网的技术,来打开搜索的大门。

那么做搜索引擎要做哪些内容呢,以前有人也这样问过nutch,lucene,hadoop之父Doug Cutting,他回答大致应该分为以下几部分:

1) 攫取(fetching):就是把被指向的网页下载下来。通常就是日常所说的网络爬虫的工作。

2) 数据库:保存攫取的网页信息,比如那些网页已经被攫取,什么时候被攫取的以及他们又有哪些链接的网页等等。

3) 链接分析:对刚才数据库的信息进行分析,给每个网页加上一些权值(比如PageRank,WebRank什么的),以便对每个网页的重要性有所估计。不过,在我看来,索引那些网页标记(Anchor)里面的内容更为重要。(这也是为什么诸如Google Bombing如此高效的原因

4) 索引(Indexing): 就是对攫取的网页内容,以及链入链接,链接分析权值等信息进行索引以便迅速查询。

5) 搜索(Searching): 就是通过一个索引进行查询然后按照网页排名显示

根据这几部分,我们可以自己写一个简单的购物搜索引擎。

第一步:抓取数据

目前开源的网络爬虫有很多,nutch,heritrix都可以算是其中的佼佼者。这里我们先自己动手写一个简单的。

仔细看淘宝的网站,会发现,基本上商品信息比较全的页面全都是以item.taobao开头的,那我们用chrome的开发人员工具分析一下页面结构。

如下图:

图片内容为:<div id=”J_itemViewed” catid=”1512″ data-value=”{“itemId”:”10810071223″,”xid”:””,”pic”:”i3/T1EJahXm4kXXb3Ses._112056.jpg”,”price”:”334800″,”itemIdStr”:””,”title”:”HTC S510e/Desire S g12 安卓2.3系统 大陆行货 联保 现货”}”></div>

我们可以看到,在这个名为J_itemViewed的div中,我们可以取到商品的三个最基本的信息,商 品名称,商品价格,商品图片地址。那么现在的目标很明确,就是在抓取item.taobao的网页,然后找到id为J_itemViewed的div标 签,取出里面的商品信息。那么动手吧。

我们写一个Crawler的类,这个类要做以下几件事:

1.提取网页链接

2.碰到包含有item.taobao的链接,分析网页内容,提取信息,将商品信息存储入本地

首先来看提取网页链接,如下图所示:

提取网页上的链接一般是从一种初始网页开始了,比如说我从www.taobao.com开始,然后分析网 页的结构,取得里面的所包含的链接,然后根据这个链接,去提取更深层次的链接。如此循环,到一定条件停止。在抓取网页的时候,网络蜘蛛一般有两种策略:广 度优先和深度优先。广度优先是指网络蜘蛛会先抓取起始网页中链接的所有网页,然后再选择其中的一个链接网页,继续抓取在此网页中链接的所有网页。这是最常 用的方式,因为这个方法可以让网络蜘蛛并行处理,提高其抓取速度。深度优先是指网络蜘蛛会从起始页开始,一个链接一个链接跟踪下去,处理完这条线路之后再 转入下一个起始页,继续跟踪链接。对于垂直搜索来说,通常采用广度优先策略。下面简单列出抓取与提供信息的方法,具体的看附近里的源程序。

GetUrlThread.class(链接抓取)

GetInfo.class(信息提取)

/**
* 提取信息
*
* @param url
* @return
* @throws ParserException
*/
private void retrieveInfo(String url) throws ParserException,
IllegalArgumentException, IOException {
URL myurl = new URL(url);
Node node = null;
Lexer lexer = new Lexer(myurl.openConnection());
while (null != (node = lexer.nextNode())) {
if (node instanceof TagNode) {
//找到id为J_itemViewed的结点,提取其value值
if ("J_itemViewed".equalsIgnoreCase(((TagNode) node)
.getAttribute("id"))) {
String content = "url:"+url+"\r\n"+"data:"+((TagNode) node).getAttribute("data-value")+"\r\n";
FileOut.instance().write(content);
}
}
}
CommonData.urlInfoed.add(url);//添加到已经提取过的集合中
CommonData.urlInfo.remove(url);//从原集合中移去
}

看一下代码:主要是采用htmlparser,一个html文档解析器来解析下载的内容,得到网页中的<a>标签,去掉邮 件,JavaScript,空锚点等,将提取出来的链接加入到集合中,并将包含有item.taobao的链接加入到要提取网页信息的集合中。

从要提取网页信息的集合中取得url,提取所需要的id为J_itemViewed的div的value值。并将其持久化到本地磁盘。我这里采用的是每一分钟写一个文件夹,每一秒写一下文件。得到的文件内容如下所示:具体看附件)

url:http://item.taobao.com/item.htm?id=7520167497

data: {“itemId”:”7520167497″,”xid”:””,”pic”:”i4/T1ZM86XoFpXXXfrvg2_043733.jpg”,”price”:”279900″,”itemIdStr”:””,”title”:”Konka /康佳 LC32IS68N 32寸液晶电视 高清网络电视机 USB/HDMI”}

第二步:建立索引
我们已经得到所需要的内容了,并将其保存在本地的硬盘上。接下来就是要对这些内容做索引了,说到索引,就不得不提lucene了,下面我们使用开源框架lucene来对刚刚提取出来的文件进行索引各搜索。
先介绍一下lucene。
简单的说呢,lucene就是一个用Java写的全文索引引擎工具包,它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。

我们先来看一下lucene索引的过程

如上图所示,lucene建立索引的步骤大概可以分为以下几步:

将内容信息存入在Field中,将多个Filed组合成Document,然后经过分词,由IndexWriter写入到目录中。

简单介绍一下这几个类,因为看lucene in action自己翻译过来的,可能会理解的不太准确,见谅。

1.IndexWriter

indexWriter 是创建索引的核心组件。它可以创建一个索引,或者打开一个已经存在的索引,也可以添加,删除,更新索引中的文档。indexWriter拥有索引的写的权限,却没有读与查询的权限。IndexWriter需要在某处来存储这些索引,而这个存储的地方就是Directory

2.Directory

Directory类代表Lucene索引存储的地方。它是一个抽象类,其子类可以存储合适的索引。在我们的indexer例子中,我们使用FSDirectory.open来得到合适的具体实现FSDirectory来存储目录下的文件,然后将其传给IndexWriter的构造方法。

Lucene包含了若干个有趣的Directory实现。IndexWriter要想创建索引,则必须通过AnalyZer来解析内容。

3.Analyzer

在文本被索引之前,它必须通过analyzer分析。在IndexWriter的构造方法中,声明了Analyzer,analyzer是负责利用将要被索引的文字来抽取标识符并且消除剩余的。如果内容被索引的部分不是最简单的部分,需要先将里面的内容的简单字符抽取出来,再索引。

Analyzer是一个抽象类,但是Lucene自带一些它的实现.

AnalyzerLucene非常重要的类,它常用于简单的过滤文本。开发者要想反lucene集成到产品中,需要正确的选择analyzer

要想分析就需要文档,即Document,document中包含单独的field用来创建索引。

4.Document

Document类是fields的集合。其可以是web网页,email或者单纯的文本。

5.Field

每一个索引中的document都包含有一个或者多个命名的字Filed。每一个Field都有一个名字与对应的值。

看一下建立索引的代码:(具体的过程看源代码中的Index.class)

建立索引

上图为建立完索引后生成的文件

第三步:搜索

建立好索引之后,我们就可以检索所需要的信息了,还是利用lucene,代码挺简单的:

/**
* 信息搜索
* @author xiaoruoen
*
*/
public class Search {
private Logger logger = Logger.getLogger(Search.class);
public void search(String name){
try {
//打开索引存放的目录
Directory dic = FSDirectory.open(new File(CommonData.index));
//创建索引搜索
IndexSearcher search = new IndexSearcher(dic);
//创建中文分词
Analyzer analyzer = new IKAnalyzer();
//开始搜索
QueryParser parser = new QueryParser(Version.LUCENE_32,"title",analyzer);
Query query = parser.parse(name);
TopDocs hits = search.search(query,100);
//显示搜索结果
logger.info("共找到"+hits.totalHits+"条记录");
logger.info("=====================================================");
for(ScoreDoc scoreDoc:hits.scoreDocs){
Document doc = search.doc(scoreDoc.doc);
logger.info("名称:"+doc.get("title"));
logger.info("价格:"+doc.get("price"));
logger.info("图片:"+doc.get("pic"));
logger.info("网址:"+doc.get("url"));
}
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
}

我们搜索一下“女装”,看一下出来的结果:

INFO (2011-09-14 10:39:15,593) - 共找到63条记录
INFO (2011-09-14 10:39:15,593) - =====================================================
INFO (2011-09-14 10:39:15,625) - 名称:CIMARRON 堆堆领 女装 长袖 舒适显瘦 针织衫
INFO (2011-09-14 10:39:15,625) - 价格:3200
INFO (2011-09-14 10:39:15,625) - 图片:i4/T1sxtSXddGXXachFs3_045631.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=12267518050
INFO (2011-09-14 10:39:15,625) - 名称:2011秋冬装新品 修身风衣双排扣 韩版女装风衣 女装中长款外套
INFO (2011-09-14 10:39:15,625) - 价格:19000
INFO (2011-09-14 10:39:15,625) - 图片:i3/T1sPxWXdhNXXXSNBQ3_050815.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=12523597229
INFO (2011-09-14 10:39:15,625) - 名称:秋装新品2011时尚瑞丽新款女装日韩服饰9482 修身仿皮短外套
INFO (2011-09-14 10:39:15,625) - 价格:6300
INFO (2011-09-14 10:39:15,625) - 图片:i8/T1QSCkXcdoXXX5S5s4_053319.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=12488194244
INFO (2011-09-14 10:39:15,625) - 名称:2011韩莉雅 秋装新款女装 时尚休闲长袖短外套HLY1131
INFO (2011-09-14 10:39:15,625) - 价格:18800
INFO (2011-09-14 10:39:15,625) - 图片:i7/T1rOSlXoBqXXaFtvc1_041102.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=13018744492
INFO (2011-09-14 10:39:15,625) - 名称:2011秋装新款专柜正品女装时尚休闲翻领绣花 短外套 军绿色/咖啡
INFO (2011-09-14 10:39:15,625) - 价格:26200
INFO (2011-09-14 10:39:15,625) - 图片:i1/T1liqlXj8oXXXTRSAT_013057.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=12730707166
INFO (2011-09-14 10:39:15,625) - 名称:水墨佳人女装2011秋装秋款新款新品加厚长袖瑞丽短外套
INFO (2011-09-14 10:39:15,625) - 价格:26200
INFO (2011-09-14 10:39:15,625) - 图片:i1/T1sTV_XadqXXcClX36_060517.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=12915156606
INFO (2011-09-14 10:39:15,625) - 名称:ViVi杂志款 Asuka  Yuri秀粗麻女装秋冬短外套
INFO (2011-09-14 10:39:15,625) - 价格:17900
INFO (2011-09-14 10:39:15,625) - 图片:i2/T1e2hOXddzXXbw55cZ_032608.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=7761546704
INFO (2011-09-14 10:39:15,625) - 名称:2011秋季新款女装羊毛呢妈妈装 宽松版中老年短外套翻领绿色
INFO (2011-09-14 10:39:15,625) - 价格:22900
INFO (2011-09-14 10:39:15,625) - 图片:i3/T1ZB40XopXXXckB9E3_051216.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=9290407443
INFO (2011-09-14 10:39:15,625) - 名称:2011韩版秋冬女装新品 洋气 调皮可爱中长款双排扣风衣 外套
INFO (2011-09-14 10:39:15,625) - 价格:8800
INFO (2011-09-14 10:39:15,625) - 图片:i7/T1KpuaXm4sXXXmcEQZ_033735.jpg
INFO (2011-09-14 10:39:15,625) - 网址:http://item.taobao.com/item.htm?id=13145728284
INFO (2011-09-14 10:39:15,625) - 名称:新款韩版女装风衣外套 修身长袖女士风衣 翻领带拉链风衣外套
INFO (2011-09-14 10:39:15,640) - 价格:15900
INFO (2011-09-14 10:39:15,640) - 图片:i4/T1SPqkXmJjXXcjLEk8_072117.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=12812355549
INFO (2011-09-14 10:39:15,640) - 名称:2011秋装新款女装军绿色工装休闲外套春秋韩版修身女士风衣
INFO (2011-09-14 10:39:15,640) - 价格:19800
INFO (2011-09-14 10:39:15,640) - 图片:i1/T17smlXb0FXXc.0vwZ_031951.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=13031860478
INFO (2011-09-14 10:39:15,640) - 名称:2011春秋装新品 韩版女装风衣外套 长款修身风衣 女士外套大衣
INFO (2011-09-14 10:39:15,640) - 价格:15900
INFO (2011-09-14 10:39:15,640) - 图片:i4/T1WOp.Xh8HXXasdJIZ_032024.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=13031892105
INFO (2011-09-14 10:39:15,640) - 名称:专柜正品女装2011新款春装韩版时尚假俩件带帽风衣
INFO (2011-09-14 10:39:15,640) - 价格:26200
INFO (2011-09-14 10:39:15,640) - 图片:i7/T1zjNYXgtkXXbyJ9g7_065620.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=9100442835
INFO (2011-09-14 10:39:15,640) - 名称:特价 风衣 女 2011新款秋装韩版大码女装时尚热卖修身风衣
INFO (2011-09-14 10:39:15,640) - 价格:13600
INFO (2011-09-14 10:39:15,640) - 图片:i4/T1y6ajXktkXXXw6vM8_070426.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=12525276117
INFO (2011-09-14 10:39:15,640) - 名称:枫之玲 2011秋装新款 修身 时尚 长袖女装风衣
INFO (2011-09-14 10:39:15,640) - 价格:20000
INFO (2011-09-14 10:39:15,640) - 图片:i8/T10d05XodEXXX8fYo4_052120.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=13145948058
INFO (2011-09-14 10:39:15,640) - 名称:以诺 2011秋装 新款 女士 女装 长款 修身 风衣
INFO (2011-09-14 10:39:15,640) - 价格:17800
INFO (2011-09-14 10:39:15,640) - 图片:i1/T1Tmx7XjhEXXbLx7w._113135.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=12637146864
INFO (2011-09-14 10:39:15,640) - 名称:2011夏装新品欧美女装单件套圆领短袖蝙蝠袖 全棉针织衫
INFO (2011-09-14 10:39:15,640) - 价格:3990
INFO (2011-09-14 10:39:15,640) - 图片:i2/T1feX4XjpkXXaI_Fjb_122628.jpg
INFO (2011-09-14 10:39:15,640) - 网址:http://item.taobao.com/item.htm?id=9674621798

这里只是简单的打印出来,有兴趣的可以弄个web,将结果显示出来。

好了,已经初步构建好一个最简单的购物搜索擎了,由于个人水平原因,可能代码写的有点……,但不管怎么说,是一个开始,接下来会慢慢完善的。

源代码下载

程序运行所需文件与搜集到的内容