鉴行志

A blogging framework for hackers.

wordpress配置及网站SEO

| Comments

前一段时间使用wordpress 的一个缓存插件,几天使用下来发现好像没有起到缓存作用。晚上查了下nginx配置,终于找到了为什么。原来是我的nginx配置不对,缓存的路径没有设置对。
找到了问题改正就很容易了。同时也把使用插件生成sitemap.xml也进行了重写,搜索引擎也可以很好的索引相关网页。

 
#如果文件存在直接返回,并设定7天的缓存期
    if (-f $request_filename) {
        expires 7d;
        break;
    }
#初始supercache缓存变量
    set $supercache_file ”;
    set $supercache_uri $request_uri;
#post不访问缓存
    if ($request_method = POST) {
        set $supercache_uri ”;
    }
 
# 因为使用了url重写,因此有查询条件就不访问缓存
    if ($query_string) {
        set $supercache_uri ”;
    }
# 如果有缓存,也不访问缓存
    if ($http_cookie ~* “comment_author_|wordpress|wp-postpass_” ) {
        set $supercache_uri ”;
    }
 
# 如果变量不为空,则访问缓存地址
 
    if ($supercache_uri ~ ^(.+)$) {
        set $supercache_file /wp-content/cache/supercache/$http_host/$1index.html;
    }
 
# 如果缓存存在,则返回缓存文件
    if (-f $document_root$supercache_file) {
        rewrite ^(.*)$ $supercache_file break;
    }
#sitemap 重写,动态生成sitemap.xml
rewrite ^/(sitemap.*)\.xml$ /index.php?feed=$1;
# 其它访问都内 index.php处理
    if (!-e $request_filename) {
        rewrite . /index.php last;
    }
  }

原来网站使用两个域名,两个域名下都是同样的内容。据说这个不利于SEO,搜索引擎也会有惩罚策略。所以就在其中一个域名上设置了301转移重写。

 
server_name  www.xiangjian.info xiangjian.info;
rewrite ^ http://blog.xiangjian.info$uri permanent;

EOF

快速图片上传到flickr,google

| Comments

今天准备上传一张照片到flickr上,在上传页面偶然间看到flickr可以通过邮件上传照片。这个我突然想到:flickr上传文件不太稳定(中国的网络环境),通过邮件上传可以比较稳定的上传,同时会不会有其它的服务也使用
邮件上传照片。果然我在picisa中也找到了通过邮件上传照片的地址。接下来就可以使用邮件将照片发布到多个网络像册中去。

晚上写了如下代码(当然是使用python)::

 
#! coding=utf-8
import smtplib
import os
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
 
family = ['XXXXXXX@photos.flickr.com','XXXXXXXXXXXXX@picasaweb.com']
SMTP_SERVER='XXXXXXXXXx'
SMTP_USER='XXXXXXXx'
SMTP_PASS='XXXXXXX'
SENDER ="XXXXXXXXXXx"
 
 
COMMASPACE = ', '
 
# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'my picture'
msg['From'] = 'xiangjian'
msg['To'] = COMMASPACE.join(family)
msg.preamble = 'my picture'
 
def forward(toAddr, msg):
    server = smtplib.SMTP( SMTP_SERVER )
    server.login( SMTP_USER, SMTP_PASS )
    server.sendmail( SENDER,toAddr , msg )
    server.quit()
    return True
 
def sendpic(dir):
    for root,dirs,files in os.walk(dir):
        for name in files:
            if(name.splitext()[1].lower() in ['.jpg','.png']):
                print name
                fp=open(name,'rb')
                img=MIMEImage(fp.read())
                fp.close()
                msg.attach(img)
                forward(COMMASPACE.join(family),msg)
 
sendpic('.')

将以上代码拷贝到照片文件夹,配置代码中的XXXXXXX。运行就可以将照片发布到多个服务器图床。经测试速度非常快,比通过http上传数据快很多。

本周推荐

| Comments

隔了好长一段时间没有写这个推荐阅读了,现在开始要把这个捡起来。

技术:

去年主要使用memcached,memcached在使用过程中发现,有些东西功能不足:不能选择性持久化;存储的值不能太大,默认为4M;加之缓存结构单一。redis可以很好解决这个问题,可以持久化,提供多种数据类型,支持LIST,这个可以方便进行扩展(我想实现一个简单的MQ) head.js是一个异步加载javascript的js脚本,像它的名字一样,这个脚本只会在head处加载它自己,后台使用javascript异步加载,可以在script比较多的页面中加快加载速度(一般情况下加载javascript浏览器会等待脚本下载)。 这个可以在很多场合使用的javascript包,可以使用IE使用websocket通信。websockets比ajax更好使用到服务器需要推送的环境下。

试用free Aws

| Comments

vps 下个月就到期了,前一段时间看到amazon有免费一年的free aws,决定试用下,明年不用继续用原来的vps使用amazon提供的aws。free aws 安装配置非常方便,很短时间就可以配置好一个可用服务。服务性能也相当不错。

今天下午配置好了服务器,申请了个固定IP,将原来的博客移植到新机器上,以下是使用感受:

  1. amozon云主机性能确实不错,网络速度也很快,不是一般vps速度可比的。
  2. 原来的VPS,使用nginx + movable type,过分想节省资源,但是靠这个节省不了多少资源(就架一个blog用不了多少资源)。相对浪费的时间,一些优化也是在折腾,除了可以学不少东西。
  3. wordpress 配置比movable type容易很多,分分钟就可以搞定。插件多得不得了,安装方便。不过movable type静态页面方式速度会快很多。

道格拉斯-普克抽稀算法

| Comments

道格拉斯-普克抽稀(Douglas-Peucker)算法是一个常用的线抽稀算法,将一条线在不改变大概形状的情况下,使用最少数量的点描述。基本原理如下图:

http://farm5.static.flickr.com/4128/5059015147_9dbced272a_m.jpg

通过Google我找到了两段代码,一段是c#的,一段是python的。现将其分享出来

C#版的:

/// <summary>
/// Uses the Douglas Peucker algorithm to reduce the number of points.
/// </summary>
/// <param name="Points">The points.</param>
/// <param name="Tolerance">The tolerance.</param>
/// <returns></returns>
public static List<Point> DouglasPeuckerReduction
(List<Point> Points, Double Tolerance)
{
if (Points == null || Points.Count < 3)
return Points;
Int32 firstPoint = 0;
Int32 lastPoint = Points.Count - 1;
List<Int32> pointIndexsToKeep = new List<Int32>();
//Add the first and last index to the keepers
pointIndexsToKeep.Add(firstPoint);
pointIndexsToKeep.Add(lastPoint);
//The first and the last point cannot be the same
while (Points[firstPoint].Equals(Points[lastPoint]))
{
lastPoint--;
}
DouglasPeuckerReduction(Points, firstPoint, lastPoint,
Tolerance, ref pointIndexsToKeep);
List<Point> returnPoints = new List<Point>();
pointIndexsToKeep.Sort();
foreach (Int32 index in pointIndexsToKeep)
{
returnPoints.Add(Points[index]);
}
return returnPoints;
}
/// <summary>
/// Douglases the peucker reduction.
/// </summary>
/// <param name="points">The points.</param>
/// <param name="firstPoint">The first point.</param>
/// <param name="lastPoint">The last point.</param>
/// <param name="tolerance">The tolerance.</param>
/// <param name="pointIndexsToKeep">The point index to keep.</param>
private static void DouglasPeuckerReduction(List<Point>
points, Int32 firstPoint, Int32 lastPoint, Double tolerance,
ref List<Int32> pointIndexsToKeep)
{
Double maxDistance = 0;
Int32 indexFarthest = 0;
for (Int32 index = firstPoint; index < lastPoint; index++)
{
Double distance = PerpendicularDistance
(points[firstPoint], points[lastPoint], points[index]);
if (distance > maxDistance)
{
maxDistance = distance;
indexFarthest = index;
}
}
if (maxDistance > tolerance && indexFarthest != 0)
{
//Add the largest point that exceeds the tolerance
pointIndexsToKeep.Add(indexFarthest);
DouglasPeuckerReduction(points, firstPoint,
indexFarthest, tolerance, ref pointIndexsToKeep);
DouglasPeuckerReduction(points, indexFarthest,
lastPoint, tolerance, ref pointIndexsToKeep);
}
}
/// <summary>
/// The distance of a point from a line made from point1 and point2.
/// </summary>
/// <param name="pt1">The PT1.</param>
/// <param name="pt2">The PT2.</param>
/// <param name="p">The p.</param>
/// <returns></returns>
public static Double PerpendicularDistance
(Point Point1, Point Point2, Point Point)
{
//Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)|   *Area of triangle
//Base = v((x1-x2)2+(x1-x2)2)                               *Base of Triangle*
//Area = .5*Base*H                                          *Solve for height
//Height = Area/.5/Base
Double area = Math.Abs(.5 * (Point1.X * Point2.Y + Point2.X *
Point.Y + Point.X * Point1.Y - Point2.X * Point1.Y - Point.X *
Point2.Y - Point1.X * Point.Y));
Double bottom = Math.Sqrt(Math.Pow(Point1.X - Point2.X, 2) +
Math.Pow(Point1.Y - Point2.Y, 2));
Double height = area / bottom * 2;
return height;
//Another option
//Double A = Point.X - Point1.X;
//Double B = Point.Y - Point1.Y;
//Double C = Point2.X - Point1.X;
//Double D = Point2.Y - Point1.Y;
//Double dot = A * C + B * D;
//Double len_sq = C * C + D * D;
//Double param = dot / len_sq;
//Double xx, yy;
//if (param < 0)
//{
//    xx = Point1.X;
//    yy = Point1.Y;
//}
//else if (param > 1)
//{
//    xx = Point2.X;
//    yy = Point2.Y;
//}
//else
//{
//    xx = Point1.X + param * C;
//    yy = Point1.Y + param * D;
//}
//Double d = DistanceBetweenOn2DPlane(Point, new Point(xx, yy));
}

python 版的:

# pure-Python Douglas-Peucker line simplification/generalization
#
# this code was written by Schuyler Erle <schuyler@nocat.net> and is
#   made available in the public domain.
#
# the code was ported from a freely-licensed example at
#   http://www.3dsoftware.com/Cartography/Programming/PolyLineReduction/
#
# the original page is no longer available, but is mirrored at
#   http://www.mappinghacks.com/code/PolyLineReduction/
"""
>>> line = [(0,0),(1,0),(2,0),(2,1),(2,2),(1,2),(0,2),(0,1),(0,0)]
>>> simplify_points(line, 1.0)
[(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)]
>>> line = [(0,0),(0.5,0.5),(1,0),(1.25,-0.25),(1.5,.5)]
>>> simplify_points(line, 0.25)
[(0, 0), (0.5, 0.5), (1.25, -0.25), (1.5, 0.5)]
"""
import math
def simplify_points (pts, tolerance):
anchor  = 0
floater = len(pts) - 1
stack   = []
keep    = set()
stack.append((anchor, floater))
while stack:
anchor, floater = stack.pop()
# initialize line segment
if pts[floater] != pts[anchor]:
anchorX = float(pts[floater][0] - pts[anchor][0])
anchorY = float(pts[floater][1] - pts[anchor][1])
seg_len = math.sqrt(anchorX ** 2 + anchorY ** 2)
# get the unit vector
anchorX /= seg_len
anchorY /= seg_len
else:
anchorX = anchorY = seg_len = 0.0
# inner loop:
max_dist = 0.0
farthest = anchor + 1
for i in range(anchor + 1, floater):
dist_to_seg = 0.0
# compare to anchor
vecX = float(pts[i][0] - pts[anchor][0])
vecY = float(pts[i][1] - pts[anchor][1])
seg_len = math.sqrt( vecX ** 2 + vecY ** 2 )
# dot product:
proj = vecX * anchorX + vecY * anchorY
if proj < 0.0:
dist_to_seg = seg_len
else:
# compare to floater
vecX = float(pts[i][0] - pts[floater][0])
vecY = float(pts[i][1] - pts[floater][1])
seg_len = math.sqrt( vecX ** 2 + vecY ** 2 )
# dot product:
proj = vecX * (-anchorX) + vecY * (-anchorY)
if proj < 0.0:
dist_to_seg = seg_len
else:  # calculate perpendicular distance to line (pythagorean theorem):
dist_to_seg = math.sqrt(abs(seg_len ** 2 - proj ** 2))
if max_dist < dist_to_seg:
max_dist = dist_to_seg
farthest = i
if max_dist <= tolerance: # use line segment
keep.add(anchor)
keep.add(floater)
else:
stack.append((anchor, farthest))
stack.append((farthest, floater))
keep = list(keep)
keep.sort()
return [pts[i] for i in keep]
if __name__ == "__main__":
import doctest
doctest.testmod()

在vps上安装dabr

| Comments

前几天twa.sh网站访问不了,有一段时间没有上过twitter了。因为知道twa.sh是dabr搭建的,我的vps也有PHP环境,决定架一个dabr. 主要按照http://zou.lu/dabr/ 写的搭建方法,完成dabr环境搭建。有一些小的改动主要是PHP环境配置问题,PHP默认有些包没有使用,没有默认的时区设置。这些可以看nginx输出的的错误日志。使用tail -f /srv/log/nginx/error.log 命令就可以查看,改下配置就可以了。

话说linux系统很不错,命令行开始可能感觉上手不易,但linux的配置,日志输出都比较固定,查看相应的信息基本上可以看到问题是出在哪了。这点比Windows强的地方,有时真不知道错误出在哪。

这几天不知道为什么php-cgi在fast-cgi下跑不很稳定,过一段时间就挂掉.不知道是不是系统的问题,我的vps安装的是archlinux。写了个bash脚本扔到/etc/cron.hourly目录中定时检查php-cgi进程是否存在,否则重启php-cgi。暂时就这样了,慢慢再找不稳定的原因。脚本:

if ['ps x |grep php--cgi|wc -l'=2];then
echo start php-cgi
/etc/rc.d/fastcgi start
fi;

更新

| Comments

好久没有更新了,上次更新还是4月份从青海回来。主要这段时间工作太忙,基本上都在外面出差,生活没有规律。现在有点问题,鸭梨很大,体重保持在140,要想办法减,肚子已经有点明显胖,原来坚持了几年的跑步也中断了。这些好的习惯要逐渐再拾起来。

blog我名字改了叫作”鉴行志”,鉴:就是镜子,希望这个是我的影子,能够看到我学习生活中的东西,李世民有一句名言就有这个字。其实我原来名字也是用这个字,小学和初中也是这个字,后来不知道怎么就改为建了。行:是我的辈份,一般不用在名字中。这个就是我取这个blog名字的原因。

总结一下这段时间的工作吧:

累:前段时间一直到各个油田部署,基本上总是在加班,还没有找到一种可以让自己工作轻松点的方法。路还很长,我还要继续摸索。

现在oracle spatial和arcgis sde结合使用已经有一些心得了。这个不是oracle spatial好还是arcgis sde好的问题,我也无意卷入这两种观点的论战。那是这两种公司售前做的事情,不论那一种方案的性能好,哪一种方案支持的数据类型多,这种争论毫无意义。重要的是这明白这两种方案的优缺点,具体问题具体分析。现在我做的项目中推荐使用oarcle spatial做存储,并在sde中注册。oracle spatial是在DB层做数据源整合应该是最实用的方案(有时间会专门写一篇说明)。

Google地图的使用,现在可以下载google地图,在项目中使用,这样就不用太关注基础数据了,基础数据使用google地图数据完全够了。我们现在做GIS的人太少,现在人手可以把注意力放到做专业数据的应用上。尽快能在GIS应用上做出一定的成果。

在数据库层在做数据缓存功能,目前在项目中使用memcache做了数据缓存,在数据库性能不变情况下改善数据访问能力。当前还不完善,Key-Value库在项目中的应用应该会多一些,也是将来应用的一个方向。

集中主意力,现在事情太杂,太分散。精力很难集中,事情反而没有做多少,还经常感觉事情太多。上班时间要少开聊天工具,把精力专注在工作上。尽量在上班时间内完成工作。决不拖拉。

昨天整了下vps,还比较顺利。google adsense也申请通过了,在我的vps上架设了dabr,可以放心上twitter了。在vps上安装还是有点折腾的,linux 系统某些方面还是不错的。

关于地震

| Comments

上周从青海回来,昨天青海玉树发生地震。新闻上报地震是7.1级大地震,好奇上 usgs (美国国家地震局),看看地震信息。结果看到地震是6.9级,不知为何中国跟美国测的结果有差别。看到校舍的抗震级别是7级就明白了,有些事明白就行,不能说明白了。

十种GIS矢量数据转换工具

| Comments

做GIS这一块的工作,GIS空间数据的转换处理工作会比较多.下面整理了这几个用过的和知道的一些GIS空间数据转换工具,写了下面的文章.文章也标题党一把,取名"十种GIS矢量数据转换工具",希望对大家有用.

Safe FME 是最专业的GIS数据转换工具之一,还支持GIS数据资源的整合。支持大量的GIS空间数据源(应该是支持最多的),而且还提供二次开发接口可以支持用户特定的数据转换整合。

FME

ArcGIS是全球最成功的GIS软件产品,提到GIS不可避免会提到ESRI的ArcGIS。ArcGIS的ToolBox中有数据转换模块支持大量数据(标准的和ArcGIS支持的数据类型)间的转换。另外说一点ArcGIS ToolBox中的数据转换模块似乎是用的FME技术?如果安装了ArcGIS后,再安装FME会在ArcGIS ToolBox中数据转换菜单中加入一个FME工具项,可以结合ArcGIS ToolBox中的工具转换GIS矢量数据。

ArcGIS

FDO(Feature Data Object)空间数据访问引擎,属于OSGEO的一个开源子项目,由autodesk捐出。autodesk Mapguide的空间数据访问引擎,提供一套数据访问标准,支持用户编写基于FDO的引擎可以访问多种空间数据源。FDO API 提供C#,java接口,可以使用FDO技术进行数据转换。

FDO2FDO基于FDO技术写的空间数据转换程序,由sl-king(sl-king还开发了免费的oracle fdo provider)开发,免费软件.

FDO2FDO

FDO ToolBox基于FDO技术,使用.net 2.0技术编写,做很多功能,包含数据的编辑管理等,支持空间数据转换.这个是开源程序,托管在google code上.

基于fdo技术,有数据转换程序,我没有用过,在OSGEO FDO官网上看到过介绍.

  • Autodesk(Map 3d,civil 3d) bulk copy

Autodesk 产品中的批量数据转换工具,基于FDO.可以实现多种空间数据间的转换. bulkcopy

  • gdal/ogr API

OGR是GDAL的一部分(矢量数据).OGR是一个读取和处理GSI矢量数据的库。这个库可以读取和处理多种流行的矢量数据.

命令行程序,核心基于gdal,可以接受gdal支持的数据源间的数据互转换,功能强大。不过命令行的参数众多,很难一次写正确。这个是跨平台的。

专门为ogr2ogr设计的一个GUI界面,核心还是ogr2ogr。通过它的GUI界面可以定制数据转换参数,方便用户使用.界面基于QT,可方便生成命令行参数.

ogr2GUI

可能会有遗漏,mapinfo,国产厂商的GIS(supermap,mapgis)产品,数据转换模块不太熟习,因此不在上面列举。

总结这一系列转换工具主要包含三个核心转换库:FME(arcgis数据转换模块据说是使用FME技术?待考),FDO,GDAR/OGR.FME是商业软件,支持格式最多,转换工具灵活,大型工程空间数据转换首选.FDO是开源,背后有autodesk支持,前景很好(使用过程中使用FDO技术转换的shp数据部分软件无法识别,尽量不要使用FDO转出shp数据).GDAR/OGR老牌空间数据类库,支持各种编程语言.

使用javascript方法给后台WCF服务直接post对象

| Comments

一直没有弄清楚,WCF如何使用post方法自动反序列化对象,看了几篇文章,终于搞清楚了怎么使用post方法进行对象传值。

下面直接使用WCF特性做元数据的自定义转换

定义元数据契约定义:

[DataContract(Name = "person")]
public class person
{
[DataMember(Name="Name")]
public string Name
{
get;
set;
}
[DataMember(Name = "Age")]
public int Age
{
get;
set;
}

服务描述:

[OperationContract]
[WebInvoke(UriTemplate = "/doit2",ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)]
bool testpost(person p);

注意使用Post方法,post的BodyStyle必须为Wrapped,否则不能正常取到反序列化后的对象。