编 写:袁 亮
时 间:2016-12-21
说 明:用户系统演进
一、用户系统限制因素
1、使用域名
单个域名
多个域名
2、使用系统是单服务器还是多服务器
3、使用域名是否属于同一个域名的不同子域名
4、系统访问环境
PC浏览器
是否兼容IE浏览器
是否兼容手机浏览器
5、用户数据库是否唯一
单一用户数据库
多个用户数据库
二、单用户中心,单域名
1、条件限制
1.1 单个域名
1.2 单一用户数据库
2、实现方案
2.1 session
磁盘IO
多服务器session共享
2.2 cookie
域名,端口,路径,cookie名
数据签名
大小限制
敏感信息
3、其他
3.1 可以有多种登陆方式
3.2 可以接入很多种第三方登陆
三、单用户中心,单个根域名
1、条件限制
1.1 单个用户数据库
1.2 多个域名同属于某个根域名
2、实现方案
2.1 cookie共享 (育儿网)
a. cookie设置在根域名
b. 所有子域名都可以正常读取并验证签名
c. 不可扩展,安全性无保障
2.2 token形式 (共享session机制的变种)
a. cookie设置在根域名
b. 子域名读取到cookie之后,调用用户中心接口获取用户数据
c. 将用户数据写入当前域名下
四、单用户中心,多个根域名
1、条件限制
1.1 单个用户数据库
2、实现方案
2.1 单点登陆 jsonp方式跨域 (淘宝)
a. 统一的登陆,查收ticket
b. jsonp方式将ticket循环传递给所有业务
c. 业务域名根据ticket获取用户信息设置登陆
d. 退出同样方式处理
缺点:
ios下,浏览器默认禁止第三方域名cookie设置,直接歇菜
2.2 单点登陆 cas方式 (新浪)
a. 通过jsonp+ajax+iframe的方式,在各个子域名框用户中心登陆
b.
缺点:手机浏览器对iframe支持的很差
2.3 服务端ticket形式,jsonp形式单点登录的变种
五、多用户中心
1、条件限制
无
2、实现方案
2.1 单域名或者多根域名跨域同三和四
3、额外增加处理
3.1 统一跳转地址
3.2 用户聚合统一
3.3 平台信息维护
3.4 vtoken登录
分类: web后端技能树
linux定时任务的设置 crontab
一、基本使用
#分 时 日 月 周
* * * * * /home/blue/do/rsyncfile.sh
二、语法
crontab [-u username] [-l|-e|-r]
选项与参数:
-u :只有 root 才能进行这个任务,亦即帮其他使用者创建/移除 crontab 工作排程;
-e :编辑 crontab 的工作内容
-l :查阅 crontab 的工作内容 (备份)
-r :移除所有的 crontab 的工作内容,若仅要移除一项,请用 -e 去编辑
三、crontab的限制
/etc/cron.allow:将可以使用 crontab 的帐号写入其中,若不在这个文件内的使用者则不可使用 crontab;
/etc/cron.deny:将不可以使用 crontab 的帐号写入其中,若未记录到这个文件当中的使用者,就可以使用 crontab 。
以优先顺序来说, /etc/cron.allow 比 /etc/cron.deny 要优先, 而判断上面,这两个文件只选择一个来限制而已,因此,建议你只要保留一个即可, 免得影响自己在配置上面的判断!一般来说,系统默认是保留 /etc/cron.deny ,你可以将不想让他运行 crontab 的那个使用者写入 /etc/cron.deny 当中,一个帐号一行!
![]()
四、crontab的原理
crond服务的最低侦测限制是分钟,所以cron 会每分钟去读取一次 /etc/crontab 与 /var/spool/cron 里面的数据内容,因此,只要你编辑完 /etc/crontab 这个文件,并且将他储存之后,那么 cron 的配置就自动的会来运行了!
执行脚本的用户:/var/spool/cron/
执行记录:/var/log/cron
![]()
五、crontab 的格式
代表意义 分钟 小时 日期(天) 月份 周 命令
数字范围 0-59 0-23 1-31 1-12 0-7 执行的命令
周的数字为 0 或 7 时,都代表『星期天』的意思!
辅助字符
特殊字符 代表意义
*(星号) 任何时刻
,(逗号) 代表分隔时段
-(减号) 代表一段时间范围内
/n(斜线) 代表每隔n单位间隔
六、周与日月
周和日月不是 并 的关系,而是 或 的关系。
你可以分别以周或者是日月为单位作为循环,但你不可使用「几月几号且为星期几」的模式工作。
30 12 11 11 5 root echo "just test" <==这是错误的写法
本来你以为十一月十一号且为星期五才会进行这项工作,无奈的是,系统可能会判定每个星期五作一次,或每年的 11月 11 号分别进行。
测试:(12月8号为星期4)
25 18 08 12 4 (echo "just test1" >> /tmp/test.txt ) //执行一次
25 18 07 12 4 (echo "just test2" >> /tmp/test.txt ) //执行一次
25 18 08 12 5 (echo "just test3" >> /tmp/test.txt) //执行一次
七、& 后台执行命令
1. command & : 后台运行,你关掉终端会停止运行
2. nohup command & : 后台运行,你关掉终端也会继续运行
参考:http://www.cnblogs.com/lwm-1988/archive/2011/08/20/2147299.html
八、2>&1 含义
先看一个例子:
0 2 * * * echo "just test" >> /tmp/test.txt 2>&1 &
这句话的意思就是在后台执行这条命令,并将错误输出2重定向到标准输出1,然后将标准输出1全部放到/dev/null 文件,也就是清空。
注释:
数字的含义:
0表示 键盘输入
1表示 标准输出
2表示 错误输出
>>是追加内容
> 是覆盖原有内容
示例:
0 2 * * * sh /tmp/test.sh 1>/tmp/out.file &
0 2 * * * sh /tmp/test.sh 2>/tmp/out.file &
0 2 * * * sh /tmp/test.sh 2>/tmp/out.file 2>&1 &
1、将tesh.sh 命令输出重定向到out.file, 即输出内容不打印到屏幕上,而是输出到out.file文件中。
2、2>&1 是将错误输出重定向到标准输出。 然后将标准输入重定向到文件out.file。
3、&1 表示的是文件描述1,表示标准输出,如果这里少了&就成了数字1,就表示重定向到文件1。
4 、& :后台执行
测试:
ls 2>1 : 不会报没有2文件的错误,但会输出一个空的文件1;
ls xxx 2>1: 没有xxx这个文件的错误输出到了1中;
ls xxx 2>&1: 不会生成1这个文件了,不过错误跑到标准输出了;
ls xxx >out.txt 2>&1 == ls xxx 1>out.txt 2>&1: 因为重定向符号>默认是1,这句就把错误输出和标准输出都传到out.txt 文件中。
九、注意点:2>&1写在后面的原因
格式:command > file 2>&1 == command 1> file 2>&1
首先是command > file将标准输出重定向到file中, 2>&1 是标准错误拷贝了标准输出,也就是同样被重定向到file中,最终结果就是标准输出和错误都被重定向到file中。
如果改成: command 2>&1 >file
2>&1 标准错误拷贝了标准输出的行为,但此时标准输出还是在终端。>file 后输出才被重定向到file,但错误输出仍然保持在终端。
![]()
JSONP
JSONP是什么
跨域资源共享(Resources Domain Resources Sharing),客户端从不同的域名发送JSON响应时绕过浏览器限制
JSONP原理解析
利用 script标签 的 src属性 进行跨域请求,服务器响应函数调用传参。
2.1 静态方法创建
代码:
<?php
//echo "a = 1";
?>
//html代码
<script type="text/javascript" src="http://ly.yungou.ws/test/index"></script>
<script type="text/javascript">
console.log(a); // 1
</script>
跨域请求成功!
2.2、 动态方法创建
动态创建 script标签的方式,添加到头部,来获取变量参数
<?php
echo "var a = 1;";
?>
//通过 script语句动态创建 script标签进行请求
<script type="text/javascript">
var script = document.createElement('script');
script.src = 'http://ly.yungou.ws/test/index';
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
console.log( a );
</script>
注意:原来动态创建 script 的方式发送请求 是异步的,虽然请求成功了,但是在使用变量时,请求还没有完成,相当于还没有定义变量,然后就报错了。
解决办法:使用callback
<?php
echo 'callback(123)';
?>
<script type="text/javascript">
var script = document.createElement('script');
script.src = 'http://ly.yungou.ws/test/index';
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
function callback(data){
console.log( data ); //callback(123) 对 callback 调用 输出 123
}
</script>
那我们就可以用这种动态的方式 很轻松的 拿到后台数据了,只不过前台声明的和 后台 调用的 函数名 需要一样才行,如上面的 然而这样也不太好,每次改动,那都要前后台对接一下。
所以我们可以把回调函数名放在参数中传输。案例如下:
<?php
$callback = $_GET[ 'callback' ]; // get 通过 callback键 得到 函数名
$userInfo = array( 'username' => 'leiyuan', 'password' => '123456' );// 生成数据
$data = json_encode($userInfo);
echo "{$callback}({$data});";// hello( json_encode($arr) )
通过 script语句动态创建 script标签进行请求
var script = document.createElement('script');
script.src = 'http://ly.yungou.ws/test/callback?callback=hello';
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
function hello(data){
console.log(data);// Object {username: "leiyuan", password: "123456"}
}
</script>
2.3 jsonp原理:
JSONP是一个协议(并且是非正式传输协议)。 该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了.
由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求,
2.4 jsonp原理
首先在客户端注册一个callback, 然后把callback的名字传给服务器。
服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp. 最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)
JSONP和JSON的区别:
目前为止最被推崇或者说首选的方案还是用JSON来传数据,靠JSONP来跨域。
JSON(JavaScript Object Notation)和JSONP(JSON with Padding)
JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。一个是描述信息的格式,一个是信息传递双方约定的方法。
1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery等框架都把jsonp作为ajax的一种形式进行了封装;
2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加
```
JSONP使用注意事项
1、跨系统跨域名,获取基本信息,
ps:后端不能存在任何页面跳转登陆信息,否则会请求失败
2、jsonp的缺陷:不提供错误处理(对方拒绝请求,网络不通,请求地址或者参数不正确等等)如果动态插入的代码正常运行,你可以得到返回,但是如果失败了,那么什么都不会发生。
3、动态请求,都是异步请求。不支持同步请求,async无效。
请求不是通过XHR完成的,而是动态创建script标记,并请求url。跨域请求和dataType: "jsonp" 本身不支持同步操作。
4、若要在fun中使用jsonp请求后的参数,需要注意的是执行顺序,fun需要写在callback中才能成功调用参数。
5、如果没有定义jsonp和jsonpCallback,jsonp默认为"callback",jsonpCallback会是Jquery自动生成的函数名。
6、请求返回的是script tag,首先会调用jsonpCallback函数,不管是否找到该函数,都会调用success函数
参考资料
http://api.jquery.com/jQuery.ajax/
Json的使用
一、简介
JSON:JavaScript 对象表示法
JSON 是存储和交换文本信息的语法。类似 XML。
JSON 比 XML 更小、更快,更易解析。
JSON的媒体类型被定义为 application/json,而文件的后缀为.json。
二、应用
JSON的应用
1、接口
2、微信开发
XML的应用
1、我们一般用于sitemap较多
2、xmlrpc是使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令和数据。
备注:json和XML可以互转
和JavaScript
一、JSON - 转换为 JavaScript 对象
1、能够使用内建的 JavaScript eval(string)方法进行解析
原因:JSON 文本格式在语法上与创建 JavaScript 对象的代码相同。
由于这种相似性,无需解析器,JavaScript 程序能够使用内建的 eval() 函数,用 JSON 数据来生成原生的 JavaScript 对象。
ajax返回的是字符串,而不是json对象。
data = eval('('+data+')');
二、实例
var JSONObject=
{
"name":"Bill Gates", "street":"Fifth Avenue New York 666", "age":56, "phone":"555 1234567"
};
JSONObject.name //调用
三、语法规则
数据在名称/值对中
数据由逗号分隔
花括号保存对象
方括号保存数组
值/对象/数组
四、方法
1、JSON.parse()
parse用于从一个字符串中解析出json对象
例子:
var str = '{"name":"huangxiaojian","age":"23"}'
结果:
JSON.parse(str)
Object
age: "23"
name: "huangxiaojian"
proto: Object
2、JSON.stringify()
stringify()用于从一个对象解析出字符串
例子:
var a = {a:1,b:2}
结果:
JSON.stringify(a)
"{"a":1,"b":2}"
五、错误提示
1、
![]()
data不是正确的json格式,造成解析出错
2、
![]()
var a=JSON.parse('{"a":"aaaaa"}');//正确
var a=JSON.parse("{'a':'aaaaa'}");//错误
3、 Uncaught TypeError: Cannot use 'in' operator to search for '' in JSON string
解决方案:JSON字符串转换为JavaScript对象。
要修复它,通过标准JSON.parse()或jQuery 的 $.parseJSON 将其转换为JavaScript对象。
4、

var a = { };
var b = { a: a };
a.b = b;
JSON.stringify(a);
参考:https://segmentfault.com/a/1190000002532027
php中的json
一、注意点
1、json_last_error:返回最后发生的错误
2、json_decode 当第二个参数为 TRUE 时,将返回 array 而非 object 。
3、由于json只接受utf-8编码的字符,所以json_encode()的参数必须是utf-8编码,否则会得到空字符或者null。
4、PHP支持两种数组,一种是只保存"值"(value)的索引数组(indexed array),另一种是保存"名值对"(name/value)的关联数组(associative array)。
由于javascript不支持关联数组,所以json_encode()只将索引数组(indexed array)转为数组格式,而将关联数组(associative array)转为对象格式。
$arr = array('one', 'two', 'three');
echo json_encode($arr); //["one","two","three"]
$arr = array('1'=>'one', '2'=>'two', '3'=>'three');
echo json_encode($arr); // {"1":"one","2":"two","3":"three"}
数据格式从"[]"(数组)变成了"{}"(对象)。
如果你需要将"索引数组"强制转化成"对象",可以这样写
echo json_encode((object)$arr);
echo json_encode($arr,JSON_FORCE_OBJECT )
5、类的转换
{
"public_ex": "this is public"
}
除了公开变量(public),其他东西(常量、私有变量、方法等等)都遗失了。
二、错误
$json = "{ 'bar': 'baz' }"; //分割符只能用单引号
$json = '{ bar: "baz" }';
$json = '{ "bar": "baz", }';
二、中文编码的问题
1、
function getJson($data){
if(version_compare('5.4',PHP_VERSION,'<')){
//5.4以上
return json_encode($data,JSON_UNESCAPED_UNICODE);
}else{
return urldecode(json_encode(url_encode($data)));
}
}
数据存的json格式,如果数据库存的是array
eval("\$session= $str;");
三、json格式的问题
微信放的json解析不了:
去除反斜杠 StripSlashes
其他补充:
json的校验
一个文本文档或字符串必须遵守JSON的语法定义,才能被视作一个有效的JSON文档。
http://www.jsonlint.com/
补充:
用 JSON 构建 API 的标准指南中文版
http://jsonapi.org.cn/
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 查找系统中最后n24小时被改变文件状态的文件
-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博客问答摘录
