Category: Coding

六月 25th, 2017 by lanxinxichen@126.com

一、 使用ffmpeg找出视频插入的关键帧

起因:某天晚上看一个科技评测节目,该节目宣称只要能够在视频中找到视频中插入的某一帧无关内容,就可以获得相应的奖品。我想了想应该是可以用代码实现的:

  1. 拿到该视频的文件

使用python3的一个工具you-get就能够做到。不过稍有曲折,我使用you-get去下载B站和优酷的视频都下载失败了,好在在该测评节目微博上找到了另外一个视频资源链接,使用you-get顺利下载下来,视频是640×360的,十分钟内容一共60M的MP4格式。

  1. 将视频逐帧抽离成为图片。

我先按照原样抽离,即抽离成640×360的图片,一共生成了8,988个文件,大小1.80 GB,不禁感慨视频压缩格式确实厉害啊,这压缩了多少倍啊,另外我考虑到可能更小的缩略图应该也拥有足够的分辨特征,所以也按照64×36的分辨率抽离了更小的缩略图
大图抽帧
640×360逐帧抽离的图片截图
小图抽帧
64×36逐帧抽离的图片截图

  1. 对比任意相邻图片的相似度。

图像相似度算法我没具体研究过,直接用的github上面的项目:https://github.com/MashiMaroLjc/Learn-to-identify-similar-images
一共有有四种算法,具体中文的文章可以参看链接:
https://segmentfault.com/a/1190000004467183 
我使用了不同的算法得到的不同的结果:
由于之前excel的制图删掉了,只能用当时程序计算的文本信息凑合了,计算出来的相似度大致就是如下的数字列表。
照片相似度对比结果

  1. 绘图寻找关键帧

其实就是根据特征去拟合一条折线,能够正确反映出异常的关键帧在哪里。
关键帧表格绘制
其实这一步,我做了两三个小时,为了选择最佳的算法和最佳的效果,只有下图能够直截了当的反映出异常的帧在哪里,后来我想了想,如果加入跳帧的对比,比如第一帧和第三帧的特征,就能够更加准确的找到关键帧的位置。
 
http://mp.weixin.qq.com/s/K2YCm8QwnpI7dNTs048Jbg
 

二、 ffmpeg做音频剪辑命令

叠加两个声音,并按照第一个声音的长度截取音乐,然后输出16k,单声道,声音质量为4的音乐:

ffmpeg -i example1.wav -i example2.wav -filter_complex amix=inputs=2:duration=first -ar 16k -ac 1 -q:a 4 output.wav

 
参考:https://ffmpeg.org/ffmpeg-filters.html
 
重复某个音频文件4次并截取80秒的音频数据

ffmpeg -stream_loop 4 –I example.wav -c copy -t 80 output.wav

 
从00:00:15开始截取音频、视频,截取5s,然后原样输出到文件中

ffmpeg -ss 00:00:15 -t 00:00:05 –I example.mp4 -vcodec copy -acodec copy output.mp4

 
pcm(已知pcm文件格式为16k 16bit 单声道)转换到固定格式的wav文件中

ffmpeg -f s16le -ar 16k -ac 1 -i tts_file_119.pcm -ar 16k -ac 1 tts_file_119.wav

对音频文件增加渐入渐出过滤效果(淡入从0秒开始,持续10秒,淡出从50秒开始,持续10秒,设定音乐音量为2, -y为覆盖已存在文件)

ffmpeg -i input.mp3 -af “afade=t=in:ss=0:d=10,afade=t=out:st=50:d=10,volume=volume=0.2” -t 60 output.mp3 –y

更多声音过滤器:http://ffmpeg.org/ffmpeg-filters.html
 
设定背景音乐,循环播放并增加淡入淡出效果

ffmpeg -stream_loop 4 -iinput.wav -af “afade=t=in:ss=0:d=10,afade=t=out:st=50:d=10,volume=volume=0.2” -t 80 output.wav

 
一般来讲 ffmpeg的文件后缀都是自适应的,比如你设置的输出格式是mp3,那么文件就能自动转换成该格式的文件,具体的采样率等参数需要单独去设置调整。

Posted in Coding, Python Tagged with: ,

一月 14th, 2017 by lanxinxichen@126.com

TypeError: not enough arguments for format string

使用Python连接数据库的时候,采用的非常非常轻量级的torndb,甚至于事务都不支持,所以用”select * from table where condition=’%s'” % (condition,)

因为用的比较原生,所以各种问题接连不断,最最恶心的就是字符串转义造成的一些列原因.

先采用

condition = re.escape(condition)

能对特殊字符进行转义,但是还是有问题,又报错TypeError: not enough arguments for format string 直到认真看输入的condition字符串的时候,才发现问题所在之处: condition中有% 需要替换%为%%才能正常执行,

condition= condition.replace('\%', '%%')

其实标题有问题,不只是操作数据库,只不过在操作数据库时候,忽略的字符串本身的内容,一直在错误的寻找解决方案.

Posted in Coding, Python, 数据库 Tagged with: ,

九月 21st, 2016 by lanxinxichen@126.com

 
最近做的一个二开开源项目,项目本身使用的是“优雅”的laravel框架开发的,我也顺带着了解了一下laravel框架。由于项目需要多平台的会员数据统一,所以第一时间想到用UCenter进行会员整合。
上次使用UCenter的时候还是2014年,那时候的会员整合我不负责,也就没在这上面下太多功夫,终于这次揭开了UCenter神秘的面纱。
安装后的首页
ucenter1
应用列表
ucenter2
首先,先添加一个新应用,填写相应的表单。应用接口文件名称需要填写应用的路由地址,这个可以先空着,填写完毕之后保存,此时的通信情况应该是通信失败的。
在github上面我们能找到好几个关于laravel – Ucenter的项目,我自己根据看根据别人的项目修改了bug:https://github.com/lanxinxichen/laravel5-ucenter ,另外推荐尝试https://github.com/binaryoung/ucenter,个人感觉比我fork的这个好一些。

安装UCenter

只要在你的 composer.json 文件require中加入下面内容,就能获得最新版.
“goodspb/laravel5-ucenter”: “dev-master”
然后需要运行 “composer update” 来更新你的项目
安装完后,在 app/config/app.php 文件中找到 providers 键,添加:
Goodspb\Laravel5Ucenter\UcenterServiceProvider::class,
找到 aliases 键,添加:
‘Ucenter’ => Goodspb\Laravel5Ucenter\Facades\Ucenter::class,
 
他这个版本config::get是有问题的,可以参看我的修改记录进行修改。
https://github.com/lanxinxichen/laravel5-ucenter/commit/01d4714174ae4acba3aa9fcfef6bfb6b931e1aa2
在config文件中增加一个ucenter.php的文件,然后添加以下内容
 
<?php
return [
‘url’       => env(‘ucenter_url’,’/api/ucapi’), // 网站UCenter接受数据地址
‘api’       => env(‘ucenter_api’,’http://www.ucn.net’), // UCenter 的 URL 地址, 在调用头像时依赖此常量
‘connect’   => env(‘ucenter_connect’,’mysql’), // 连接 UCenter 的方式: mysql/NULL, 默认为空时为 fscoketopen()
‘dbhost’    => env(‘ucenter_dbhost’,’localhost’), // UCenter 数据库主机
‘dbuser’    => env(‘ucenter_dbuser’,’root’), // UCenter 数据库用户名
‘dbpw’      => env(‘ucenter_dbpw’,”), // UCenter 数据库密码
‘dbname’    => env(‘ucenter_dbname’,’ucenter’), // UCenter 数据库名称
‘dbcharset’ => env(‘ucenter_dbcharset’,’utf8′),// UCenter 数据库字符集
‘dbtablepre’=> env(‘ucenter_dbtablepre’,’uc_’), // UCenter 数据库表前缀
‘key’       => env(‘ucenter_key’,’76bc3bbK5aoWVrb26juV1vk4uq4c2aSNQvzv70Zs12′), // 与 UCenter 的通信密钥, 要与 UCenter 保持一致
‘charset’   => env(‘ucenter_charset’,’utf-8′), // UCenter 的字符集
‘ip’        => env(‘ucenter_ip’,’127.0.0.1′), // UCenter 的 IP, 当 UC_CONNECT 为非 mysql 方式时, 并且当前应用服务器解析域名有问题时, 请设置此值
‘appid’     => env(‘ucenter_appid’,2), //当前应用的 ID
‘ppp’       => env(‘ucenter_ppp’,20), //当前应用的每页数量
];
注意:上面的配置根据自己实际环境进行修改。
 

配置路由

在项目中的相应位置添加通信api的路由
Route::any(Config::get(‘ucenter.url’), function(){
return \Goodspb\Laravel5Ucenter\UcenterApi::execute();
});
 
这时候就可以返回UCenter应用管理中心,把之前空的接口文件路由修改为自己定义的路由,比如我设置的路由是/api/ucapi那么在填写的时候需要填写ucapi,不带/api/。因为我在这里被坑了,所以附上通信接口调试文章https://my.oschina.net/ppss/blog/744743    
ucenter3
通信成功!
 
可以通过以上链接里面的办法把接口通信调试成功,然后就是实现自己的业务逻辑了。

Posted in PHP Tagged with: , ,

九月 21st, 2016 by lanxinxichen@126.com

laravel
最近一直在专心复习java,而且打算完全转型java,所以自认为这是我PHP项目生涯的末期。然而在这段日子里,我有幸接触了大名鼎鼎的Laravel。
从开始接触到现在也不过短短三天时间,只简单把运行原理搞懂了,所以如果本文有失偏驳,与您观点不符,那实在是抱歉,反正我也不改。
接触Laravel之前,只听外界她的优雅,接触之后才感慨实至名归。当然也发现了另外一个与优雅齐名的缺点:慢。本篇文章并不打算介绍Laravel的入门,单纯吐槽一下最近使用的真实感受。
Laravel 对PHP版本要求比较高,放眼国内,虚拟主机的php版本都还停留在5.3的水平,再加上composer这种新概念的冲击(还有网络访问比较困难),Laravel在国内出现了水土不服的现象。熟悉java,Python,Nodejs的人对包管理一定不会陌生,java的Maven,Python的pip,Nodejs的npm都是使用起来特别爽的,简简单单的命令行就能实现下载/更新依赖了,composer也是如此,只不过是专门针对PHP的包管理。Laravel 注重快捷高效的开发,当你通过composer全局安装Laravel,并将其加入到环境变量之后,直接通过“laravel new project”就能创建项目了,并且内置了artisan实用的命令行工具,配合Phpstorm让开发效率进一步提升。配置Phpstorm 配置artisan命令行
Laravel依托于composer,所以项目搬迁以及升级都会非常方便。方便是建立在熟悉并知道如何使用的情况下,我在整合laravel和UCenter的时候也遇到了很多问题,一来是文档不够完善,二来就是提问的人太少了,很难找到解决问题的办法,只能靠自己一点儿一点儿琢磨。
Laravel 实在是太慢了。只要在google上面搜索laravel slow,就能找到很多吐槽文章。针对我目前这个项目,平均每个网页访问时间都要在1.3~1.7秒,这速度根本不能忍吧。尽管了我已经做了一些优化工作,比如routes cache,config cache,class optimize,开启opcache,也只是略微改善,并没有提高多少速度,相比以前开发的项目,她的速度简直是惨不忍睹。想到这里我把标题中的“优雅”两个字删掉了。据说Lumen是速度很快,没有亲自体验。
客观来讲,对Laravel接触时间还是太短了,我这只能算个Laravel的初体验。毋庸置疑的是,借助composer上面优秀的库,Laravel对大项目的开发速度肯定会有所提高,包括她对RESTful 的友好支持都是让人心动的,对于小项目而言,选择其他框架可能是更好的选择。
 
最后,恶趣味的我专门在博客园找了一篇对Laravel的吐槽十分精彩的文章(包括评论):
http://www.cnblogs.com/yjf512/p/4031782.html#top

Posted in PHP Tagged with: ,

六月 22nd, 2016 by lanxinxichen@126.com

301全站跳转
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.old\.net$ [NC]
RewriteRule ^(.*)$ http://www.new\.net/$1 [L,R=301,NC]
其中 http://不能省略,不然出现绝对路径加在跳转重写前面的
.htaccess 正则表达式
# 位行首表示注释
[F] Forbidden (禁止):
命令服务器返回403 Forbiden 错误给用户浏览器
[L] Last rule (最后一条规则)
告诉服务器在本条规则执行完后停止重写URL
[N] Next (下一条规则)
告诉服务器继续重写,指导所有重写指令都执行过
[G] Gone (丢失)
命令服务器返回410 GONE(no longer exists)错误消息
[P] Proxy (代理)
告诉服务器通过mod_proxy模块处理用户请求
[C] Chain (捆绑)
告诉服务器将当前的规则和前面的规则进行捆绑
[R] Redirect(重定向)
告诉服务器发出重定向消息,以便用户浏览器发出rewitten/modified(重写/修改) 请求
[NC] No Case(不区分大小写)
对客户端请求的URL不区分大小写
[PT] Pass Through(放行)
让mod_rewrite 模块将重写的URL传回给Apache做进一步处理
[OR] Or(逻辑或)
用逻辑“或”将两个表达式连接在一起,如果结果为“真”,则会应用后继的相关规定
[NE] No Escape (禁止转义)
命令服务器在输出时禁用转义字符
[NS] No Subrequest(禁用子请求)
如果存在内部请求,则跳过当前命令
[QSA] Append Query String(追加查询字符串)
命令服务器在URL末尾追加查询字符串
[S=x] Skip(跳过)
如果满足某指定条件,则跳过后面第X条规则
[E = Variable:value](环境变量)
命令服务器交将值 value赋给变量 variable
[T=MIME-type] Mime Type (MIME 类型)
声明目标资源所属的MIME类型
[]
匹配一个字符集,如[xyz]可以匹配x,y或者z
[^]
如:[xyz]+ 会以任何顺序,次数匹配x,y,z的出现
[a-z]
连字符(-)表示匹配从字母a到z的所有字符串
a{n}
指定字母a出现的次数为N次,满足该条件时匹配。如x{3}仅与xxx匹配
a{n,}
指定字母a出现的次数至少为N次,例如X{3}可以与XXX或者xxxxx等级匹配
a{n,m}
指定a出现的次数至少为n到m次
()
用于将正则表达式分组,满足第一组正则表达式的字符串会被存储在变量$1中,以此类推。如果括号呈的不是正则表达式,例如(myname)?press 将能够匹配有或者没有myname前缀的press
^
位于行首。注意:和中括号中的[^]意义不同
$
位于行末
?
例如 world?会匹配world或者worldx,而如 wor(ld)? 会匹配wor或者world,又如:x?会匹配“空字符”或者一个x
!
逻辑非。例如:”!myname”将会匹配除了“myname”以外的所有字符串
.
表示任意字符

命令apache“不要”重写URL,例如:”xxx.domian.com.* -[F]”
+
匹配至少一个任意字符,例如:G+ 匹配以G开头,并且后面至少有一个字符的字符串
*
匹配零个或多个字符,例如:“。”匹配任意字符
|
逻辑“或”。与[OR]不同的是,它是匹配字符串,例如(x|y)匹配x或者y
\
转义字符。可以转义左括号(,尖括号^,美元符号 $, 感叹号 !点 。 星号 *,管道符号|等,
\.
转义为点字符(点字符在正则表达式中可以匹配任意字符)
/*
零个或多个字符
.*
零个或多个任意字符(即匹配任意字符,包括空字符)
^$
匹配“空字符”,“空行”
^.*$
匹配任意字符串(仅限一行)
[^/.]
匹配既非“正斜杠”也不是“点”的任意字符
[^/.]+
匹配第一个字符既非“正斜杠”也不是“点”,后继字符可以是“正斜杠”或者“点”字符串
http ://
匹配 http ://
^domain.*
匹配以”domain”开始的字符串
^domain\.com$
仅匹配 “domain.com”
-d
测试字符串是否已存在的目录
-f
测试字符串是否是已经存在的文件
-s
测试字符串所指文件是否有“非零”值
以下为相关例子:
1。将.htm 页面映射到 .php
Options +FollowSymlinks
RewriteEngine On
RewriteRule ^(.*)\.htm$ $1.php [NC]
2。临时重定向(R=302)与永久重定向(R=301)
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)\.htm$ $.php [R,NC,L]
•该RewriteRule能够将.htm静态页面重定向到.php动态页面
•如果通过.htm进入,浏览器地址栏会自动转为.php,这也是重定向的本质
•必须保证服务器上有对应的.php,否则会404
•浏览器和搜索引擎可以同时通过.htm和.php访问网页
•如果该目录上存在.htm,将被忽略
•RewriteBase定义了重写基准目录。
•例如,如果你将虚拟站点设置在/var/www目录下,删除这行将会导致重定向到h ttp://yourdomain.com/var/www/1.php 。显然这是找不到的,而且你也不会希望用户看见你的服务器的目录结构。
•再举个例子,如果RewriteBase /base/,那么将会重定向到h ttp://yourdomain.com/base/1.php 。
•对于重写基准目录,我们还可以通过将$1.php变成/$1.php实现直接变换,这时就可以将RewriteBase省略。
•字母R表示临时重定向,相当于[R=302,NC]。关于重定向代码,请参考h ttp://lesca.me/archives/htaccess-appendix.html 《HTTP协议重定向编码》
•字母L表示如果能匹配本条规则,那么本条规则是最后一条(Last),忽略之后的规则。
永久得定向 R=301
RewriteEngine On
RewriteRule ^(.*)$ h ttp://newdomain.com/$ [R=301,NC,L]
•这个规则告诉浏览器和搜索引擎,网站地址发生了永久性变更,用户的URL请求将会被发送给新的域名(主机)处理。
•由于是重定向到新的主机地址,RewriteBase也就没有出现的必要了。
3.为什么要用重定向?——重定向和URL重写的区别
•通过重定向,浏览器知道页面位置发生变化,从而改变地址栏显示的地址
•通过重定向,搜索引擎意识到页面被移动了,从而更新搜索引擎索引,将原来失效的链接从搜索结果中移除
•临时重定向(R=302)和永久重定向(R=301)都是亲搜索引擎的,是SEO的重要技术
•URL重写用于将页面映射到本站另一页面,若重写到另一网络主机(域名),则按重定向处理
长短地址转换
利用URL重写,我们可以很方便地实现长短地址的转换,但是用重定向就不合适了。
RewriteEngine On
RewriteRule ^grab /public/file/download/download.php
若访问
h ttp://mysite/grab?file=my.zip
则会执行该页面:
h ttp://mysite/public/files/download/download.php?file=my.zip
去掉www
options +FollowSymlinks
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ h ttp://$1/$1 [R=301,NC,L]
加上www
optionEngine On
RewriteCond %{HTTP_HOST} ^(.*)$
RewriteRule (.*) h ttp://www\.%1/$1 [R=301,L]
支持多域名访问
如果你不凑巧买到了不支持多域名的主机,那么.htaccess或许可以帮助你。现在假设你有域名domain-one.com和domain-two.com,并且在服务器根目录有对应文件夹one和two,那么通过下面的改写就能让Apache同时接受者两个域名的请求:
RewriteCond %{HTTP_HOST} domain-one.com
RewriteCond %{REQUEST_URI} !^/one
RewriteRule ^(.*)$ /one/$1 [L]
RewriteCond %{HTTP_HOST} domain-two.com
RewriteCond %{REQUEST_URL} !^/two
RewriteRule ^(.*)$ /two/$1 [L]
改写查询字符串QUERY_STRING
查询字符串是指URL请求中“问号”后面的部分。比如,h ttp://mysite/grab?foo=bar ?部分就是查询字符串,其中变量名是foo,值是bar。
1.利用QSA转换查询字符串QUERY_STRING
QSA标志( Query String Appending)用于在URI中截取查询字符串,这个截取操作是通过小括号正则表达式实现的:
RewriteEngine On
RewriteRule /pages/(.+) /page.php?page=$1 [QSA]
•将会把请求/pages/123?one=two 映射到 /page.php?page=123&one=two
•注意几乎是相同的,除了“问号”变成了“与”符号
•如果没有QSA标志,那么会映射到/page.php?page=123。
•如果没有用到小括号正则表达式,就不需要QSA
•小括号正则表达式可以截取查询字符串中的内容,但是如果没有开启QSA标志,那么在/page.php?page=$1中“问号”之后将会被剥离丢弃。这种特性可以用于实现“剥离查询字符串”
通过QSA,我们可以将简单链接/simple/flat/link/ 映射成 server-side.php?first-var=flat&second-var=link
RewriteEngine On
RewriteRule ^/([^/]+)/([^/]+)/? /index.php?first-var=$1&second-var=$2 [QSA]
利用RewriteCond改写查询字符串QUERY_STRING
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.*)
RewriteRule ^grab(.*) /page.php?bar=%1
该规则将访问请求htt p://mysite/grab?foo=bar转换为htt p://mysite/page.php?bar=bar
RewriteCond用于捕获查询字符串(QUERY_STRING)中变量foo的值,并存储在%1中
QUERY_STRING是Apache定义的“变量=值”向量(数组)
QSA与RewriteCond一起用
RewriteEngine On
RewriteCond %{QUERY_STRING} foo=(.+)
RewriteRule ^grab/(.*) /%1/index.php?file=$1 [QSA]
•会把/grab/foobar.zip?level=5&foo=bar 映射到 /bar/index.php?file=foobar.zip&level=5&foo=bar
•转换后根目录是bar目录
•foobar.zip?level=5中的“问号”变成了foobar.zip&level=5中的“与”符号

剥离查询字符串

只需在要开始剥离的链接后面加个“问号”,并且不要启用QSA标志,就可剥离查询字符串
RewriteEngine On
RewriteCond %{QUERY_STRING} .
RewriteRule foo.php(.*) /foo.php? [L]
用.htaccess阻止User-agent
什么是User-agent?User-agent用于浏览器向服务器“自报家门”,更确切的说是所有HTTP客户端都得用User-agent向服务器“自报家门”,以便服务器对不同的客户端作出不同响应。比如,某站点可能需要对浏览器、搜索引擎crawl还有各类下载工具作出不同的响应。服务器就是通过所谓的User-agent进行区分的。
如果你的服务器提供某些资源的下载,那么你就必须多加小心诸如“迅雷”等下载软件,因为它们可能把你网站资源吸干,并且影响你的正常访客访问。为此,我们可以利用Rewrite限制某些UA的访问:
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} 2.0.50727 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^BlackWido [NC,OR]
# ect…
RewriteRule . abuse.txt
•该规则限制“迅雷”客户端下载资源,并将下载文件重置到abuse.txt
•HTTP_USER_AGENT是Apache的内置变量
•2.0.50727是迅雷User-agent的特征字符串
•RewriteRule后面的“点”表示“任意URI”,也就是不管请求的是什么,都输出abuse.txt
文件访问控制
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !^(.+)\.css$
RewriteCond %{REQUEST_FILENAME} !^(.+)\.js$
RewriteCond %{REQUEST_FILENAME} !special.zip$
RewriteRule ^(.+)$ /chat/ [NC]
•该规则将仅允许用户请求.css, .js类型的文件,还有special.zip文件
•RewriteRule 后面指定了限制规则:映射到/char/目录下处理
•RewriteCond 后面的“感叹号”(!)起到了“否定”作用,它表明,对不满足后面正则表达式者应用RewriteRule规则,也就是对当前类型的文件将不应用规则
•RewriteCond 之间是以逻辑“与”连接的,也就是只有当三个条件都不满足时才执行RewriteRule
•该规则也会限制访问.htm, .jpg等格式
•该规则不可以放在虚拟站点根目录(/)下,否则会死循环
•如果是二级目录,如/test/,那么传入RewriteCond的参数是以/test/开始的,因此从(.+)获得的文件名也含有/test/,读者必须对此多加小心
•要想仅获得文件名,可以将(.+)替换成([^/]+),并且去掉符号^,如下所示:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !([^/]+)\.css$
RewriteCond %{REQUEST_FILENAME} !([^/]+)\.js$
RewriteRule ^(.+)$ /chat/ [NC]
RewriteEngine Off
#RewiteBase /
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ blog/$1
# 没有输入文件名的默认到到首页
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ [NC]
RewriteRule ^(/)?$ blog/index.php [L]
防盗链:
RewriteEngine on
#RewiteBase /
RewriteCond %{HTTP_REFERER} !^$ [NC]
RewriteCond %{HTTP_REFERER} !xxx.info [NC]
RewriteCond %{HTTP_REFERER} !(www\.)?baidu.com$ [NC]
RewriteCond %{HTTP_REFERER} !(www\.).google.com$ [NC]
RewriteRule \.(jpg|gif|png|bmp|swf|jpeg)$ /error/daolian.gif [R,NC,L]
【RewriteCond语法】
RewriteCond TestString CondPattern [flags]
rewritecond的其他用法:
“-d”(目录)
将TestString视为一个路径名并测试它是否为一个存在的目录。
“-f”(常规文件)
将TestString视为一个路径名并测试它是否为一个存在的常规文件。
“-s”(非空的常规文件)
将TestString视为一个路径名并测试它是否为一个存在的、尺寸大于0的常规文件。
“-l”(符号连接)
将TestString视为一个路径名并测试它是否为一个存在的符号连接。
“-x”(可执行)
将TestString视为一个路径名并测试它是否为一个存在的、具有可执行权限的文件。该权限由操作系统检测。
“-F”(对子请求存在的文件)
检查TestString是否为一个有效的文件,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性能,所以请谨慎使用!
“-U”(对子请求存在的URL)
检查TestString是否为一个有效的URL,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性能,所以请谨慎使用!
【RewriteRule语法:】
RewriteRule Pattern Substitution [flags]
【flags】
“chain|C”(链接下一规则)
“cookie|CO=NAME:VAL:domain[:lifetime[:path]]”(设置cookie)
“env|E=VAR:VAL”(设置环境变量)
“forbidden|F”(强制禁止URL)
“gone|G”(强制废弃URL)
“handler|H=Content-handler”(强制指定内容处理器)
“last|L”(结尾规则)
“next|N”(从头再来)
“nocase|NC”(忽略大小写)
“noescape|NE”(在输出中不对URI进行转义)
“nosubreq|NS”(不对内部子请求进行处理)
“proxy|P”(强制为代理)
“passthrough|PT”(移交给下一个处理器)
“qsappend|QSA”(追加查询字符串)
“redirect|R [=code]”(强制重定向)
“skip|S=num”(跳过后继规则)
“type|T=MIME-type”(强制MIME类型)
RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]
示例:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$
RewriteCond %{REQUEST_URI} !^/blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /blog/$1
# 没有输入文件名的默认到到首页
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$
RewriteRule ^(/)?$ blog/index.php [L]

【RewriteEngine On】
表示重写引擎开,关闭off,作用就是方便的开启或关闭以下的语句,这样就不需要一条一条的注释语句了。
【RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$】
这是重写条件,前面%{HTTP_HOST}表示当前访问的网址,只是指前缀部分,格式是www.xxx.com不包括“http://”和“/”,^表示 字符串开始,$表示字符串结尾,\.表示转义的. ,如果不转义也行,推荐转义,防止有些服务器不支持,?表示前面括号www\.出现0次或1次,这句规则的意思就是如果访问的网址是xxx.com或者 www.xxx.com就执行以下的语句,不符合就跳过。
【RewriteCond %{REQUEST_URI} !^/blog/】
也是重写条件,%{REQUEST_URI}表示访问的相对地址,就是相对根目录的地址,就是域名/后面的成分,格式上包括最前面的“/”,!表示非,这句语句表示访问的地址不以/blog/开头,只是开头^,没有结尾$
【RewriteCond %{REQUEST_FILENAME} !-f】
【RewriteCond %{REQUEST_FILENAME} !-d】
这两句语句的意思是请求的文件或路径是不存在的,如果文件或路径存在将返回已经存在的文件或路径
【RewriteRule ^(.*)$ /blog/$1】
重写规则,最重要的部分,意思是当上面的RewriteCond条件都满足的时候,将会执行此重写规则,^(.*)$是一个正则表达的 匹配,匹配的是当前请求的URL,^(.*)$意思是匹配当前URL任意字符,.表示任意单个字符,*表示匹配0次或N次(N>0),后面 /blog/$1是重写成分,意思是将前面匹配的字符重写成/blog/$1,这个$1表示反向匹配,引用的是前面第一个圆括号的成分,即^(.*)$中 的.* ,其实这儿将会出现一个问题,后面讨论。
 
【RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$】
【RewriteRule ^(/)?$ blog/index.php [L]】
这两句的意思是指请求的host地址是www.xxx.com是,如果地址的结尾只有0个或者1个“/”时,将会重写到子目录下的主页,我猜想这主要因为重写后的地址是不能自动寻找主页的,需要自己指定。
 
现在说说出现的问题,RewriteRule ^(.*)$ /blog/$1 前部分 ^(.*)$ 将会匹配当前请求的url。
例如:请求网址是http://www.xxx.com/a.html,到底是匹配整个http://www.xxx.com/a.html,还是只匹配/a.html即反斜杠后面的成分,还是只匹配a.html。
答 案是:(根据RewriteBase规则规定,如果rewritebase 为/,将会匹配a.html,不带前面的反斜杠,所以上条语句应该写成RewriteRule ^(.*)$ blog/$1(不带/),不过实际应用上带上前面的反斜杠,也可以用,可能带不带都行。现在问题出来了,如果不设置rewritebase 为/ ,将会匹配整个网址http://www.xxx.com/a.html,显然这是错误的,所以应该添加这条:RewiteBase /)有误,自己测试通不过,所以确的应该是 RewriteRule 中的跳转部分加上 http://协议
 
还有一个问题是,不能保证每个人输入的网址都是小写的,如果输入大写的呢,linux系统是区分大小写的,所以应该在RewriteCond后添加[NC]忽略大小写的。
至此,完整的语句应该是:
 

RewriteEngine On
RewiteBase /
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/blog/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ blog/$1
# 没有输入文件名的默认到到首页
RewriteCond %{HTTP_HOST} ^(www\.)?xxx\.com$ [NC]
RewriteRule ^(/)?$ blog/index.php [L]

以上来自www.cnblogs.com/adforce/archive/2012/11/23/2784664.html
help.vit.cn/item/category/htaccesslesca.me/

Posted in PHP Tagged with: , ,

四月 29th, 2016 by lanxinxichen@126.com

事情的起因是这样的,mysql5.5(包括)以下版本都是不支持设置多个timestamp默认值的,所以当我执行有的表中包含两个timestamp带DEFAULT CURRENT_TIMESTAMP的sql的时候就执行不了了.为了保持代码和数据库的版本一致性,就开始了这次的mysql安装之旅.
第一次安装mysql的时候是大二大三的时候吧,那时候是安装版.我一直以为如果别人的轮子比你造的好,你就不用重复造轮子,所以我以前一直使用的是mysql的集成环境,即使是在linux上面安装mysql也都是按照教程一点一点儿来的,只有当现有的东西不能满足的情况下,才需要自己动手.所以才动手安装mysql5.7的.我按照印象去下载mysql,下载下来结果发现是绿色版,一脸懵逼…接下来就简单记录一下mysql安装中需要解决的几个问题.
1. 解压mysql
解压后注意修改解压文件夹的位置,尽量不要放在中文目录下面,虽然我没有测试是否有问题,但是在这上面遇到的坑又不是一次两次了.
2. 增加配置文件: my.ini
修改默认的my-default.ini文件
[mysqld]
basedir=”D:/MySQL/”   # mysql的解压路径
datadir=”D:/MySQL/data/”  # mysql的数据表的存储路径
3. 初始化mysql (第一个坑)
网上流传的mysql绿色版的安装方式都是没有这一步的最多指定以下my.ini的位置,但是如果跳过这一步,下面的服务项即使是安装成功了,也会处于”mysql –正在启动中吧  mysql — 启动失败”状态中.所以需要进行mysql的初始化工作.在mysql/bin的目录中执行以下代码:
mysqld –defaults-file=my.ini –initialize-insecure 
如果报mysqld命令不存在的话,请核对你自己的mysql安装路径是否正确,具体查看参考链接1
4. 安装mysql到服务项
这一步就是简单的 mysqld –install 同时如果想要卸载服务项的话,就使用mysqld –remove
5. 启动服务项
在cmd命令行中敲入net start mysql ,同样的如果需要停止的话,就敲入 net stop mysql
既然是加入到了服务项中,自然也可以在windows的服务管理中找到这个服务,然后进行操作.
6. 增加一个远程的全局权限的用户
这时候在mysql/bin 目录中敲入 mysql -u root 进入到mysql命令行中,修改密码,不知道mysql是哪个版本开始,密码的字段名不再是password而是authentication_string,蜜汁设定...具体查看参考链接2

update user set authentication_string=password('root') where user='root';

这时候的root用户只能在本地访问的,我强制修改数据表的localhost为%还是不行,没有验证是不是配置文件也需要修改,印象中之前的版本就是控制字段就可以 了.这条路行不通,那么我就需要增加一个远程访问的超级管理员用户了.按照参考链接3就尅完成操作了.
创建一个远程访问的超级管理员chen,密码为chen
grant all privileges on *.* to chen@’%’ identified by ‘chen’;
 
参考:
解决Windows安装解压版MySQL出现服务正在启动-服务无法启动的问题
mysql-user-db-does-not-have-password-columns-installing-mysql-on-osx
mysql创建超级管理员

Posted in 数据库 Tagged with:

四月 25th, 2016 by lanxinxichen@126.com

apache-tomcat
我之前的技术方向是PHP,现在是做java,暂且不提两门语言谁优谁劣,我就是感觉什么方便就用什么,适合用什么就用什么.现在做的NLP项目是基于java的web项目,想要在PHP的官网上面挂出来,方法有很多,比如:后端json API转化;无视端口的不一样,前端直接jsonp,当然最简单的办法就是今天提到的apache跟tomcat的整合.博主本身只是刚刚学会了,过程太顺利了,反而害怕以后会不会有什么隐患.遇到问题,以后继续更新在这里.
由于是tomcat跟apache的整合,那我就默认环境中已经有了这两个服务器软件,单纯运行的服务器配置就不再讲解了,只着重讲整合中需要做的工作.
首先打开apache的配置文件:http.conf
在http.conf中打开模块支持:

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

如果在你的Apache/modules路径下没有这两个模块,请从我提供的百度云盘上面下载.百度云盘-php-apache-module,我这一步配置走的很顺,如果做完这一步apache启动不起来,就自己找匹配的模块吧.我用的集成环境,没有花时间在这个上面折腾.
然后配置转发请求到tomcat.
在http.conf中引入一个额外的配置文件httpd-proxy.conf,引入方式:Include conf/extra/httpd-proxy.conf,注意路径跟你放置的文件匹配起来.在配置文件中写入你要转发的请求.比如我现在的配置是:
ProxyPass /java/ ajp://127.0.0.1:8009/java/
ProxyPassReverse /java/ ajp://127.0.0.1:8009/java/
这个配置文件的意思是当我收到/java/的请求的时候通过ajp协议转发到ajp://127.0.0.1:8009/java/的URL请求中,其他的就没有什么可玩的了.具体的ProxyPass和ProxyPassReverse使用可以参看这里Apache配置中的ProxyPass 和 ProxyPassReverse .
总结以下:其实来讲这些东西思路都是一样的,就是代理的思想,我们平时遇到的负载均衡,cname请求转发,fq软件都是这个道理,只不过在服务器层间的转发或者封装了的转发要省很多事.需要注意的是路径的映射,从apache中配置的路径转发到tomcat的路径的时候需要对应起来,如果有同名的注意会不会覆盖请求.
参考文章:
Tomcat: Connector中HTTP与AJP差别与整合 – arun_yh – 博客园
整合apache和tomcat构建Web服务器 – iTech – 博客园

Posted in Java, PHP, 服务器 Tagged with: , , ,

二月 24th, 2016 by lanxinxichen@126.com

简述

初学quartz,按照IBM基于 Quartz 开发企业级任务调度应用一步一步学习的.遇到的问题在这里一一记录,可以给以后学习的人少走一些弯路.
当前项目中使用的quartz版本为:quartz-2.2.2,在该文章中有一些不兼容问题简单陈述

版本兼容

1. StatefulJob 过期
请使用@DisallowConcurrentExecution或者@PersistJobDataAfterExecution 注解的方式同时实现Job接口
2.JobDetail不支持构造函数
通过以下代码构建JobDetail
JobBuilder job = JobBuilder.newJob(TestJob.class);
JobDetail jobDetail = job.withIdentity(“sampleJob”, “sampleGroup”).build();
3.DailyTimeIntervalTrigger类被DailyTimeIntervalTriggerImpl替代
使用DailyTimeIntervalTriggerImpl
4.IntervalUnit不再是DailyTimeIntervalTrigger的属性
可以直接使用IntervalUnit.SECOND类似方法直接访问静态属性
5.deleteJob只有两个方法传入jobkey 或者jobkey列表
jobkey可以通过jobDetail直接getKey()获取,然后使用Scheduler对象的deleteJob方法删除
 

代码运行中的异常

异常1

Scheduler won't start - java.lang.NoClassDefFoundError:com/mchange/v2/c3p0/ComboPooledDataSource

错误分析:找不到类com/mchange/v2/c3p0/ComboPooledDataSource
解决:在下载的quartz解压文件夹中找到\quartz\lib\c3p0-*.jar 添加到class path中
参考:http://forums.terracotta.org/forums/posts/list/5268.page
 
异常2

插入数据postgresql报错:Caused by: org.quartz.JobPersistenceException: Couldn't retrieve trigger: 不良的类型值 long : \x [See nested exception: org.postgresql.util.PSQLException: 不良的类型值 long : \x]

错误分析:数据库不兼容(其实我也不太清楚,没挖那么深)
解决:在配置文件中把org.quartz.jobStore.driverDelegateClass的org.quartz.impl.jdbcjobstore.StdJDBCDelegate修改为postgresql专用的 org.quartz.impl.jdbcjobstore.PostgreSQLDelegate驱动类文件
参考:https://jira.talendforge.org/browse/TDI-27463
https://quartz-scheduler.org/documentation/quartz-2.2.x/configuration/ConfigJobStoreCMT
 
持续更新…

Posted in Java Tagged with:

一月 5th, 2016 by lanxinxichen@126.com

作为感受过whoosh的各种优点的人,初学Lucene,各种不习惯.在使用最新的Lucene5.4的时候,搜索字段一直有问题.报错:
Exception in thread "main" java.lang.IllegalStateException: unexpected docvalues type NONE for field 'id' (expected=NUMERIC). Use UninvertingReader or index with docvalues.
在尝试使用google 和stackoverflow用英语搜索各种问题之后,都没有解决.没想到用中文搜索竟然找到了答案.特写一篇文章,希望被收录,帮到更多的人.
首先,之前的教程都是如下代码:
Sort sort = new Sort(new SortField("id",SortField.INT,false));
TopDocs topDocs = indexSearcher.search(query,100,sort);
而这样的代码直接运行就会报上面的错.
实际上,Lucene在5.X的版本中,应该使用排序专用Field,而不是IntField这种.

NumericDocValuesField  //SortedNumericDocValuesField 已过时的API 

demo:

// doc.add(new IntField("id", article.getId(),Store.YES));
doc.add(new NumericDocValuesField("sortid", article.getId()));

使用一个NumericDocValuesField索引专用字段用来保存需要索引的字段,然后在搜索的时候使用

Sort sort = new Sort(new SortField("sortid", SortField.Type.INT, true));

Posted in Java Tagged with: , , , ,

十一月 26th, 2015 by lanxinxichen@126.com

python以其强大和简洁的语言让人折服,那么究竟有多强大,多简洁呢?在今天学习python的过程中,我来举个例子。
in:将以下列表转化成{‘a’:1,’b’:2}的形式

var = [('a','A',1),
       ('b','B',2),
       ('c','C',3)]

方法1:

tmp1 = []
tmp2 = []
for i in range(3):
 val1 = var[i][0]
 val2 = var[i][2]
 tmp1.append(val1)
 tmp2.append(val2)
tmpdict = {}.formatkeys(tmp1,0)
for i in range(3)
 tmpdict[tmpdict.keys()[i]] = tmp2[i]

当然我有意的拉长了代码。
方法2:

tmp1 = []
tmp2 = []
for i in range(3):
 tmp1.append(var[i][0])
 tmp2.append(var[i][2])
tmpdict = dict(zip(tmp1,tmp2))

采用zip压缩数组,然后转换成dict
方法3:

 tmpdict = {i[0]:i[2] for i in var}

一句话循环并组成字典。
同样的还有很多地方用到,比如lambda,reduced,filter,cmp等这类函数的应用。能大大减少代码量。更有意思的可以查看:一行 Python 能实现什么丧心病狂的功能?
 
 

Posted in Python Tagged with: