grep和find命令的基本用法:

grep命令:文本搜索

命令格式 : grep [options] pattern files
pattern 即 匹配的条件

[options]主要参数:
-c:只输出匹配行的计数。
-i:不区分字符大小写。默认区分大小写
-h:查询多文件时不显示文件名,显示文件的内容。
-l:查询多文件时只输出包含匹配字符的文件名。
-L:列出不匹配的文件名,
-n:显示匹配行及行号。
-s:不显示不存在或无匹配文本的错误信息。
-v:显示不包含匹配文本的所有行。

pattern正则表达式主要参数:
\: 忽略正则表达式中特殊字符的原有含义。
^:匹配正则表达式的开始行。
$: 匹配正则表达式的结束行。
\<:从匹配正则表达 式的行开始。
>:到匹配正则表达式的行结束。
[ ]:单个字符,如[A]即A符合要求 。
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。
。:所有的单个字符。
* :有字符,长度可以为0。

files 即 匹配的文件地址 获取当前目录的地址可以使用 ./,也可以使用绝对地址/opt/.....

一些有意思的匹配:
grep -w pattern files :只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’),
grep -C number pattern files :匹配的上下文分别显示[number]行,
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。

find命令:文件搜索

命令格式:find pathname -options [-print -exec -ok ...]
参数:
pathname: find命令所查找的目录路径。例如用.来表示当前目录,也可以使用绝对地址

-print: find命令将匹配的文件输出到标准输出。

-exec: find命令对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' { } ;,注意{ }和;之间的空格。

-ok: 和-exec的作用相同,只不过以一种更为安全的模式来执行该参数所给出的shell命令,在执行每一个命令之前,都会给出提示,让用户来确定是否执行。

使用print将参数输出到下一条命令,使用exec或ok来执行shell命令

[options]一些常用的命令选项:
-name 按照文件名查找文件。
-perm 按照文件权限来查找文件。
-prune 使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用-depth选项,那么-prune将被find命令忽略。
-user 按照文件属主来查找文件。
-group 按照文件所属的组来查找文件。
-mtime -n +n 按照文件的更改时间来查找文件, - n表示文件更改时间距现在n天以内,+ n表示文件更改时间距现在n天以前。find命令还有-atime和-ctime 选项,但它们都和-m time选项。
-nogroup 查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。
-nouser 查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。
-newer file1 ! file2 查找更改时间比文件file1新但比文件file2旧的文件。
-type 查找某一类型的文件,诸如:
b - 块设备文件。
d - 目录。
c - 字符设备文件。
p - 管道文件。
l - 符号链接文件。
f - 普通文件。
-size n:[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。-depth:在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。
-fstype:查找位于某一类型文件系统中的文件,这些文件系统类型通常可以在配置文件/etc/fstab中找到,该配置文件中包含了本系统中有关文件系统的信息。
-mount:在查找文件时不跨越文件系统mount点。
-follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。
-cpio:对匹配的文件使用cpio命令,将这些文件备份到磁带设备中。

另外,下面三个的区别:

-amin n 查找系统中最后N分钟访问的文件
-atime n 查找系统中最后n24小时访问的文件
-cmin n 查找系统中最后N分钟被改变文件状态的文件
-ctime n 查找系统中最后n
24小时被改变文件状态的文件
-mmin n 查找系统中最后N分钟被改变文件数据的文件
-mtime n 查找系统中最后n*24小时被改变文件数据的文件

find命令实例:
1.在当前目录及子目录中,查找大写字母开头的txt文件
find . -name '[A-Z]*.php' -print

2.在当前及其子目录中,查找test开头的文件
find . -name 'test*' -print

3.在当前目录及子目录中,查找不是out开头的php文件
find . -name "out" -prune -o -name ".php" -print

4.查找2天内被更改过的文件
find . -mtime -2 -type f -print

5.查找超过1M的文件
find . -size +1M -type f -print

6.用grep命令在当前目录下的所有普通文件中搜索hostnames这个词
find . -name * -type f -print | xargs grep "host"

7.删除指定目录下带有“我是”的文件
find ./* - name "*.php" -print | xargs grep -l "我是" | xargs rm -rf

移动端列表页操作优化

详情见ppt
移动端列表页操作优化
旧项目代码
code

大纲如下
方案一:PHP + ajax方式
tab切换使用PHP判断
第一页数据PHP获取,输出
当前页面滚动到底部,ajax加载后续数据

方案二:纯ajax方式
tab切换也使用加载
默认加载第一页数据
滚动到屏幕底部,加载下一页

方案三:本地存储缓存列表
同纯ajax加载方式
点击详情页的时候,保存当前状态
屏幕滚动位置
当前列表页数据
当前页码
初始化时,如果本地存储有数据
恢复相应数据(列表页、滚动位置、页码等)
删除本地存储数据

对比总结

优化方案
纯ajax处理
每次ajax请求的时候,将请求参数附加到当前URL上
window.location.replaceState
点击内页,本地存储中存储当前滚动条滚动位置
初始化的时候,读取url中的请求参数进行请求
page如果不是第一页,则合并请求,修改limit
读取本地存储中的滚动位置,js滚动

常见JS写法问题
PHP和JS代码混合
列表页数据统一,不要一部分PHP,一部分JS
在JS中,到处有PHP输出的内容
污染全局,各种变量,函数定义
到处有监听事件的代码,同一个事件可能都有几个地方
JS使用样式定义的class或者ID
代码耦合严重,全都堆积在一起
JS文件未压缩

如何配置测试环境,支持多分支开发

标签: 运维 测试环境搭建 apache


编 写:袁 亮
时 间:2016-09-05
说 明:如何配置测试环境,支持多分支开发

一、目的

1、业务开发,多人合作的时候,需要开启多个分支
2、每个分支的开发、调试、访问需要能跟其他分支独立

二、分支独立需要考虑如下问题

1、需要配置独立的访问规则,来支持各个分支
    要求:访问规格更改不需要改动程序
2、配置文件,每个分支可以自行配置,也可以使用通用的
    包含配置:
        数据库、缓存、静态文件等等
    解决方案:
        SetEnv CI_ENV development
        development配置目录不要放在svn里,通过svn ignore忽略
3、图片、文件上传
    解决办法:所有上传,走统一的接口,返回上传之后的地址即可,各个分支一样
4、api接口
    解决办法:在各自分支里,调用不同的api分支

三、访问规则配置方案

1、方案一:
    实施:将分支名以目录的形式放在测试hosts之后,比如shopdev的配置
    优点:新建分支很简单,在相应目录下建个分支目录即可
    缺点:因为多了一层目录,会导致整个的访问规则都不一样了,代码中需要做相应的兼容判断,比如出现这种:
        http://shopdev.ci123.com/svn/yungou/webroot/index_yiqigou.php/item-5287.html?store_id=120&share_uid=406259
        或者直接/目录开头的访问等等

2、方案二:
    实施:将分支名以泛域名解析的形式,隐藏到hosts里
    优点:对程序不用做任何改动,访问规则完全兼容(ps:代码里写死了绝路路径的这种自己挖坑的另算)
    缺点:测试域名一般不是实际解析的域名,也意味着没有走DNS解析的过程,只能通过hosts来实现
        而hosts并不具备解析功能,隐藏泛解析这种hosts是做不了的,只能每个分支自己加hosts
        ps:如果嫌加hosts麻烦,可以考虑将测试域名做实际解析
            或者在公司内部自建DNS(bind),缓存非测试域名,测试域名自己做解析
            比较麻烦,没太大意义,暂时不考虑
    其他:
        直接使用nginx+fastcgi会更简单,只是我们使用的apache为主,因此是配置的nginx+apache的方式

四、方案二实施

1、nginx 配置泛域名解析
    server_name通配符即可

2、apache支持泛域名解析(rewrite方式)
    1.1 ServerAlias 通配符实现泛解析
    1.2 rewrite 实现将分支名转为相应的目录名
    1.3 框架本身的rewrite重写
    1.4 静态文件rewrite重写

3、hosts 处理
    需要使用的分支,自行添加hosts

五、yungou.ws测试机最终使用

1、svn 创建分支,checkout到/opt/ci123/www/html/seller_shop下
    ps:分支名只支持大小写字母、数组、_组成的字符串
2、本地添加hosts
    192.168.0.249 分支名.yungou.ws
3、浏览器访问 (一些老旧浏览器需要强刷或者重启)
    分支名.yungou.ws

六、apache rewrite 概述

RewriteEngine On

# 将所有非static静态文件的请求,全部达到webroot的index中,框架本身的rewrite要求,将分支名嵌入进去
RewriteCond %{HTTP_HOST} [\w_]+.yungou.ws
RewriteCond %{REQUEST_URI} !static.*
#将hosts放到rewrite匹配源中,需要其中的分支名作为后续使用 跟下一条规则关联
RewriteRule ^(.+) %{HTTP_HOST}$1 [C] 
RewriteRule ([\w_]+).yungou.ws(.*) /$1/webroot/index.php/$2 [L]

# static 静态文件目录不rewrite,直接访问
RewriteCond %{HTTP_HOST} [\w_]+.yungou.ws
RewriteCond %{REQUEST_URI} static.*
RewriteRule ^(.+) %{HTTP_HOST}$1 [C]
RewriteRule ([\w_]+).yungou.ws(.*) /$1/webroot/$2 [L]

附:参考文档

1、nginx泛解析域名实现多级域名多个同时绑定
2、nginx泛域名解析实现二级域名多域名
3、Apache 2.2 + Tomcat 泛域名解析 动态二级域名
4、使apache解析域名到目录的方法
5、Apache的Rewrite规则详细介绍
6、Apache Module mod_rewrite
7、解析无限个二级域名的方法

如何使用CasperJs抓取商品数据

标签: 爬虫 casperjs phantomjs


编 写:袁 亮
时 间:2016-08-30
说 明:如何使用CasperJs抓取商品数据

一、目的

抓取天猫、淘宝、京东的相应商品数据
抓取商品名、价格、轮播图、详情、产品属性等数据

二、方案选择

1、情况分析
    1.1 对应的页面数据很多都是后加载的
    1.2 页面请求很多,想找到其对应的ajax请求比较麻烦
    1.3 ajax请求的地址是服务端生成的,不能通过简单的拼接来生成
    1.4 对正则水平要求较高,很多请求地址是写在js里的

2、可选方案
    2.1 php等语言,直接发钱http请求,然后通过正则匹配等方式,找到响应数据源
        curl、phpquery、Snopy等等 
    2.2 使用浏览器实际访问,然后获取浏览器的最终结果数据
        phantomJS
        casperJS + phantomJS
        python + selenium + phantomJS
3、选用方案 casperJS + phantomJS
    3.1 纯JS,方便前后端使用
    3.2 Casper封装的比较友好、文档齐全,比较好用
        特别是针对后加载的元素,之间waitForSelector的方法非常方便
        可以引入jquery等自己的js文件,方便dom操作
    3.3 获取数据,只需要在浏览器打开的时候,找到对应的节点选择器即可
    3.4 安装部署方便

三、简单例子

var casper = require('casper').create();
casper.start('http://casperjs.org/', function() {
    this.echo(this.getTitle());
});

casper.thenOpen('http://phantomjs.org', function() {
    this.echo(this.getTitle());
});
casper.run();

四、环境部署 (非源码安装)

1、安装phantomjs
    1.1 下载安装
        wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
    1.2 解压
        tar jxvf phantomjs-2.1.1-linux-x86_64.tar.bz2
    1.3 做软连接,放在环境变量里,比如(注意权限问题,如果需要apache调用,更要注意)
        ln -s /opt/ci123/phantomjs/bin/phantomjs /usr/local/sbin/
    1.4 测试运行
        phantomjs --version

2、安装casperjs
    2.1 选择相应版本下载
        wget https://github.com/casperjs/casperjs/archive/1.1.3.zip
    2.2 解压
        unzip 1.1.3.zip 
    2.3 做软连接,放在环境变量里,比如(注意权限问题,如果需要apache调用,更要注意)
        ln -s /opt/ci123/casper/bin/casperjs /usr/bin/casperjs
    2.4 测试是否正常
        casperjs --version

五、实际使用

1、apache调用php
2、php根据url调用不同的CasperJS,传入要抓取的url
3、Casper输出json数据
4、php使用exec调用,并获取casper的输出
5、php将相应的json输出返回apache或者存入数据库等等
演示代码:
    192.168.0.249 
    /opt/ci123/www/html/yuanliang/casper/fetch

六、踩过的坑

1、抓取https的时候,249上一直失败
    原因:
        249上的ssl配置应该问题,导致抓取部分https网站的时候,一直报错
    解决办法:
        a:CasperJS需要较高版本才能用
            casperjs --ignore-ssl-errors=yes --ssl-protocol=any xxx.js
            phantomjs --ssl-protocol=any xxx.js
        b:升级249上的ca证书或者openssl版本

2、抓取速度太慢
    原因:
        这个工具本质是一个无界面的浏览器,因此里面的所有资源都跟浏览器一样,会去加载,图片等资源较多的时候会卡
    解决办法:
        设置不加载图片 loadImages:false
3、clientScripts 注入远程jquery文件无效
    原因:
        只能加载本地的js文件,不能加载远程的js文件
    解决办法:
        可以下载到本地,或者使用remoteScripts来加载,这个可以使用远程文件
        不过使用本地文件比较好,少一次http请求,速度会快很多
4、淘宝的后加载数据一直获取不到
    原因:
        之前https的出问题的时候,以为是ua有问题,所以设置了一个chrome的ua,但是实际上内核不一样
        导致淘宝本身的js执行失败,数据加载不出来
    解决办法:
        去掉ua设置即可
5、天猫的后加载数据(详情)一直加载不出来,报语法错误
    原因:
        天猫的代码中,如何屏幕大小超过1260,会执行一段JS,这段JS会出错
    解决办法:
        设置屏幕宽度小于1260即可
6、waitForSelector获取某个数据,超时,导致后面都不执行了
    原因:
        默认的timeout处理函数,会直接将整个进程中止,后面的所有代码都不执行
    解决办法:
        如果可以接受部分字段抓取不到,则可以在waitForSelector中自行设置timeout处理函数,不中止
        如果需要全部抓取才算结束,可以在timeout的时候触发一个报警等来通知
7、根据浏览器的元素定位,返回不了相应的数据
    原因:
        浏览器最终呈现的元素,有些跟phantomJs返回的不一样
        比如图片后加载,这是在页面滚动到一定位置之后才会触发的
    解决办法:
        如图片后加载这种,数据其实已经返回了,只是存在其他地方,可以返回对应的html,然后看数据存储在哪个字段上
        如果有些是点击、滚动等之后,从服务端获取的数据,那就需要模拟浏览器的点击滚动等事件,然后获取,比较少见
8、执行获取页面数据的时候,失败报错
    原因:
        页面代码执行在不同的沙箱中,在CasperJS本身是读取不到的
    解决办法:
        均在this.evaluate函数中执行,在内部可用操作所有的DOM,跟页面执行JS效果一样
9、天猫商品详情图片一直抓取不对
    原因:
        图片本身是后加载的,之前数据是放在data-ks-lazyload中,后加载执行之后,这个data被干掉了
        直接取src也会有问题,因为有的时候取数据的时候,后加载js还没执行到
        所以导致一会好一会坏
    解决办法:
        先取data-ks-lazyload,如果没有,则去src数据

七、注意事项

1、debug的时候,可用通过将当前页面截图出来,方便查看加载到什么情况了
    也可以将完整的html输出到文件里查看
2、打印json数据,方便跟php等交互
    打印数据
    casper.then(function(){
        require('utils').dump(data);
    });
3、注意很多异步操作,很多时候,执行效果会跟预期不一样
4、当Casper运行结果跟预期不一样的时候,可以考虑直接写相应的phantomJs做对应小块功能来调试
5、淘宝url等在命令行传参会出错,需要用单引号包含起来

八、参考资料

1、CasperJS 官方文档
    http://docs.casperjs.org/en/latest/index.html
2、phantomJS 文档
    http://phantomjs.org/documentation/
3、PhantomJS基础及示例
    http://imweb.io/topic/560b402ac2317a8c3e08621c
4、casperjs模拟登陆https页面获取当前面地址后发现为about:blank问题排查
    http://www.bubuko.com/infodetail-1018663.html
5、 Linux使用curl访问https站点时报错汇总
    http://www.ipcpu.com/2014/12/curl-https-error/

PHP empty、isset的差异

PHP empty、isset的差异:
1.isset():
参数           返回
''            true
0             true
false          true
null($p=null)     false
参数未定义($p)    false
其他           true

总结:如果参数存在(非NULL)则返回 TRUE,否则返回 FALSE(包括未定义)。
参数值设置为:null,返回false;
注意,isset对于NULL值变量,特殊处理。

2.empty():

参数           返回
''            true
0             true
false          true
null($p=null)     true
参数未定义($p)    true
其他           false

总结: 如果参数是非空或非零的值,则 empty() 返回 false。
未定义以及没有任何属性的对象都将被认为是空的,如果参数为空,则返回 true。

iOS博客问答摘录

最近在阅读大神Casa Taloyum博客,发现他不仅文章写得好,还尽心尽力的回复每一个人的评论,每篇文章评价都上百条,一条条看下来,受益匪浅,不仅有初学者的问题,也有开发遇到瓶颈的探讨,作者都一一解答,我就摘抄了一部分,让大家分享。

1、什么时候添加和删除notification?

答:

  • 根据最小权力原则,我们倾向于优先放在展示周期去监听事件。
    ViewController的展示周期是小于ViewController的生命周期的,所以一般如果能在展示周期完成的监听事件的需求,就不会放到生命周期中去做。除非展示周期搞不定的,才会把监听扩大到生命周期。

2、如果一个ViewController 有很多的业务,视图也比较复杂,该怎么拆分呢?我想把业务的处理和页面跳转抽取出来,放到一个category里面,这样viewController可以减少很多代码,但是这个category貌似没有复用的价值。
另外,如果UITableView里面有很多不一样的cell,如何重构代码才能使cell的逻辑简化呢?我尝试用工厂模式去解决,但是发现每个cell需要的model参数都差不多,无法通过model去区分,而通过indexPath去区分的话又不方便重用,只能是一个页面适用。

答:

  • 一般是按照业务角色来拆分业务模块,这需要你对业务有很好的抽象能力。首先,用Category来做对象功能拆分这个思路是没错的,但是对于拆分ViewController来说,拆分更加偏重的是对业务的抽象,然后设立角色,这样才能做到可复用,所以category的思路在这种场景下是不适用的。category只是把大对象变多个小对象而已,它适合拆分那种本身就已经抽象程度比较高、可复用性比较高的底层对象,而不适合用来拆分业务。

  • 独立出DataSource成一个对象,DataSource事实上就可以理解为一个factory,然后DataSource根据Controller给的指示(通过设置DataSource属性也好,通过方法穿参数也行)去生产当前需要的Cell
    继续阅读iOS博客问答摘录

solr使用进阶

快速入门主要讲的是solr管理界面,并且已经利用给好的例子做简单的搜索。
接下要做的是利用数据库是数据来建议搜索。
 
索引mysql的数据 要怎么做?
官方文档也没有详细的说明,主要是修改solrconfig.xml和schema.xml
 
一、先看下路径问题:
为什么要先看路径,是因为有些需要自己去设置。

002oYysygy70MdCwKYa0a&690

bin 常用命令脚本

contrib 各种jar包

dist 各种jar包

server web服务器

solr 未来创建的core会在该目录下

configsets  solr配置集,新建的core可以从这里拷贝配置

二、创建一个搜索实例 

1、{solr安装路径}/server/solr/新建一个文件夹命名为test

2、拷贝{solr安装路径}/server/solr/configsets/sample_techproducts_configs中的conf文件夹到test目录下

3、在后台采用如下配置,然后点击【add core】按钮完成搜索实例的添加

4、solr5.3下自带db、mail、rss、solr、tika实例

目录结构
002oYysygy70MdNZO1593&690
三、配置分词
目前sphinx用的是mmseg分词,而solr支持的分词支持较多。

1、导入smartcn的jar包

在{solr安装路径}/server/solr/test/conf/solrconfig.xml加入如下代码

<lib dir="${solr.install.dir:../../../..}/contrib/analysis-extras/lucene-libs/" regex=".*smartcn.*\.jar"></lib>

2、配置分词器

在{solr安装路径}/server/solr/test/conf/schema.xml加入如下代码

<fieldType name="text_cn" class="solr.TextField" positionIncrementGap="100">
      <analyzer> 
          <tokenizer class="org.apache.lucene.analysis.cn.smart.SmartChineseSentenceTokenizerFactory"/>
          <filter class="solr.LowerCaseFilterFactory"/>     
          <filter class="org.apache.lucene.analysis.cn.smart.SmartChineseWordTokenFilterFactory"/>           
      </analyzer>
    </fieldType>

在{solr安装路径}/server/solr/test/conf/schema.xml加入如下代码

效果如图

002oYysygy70MdPaUWi3e&690

分词效果:这里的好处就是可以直接界面测试。
之前遇到的一个梗,就是123456qq
分词的结果一般都是123456和qq,所以搜123456q是搜不到的
002oYysygy70MdQ9T74ea&690
具体的分词效果,后期会再验证。这里只讲怎么配置。
四、配置导入功能

1、导入相关jar包

①mysql的jar包 

导入下载地址:https://dev.mysql.com/downloads/connector/j/

将jar放置到{solr安装路径}/dist目录下

在{solr安装路径}/server/solr/test/conf/solrconfig.xml加入如下代码

<lib dir="${solr.install.dir:../../../..}/dist/" regex="mysql.*\.jar" />

②dataimporthandler包在{solr安装路径}/server/solr/test/conf/solrconfig.xml加入如下代码

<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-dataimporthandler-.*\.jar" />
2、配置handler

在{solr安装路径}/server/solr/test/conf/solrconfig.xml加入如下代码

<requestHandler name="/dataimport" class="solr.DataImportHandler">
    <lst name="defaults">
      <str name="config">db-data-config.xml</str>
    </lst>
  </requestHandler>

3、配置数据源

在{solr安装路径}/server/solr/test/conf/下新建db-data-config.xml,配置如下:

002oYysygy70MdSCNgg44&690

002oYysygy70MdCwKYa0a&690

002oYysygy70MdSCNgg44

zzz

五、效率问题


第一次(本地)

002oYysygy70MdY8RkRc1&690

第二次(10w)

002oYysygy70MdZ0ivo12&690

第三次(100w)

002oYysygy70MdZX6nb0d&690

根据sphinx的记录
sphinx效率是5-8w docs/sec

solr是基于java单纯执行速度上比C写的sphinx慢
 
六、其他问题
1、导入不全的问题
选取的字段不能为空 如create_date为空,导入终止
2、solr的优势
sphinx的rotate选项可以动态更新索引
3、sphinx比solr建立索引的效率更快

solr入门

第一部分:了解solr

一、solr是什么?
Solr 是一个开源的企业级搜索服务器,底层使用易于扩展和修改的Java 来实现。服务器通信使用标准的HTTP 和XML,所以如果使用Solr 了解Java 技术会有用却不是必须的要求。
二、lucene是什么?

Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。

目前已经有很多应用程序的搜索功能是基于 Lucene ,比如 Eclipse 帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要把你要索引的数据格式转化的文本格式,Lucene 就能对你的文档进行索引和搜索。

三、Solr VS Lucene

Solr 与Lucene 并不是竞争对立关系,恰恰相反Solr 依存于Lucene ,因为Solr 底层的核心技术是使用Apache Lucene 来实现的,简单的说Solr 是Lucene 的服务器化。需要注意的是Solr 并不是简单的对Lucene 进行封装,它所提供的大部分功能都区别于Lucene 。

第二部分:教程

一、从网站上下载

http://lucene.apache.org/solr/

我找的版本是5.3.1,最新版本是5.5

二、安装与运行

1、安装环境要求:

java的版本大于 1.7(利用java -version查看)

php接口是 >=5.2.11

 

2、启动:

bin/solr start -e cloud -noprompt

默认是8983端口
http://localhost:8983/solr/
快速入门solr002oYysygy70MbNH8XLf1&690
 
图片中各项的具体含义:
快速入门solr
002oYysygy70MbQv8Voee&690
002oYysygy70MbSpB5o1a&690
说明:这里是使用给好的例子,所以是有索引的。
使用 bin/solr start 是看不到索引。
其他命令
bin/solr start -p 8984(指定为8984端口)
bin/solr create -c 指定一个实例
bin/solr create -help 帮助
 
三、建立一个实例:
bin/post -c gettingstarted docs/

    -c gettingstarted:索引的名字(后期获取结果时用到)
    docs/:数据
快速入门solr002oYysygy70MbTPRJm48&690
在界面中可以看到,建立了实例。
并且也是有数据的。
 也是可以通过命令去查看的
http://localhost:8983/solr/admin/cores?action=STATUS
 
四、数据说明:
1、数据类型:索引不同类型的文档
官方文档中说:
Solr can be queried via REST clients, cURL, wget, Chrome POSTMAN, etc., as well as via the native clients available for many programming languages.

可以看出,可以建立不同形式的索引,包括json,xml,以及word

功能:添加,更新,删除等
如xml数据:
<add>
<doc>
  <field name="id">USD</field>
  <field name="name">One Dollar</field>
  <field name="manu">Bank of America</field>
  <field name="manu_id_s">boa</field>
  <field name="cat">currency</field>
  <field name="features">Coins and notes</field>
  <field name="price_c">1,USD</field>
  <field name="inStock">true</field>
</doc>
</add>
conf/schema.xml配置文件中规定好的。
 
五、怎么搜索?
1、界面搜索
http://localhost:8983/solr/#/gettingstarted_shard1_replica1/query
快速入门solr002oYysygy70Mc05TGz83&690
 

2、页面访问:

http://localhost:8983/solr/gettingstarted/select?wt=json&indent=true&q=foundation
 
六、思考:通过curl就可以获取,缺点就是不太安全吧?

如5.3上管理用户界面没有用户限制,所以任何人都可以访问管理员的用户界面将可以做任何事情与您的系统。

解决方案:基本认证和授权插件/设置防火墙
 
 
以上就是一个简单的索引的建立和搜索功能,有问题欢迎留言。

http到https的过渡

最近https有点火,搜索一下“运商商 流劫持持”,应该能看到好多运营商向网页中强制插入广告的新闻,运营商能这做一是因为流量都要从运营商过路,二是因为http传输的是明文。如果换成https传输数据,数据的安全性可以提高一个档次。

看下文之前请先看《https的使用注意事项》

http到https的切换,道理是很简单的,主要是修改对网址的解析(包括主域名和资源文件的CDN),项目里把“http://”改为“https://”或“//”(自适应协议)。下面是比较详细的改造过程:

1、改配置文件。
配置文件一般存放了项目域名、资源文件域名,所以第一步从这里下手改。
如果开启了https,$_SERVER['HTTPS']非空,一般为on(非https时,在IIS上使用ISAPI方式,该值为off)。
所以,判断是否是https访问的判断条件是 $_SERVER['HTTPS']=='on',我们用 $protocal 表示当前协议,然后把配置里的 http:// 改成 $protocal 。

2、修改项目中的绝对路径。
主要关注几个,jquery路径,二维码路径,微信js地址,轮播图地址,轮播图的点击地址,登录页面的地址。

3、外网资源文件。
如果资源文件很少,可以抓取过来放到自己网站。
如果资源文件很多,可以强制跳转到http页面。(百度图片就是强制跳转到http)

4、统计JS。
百度统计、腾讯统计均支持https,CNZZ现在也支持https(以前的cnzz统计代码不支持https)。
量子统计不支持https。

5、切换到https后可能出现的问题。
a.访问出现502错误;
b.网页打不开,加载时间非常长;
首先看是否是cdn解析问题,如果不能快速解决就切换回http。

总结:
刚始始切换后问题很多,主要特点就是“打不开”、“变慢”。多和运维做些沟通,持续优化https的体验。
https不是绝对安全,如果项目牵扯很多,改造起来难度也很大,量力而行。
记得要保证可以随时切回http。

PHP 自动加载总结

自动加载的测试代码

https://github.com/bayuexiong/simple-composer

1. 自动加载

php的加载文件,一般分为三种情况

  1. 直接include/require,不属于自动加载,一般用于PHP5以前的版本。
  2. 使用__autoload(),PHP5.0引入,在PHP5.1.12之后不再推荐使用。
  3. 使用spl_auoload_register(),现在使用比较多,于PHP5.1.12之后加入,提供了一种更加灵活的方式加载文件。

具体实例

第一种没什么说的。主要还是看第二种和第三种。

假设在一个项目里面有两个文件

Demo.php

class Demo
{
# coding
}

index.php

function __autoload($class_name)
{
$file = dirname(__FILE__) . '/' . $class_name;
if (file_exist($file)) {

include($file);

}

}

$obj = new Demo();

Demo.phpindex.php只要在一个同级目录内,php变会很智能的加载Demo.php,不需要显示的操作。

但是这里还是存在弊端的,比如一个项目中只能有一个__autoload(),这也意味着自动加载的价值变得很低,于是PHP便在PHP5.1.12版本之后添加了spl_autoload_register(),它接受一个回调函数,使得自动加载更加的灵活。

修改index.php

function my_autoload($class_name)

{

$file = dirname(__FILE__) . '/' . $class_name;

if (file_exist($file)) {

include($file);

}

}

spl_autoload_register('my_autoload');

$obj = new Demo();

之前的Demo.php不做修改,将index.php如此修改,便可以同样的功能。

关于spl_autoload_register()更多的内容可以查看官方文档。

http://php.net/manual/zh/function.spl-autoload-register.php

 TIPS
注意类名和文件名必须保持一致!!!

2. Composer

在5.3之后,Composer大行其道,号称PHP未来的希望。。。

使用Composer自动加载时只要引入一个自动加载文件就可以了。

include_once('vendor/autoload.php');

那么Composer的自动加载时怎么实现的呢,其实也是依靠spl_autoload_register()

首先Composer存储三对数组

class=>dir
namespace=>array(dir, dir, dir)
PSR4=>array(dir, dir1, dir2...)

然后在autoload.php, 存在一个loader,可以触发spl_autoload_register,
一旦触发,Composer会对触发的类型进行分析,选择合适的数组,将真实的地址提取出来,然后include,原理还是很简单,推荐大家自行查看一下Composer的自动加载的代码。

关于composer的一个Tips

在上线代码时可以使用composer dump-autoload -o 转换PSR-0/4 autoloadingclassmap 获得更快的载入速度。这特别适用于生产环境,但可能需要一些时间来运行,因此它目前不是默认设置。至于为什么,看完源代码就清晰了。

3. 简单实现一个Composer自动加载

简单实现ClassMap的自动加载功能

https://github.com/bayuexiong/simple-composer/tree/master/vendor

使用代码和Composer一样。

include 'vendor/autoload.php';

$obj = new Demo('gg');

$obj->sayName();

$obj2 = new Other('aa');

$obj2->sayName();

4. 如何选择自动加载机制

  1. 在程序一开始运行的时候,使用数组,将项目内所有的文件记录下来,实现自动加载(如果使用cache,应该还hold的住),symfony使用这种形式,代码如下。
    https://github.com/symfony/class-loader/blob/master/ClassMapGenerator.php
  2. class名和路径对应,便于查找,但是这样缺乏灵活性,框架的侵入性太强了,代码很受框架的限制,像ThinkPHP,CI就是使用这种形式。
  3. 组合使用,像Laravel就是使用PSR4和symfony的classLoader。

5. CI框架的自动加载

现在公司使用CI框架的情况比较多,所以对CI框架的自动加载做一些详细的介绍。

对于一个普通的CI加载类的方式:

 $this->load->library('myclass');

CI框架的内部是如何运行的呢?首先上个流程图

QQ截图20160314174227

具体的实现可以查看源代码,都在system/core/Loader.php文件下面。

其实CI框架的自动加载并没有借助spl系列的函数,而是直接查找文件的方式来自动加载,这可能与CI框架诞生的年岁有关,在那个时期不失为一种优秀的自动加载方法。

但是现在来说,算不上优秀,其对命名的规范太过苛刻了,效率也谈不上高效,当然CI框架的整体速度还是很快的,毕竟像symfony之流的框架为了实现完全解耦,付出了很多性能上的代价。

Tips

对于一个普通的加载类
$this->load->library($library, $param, $object_name);
1. $library 可以是一个数组key代表需要加载的类,value则是obejct_name。
2. $param 需要一个数组,作于传入构造器中的值
3. $object_name$this->load->model(calss, object_name)中第二个参数一样,加载完之后可以$this->object_name->sayHello()

具体的可以结合CI的文档再加上阅读CI的源代码,的确CI的文档相比其他的框架比较全面,但是一些技巧也没有详尽的介绍。

6. 小结

使用Composer吧!使用RSP4命名空间规范吧!这样各个组件与组件之间,自己的代码和别人的代码都可以无痛的结合,不需要花费额外的精力去处理文件加载的问题。

7. 补充

  1. 命名空间,命名空间提供了一种灵活的效率更高的辅助自动加载的方法。
  2. PSR4 规范命名空间的定义,是最近比较流行的命名空间规范。

材料参考:

  1. https://github.com/qinjx/adv_php_book/blob/master/class_autoload.md
  2. spl_autoload_register
  3. __atuoload