小子 发布的文章

ie文字强制换行

现象

small标签,word-break: break-all; 在chrome下面正常换行,而在ie下面不起作用

解决

ie下的word-break: break-all; 貌似在block元素上才会起作用,加上display: block; 就可以了。

object-c in_array

判断的三种方式:

//
//  main.m
//  learning
//
//  Created by xiaozi on 13-12-8.
//  Copyright (c) 2013年 xiaozi. All rights reserved.
//

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        
        NSString* extsStr = @"php,js,py";
        NSArray* extsArr = [extsStr componentsSeparatedByString:@","];
        
        // 是否在数组中 {{{
        NSPredicate* rule1 = [NSPredicate predicateWithFormat:@"SELF IN %@", extsArr];
        BOOL result1 = [rule1 evaluateWithObject:@"txt"];
        NSLog(@"%d", result1);
        // }}}
        
        // {{{
        NSPredicate* rule2 = [NSPredicate predicateWithFormat:@"SELF CONTAINS %@", @"js"];
        
        // 数组包含
        BOOL result2 = [rule2 evaluateWithObject:extsArr];
        NSLog(@"%d", result2);
        // }}}
        
        // 数组过滤
        BOOL result3 = [[extsArr filteredArrayUsingPredicate:rule2] count];
        NSLog(@"%d", result3);
        
    }
    return 0;
}

python抓取taobao ip数据库

准备

由于taobao提供了rest api,所以这次就不用scrapy了,改用unirest

pip install unirest

代码

unirest是异步请求的(多线程),所以提供一个callback,但是要是有额外的参数需要传入,用全局变量的话会产生问题。

具体的实现可以根据纯真IP数据库的IP段来查询,单台机器抓取的话估计2~3天的样子,下面是单个IP段抓取的实现代码:

# encoding: utf-8
import time, unirest

def pp(extra):
    # 其实这种做法和js很像,用一个闭包限制变量的作用域
    def p(resp):
        print(extra)
        # 在这里做数据的处理和储存
    return p

def main():
    r = ['192.9.201.0', '192.9.201.255'];
    unirest.get('http://ip.taobao.com/service/getIpInfo.php', headers = {}, params = {'ip': r[0]}, auth = (), callback = pp(r))
    # taobao访问限制:为了保障服务正常运行,每个用户的访问频率需小于10qps。
    time.sleep(.5)

if __name__ == '__main__':
    main()

[Laravel4] 使用command执行任务

场景

  1. 比如使用redis作为计数器,然后在每天的凌晨将计数保存到MySQL
  2. 比如定时执行一些批量的任务

扩展artisan的command

例子:批量将文字题目生成为图片

artisan command:make QuestionCommand
# app/command/QuestionCommand.php

生成php文件之后,首先需要修改name为你的命令

protected $name = 'question:gen';

getArguments, getOptions 分别为获取参数和选项的值

getArguments // command arg1 arg2
getOptions // command --opt1=val1 --opt2=val2
fire // 执行命令的时候具体要做的事情

较为完整的例子

<?php

use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;

class QuestionCommand extends Command {

    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'question:gen';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '生成question图片';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return void
     */
    public function fire()
    {
        $questions = $this->option('all') ? Question::all() : Question::whereThumb(0)->get();
        // 初始化markdown解析引擎
        $ciconia = new Ciconia\Ciconia();
        $ciconia->addExtension(new Ciconia\Extension\Gfm\FencedCodeBlockExtension());
        $ciconia->addExtension(new Ciconia\Extension\Gfm\TaskListExtension());
        $ciconia->addExtension(new Ciconia\Extension\Gfm\InlineStyleExtension());
        $ciconia->addExtension(new Ciconia\Extension\Gfm\WhiteSpaceExtension());
        $ciconia->addExtension(new Ciconia\Extension\Gfm\TableExtension());
        foreach ($questions as $question) {
            $item = array(
                'id' => $question->id,
                'absPath' => public_path('upload/question/' . $question->id . '.png'),
                'relPath' => 'question/' . $question->id . '.png',
                'question' => $ciconia->render($question->question),
            );
            Queue::push('code2png', $item, 'code2png');
            $this->info('Question ' . $question->id . ' has been added to the queue.');
        }
    }

    /**
     * Get the console command arguments.
     *
     * @return array
     */
    protected function getArguments()
    {
        return array(
            // array('example', InputArgument::REQUIRED, 'An example argument.'),
        );
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return array(
            array('all', null, InputOption::VALUE_OPTIONAL, '全部重新生成', null),
        );
    }

}

需要在app/start/artisan.php里面添加下面一行才会生效

// 4.0
$artisan->add(new QuestionCommand);
// 4.1
Artisan::add(new QuestionCommand);

命令行中这样执行

artisan question:gen --all=1

如果要在Controller里面调用,可以这样

Artisan::call('question:gen', array('--all' => 1));

[Laravel4] 从数据库读取配置

再次验证时发现下面的代码有问题,有待修复

场景

很多时候我们的网站的配置都是存在数据库里面的,这样后台也方便配置修改。而Laravel4默认的是将数组直接写在配置文件里面的。

解决

Get Config from database 这个还不错,但是有个问题,就是不支持这样的$register = Config::get('site.register'); var_dump($register['invite']);类似于多级数组的意思

数据库里面直接这样写:

|       key       | value |
|-----------------|-------|
| register.invite |   1   |

我们改造一下

<?php
// app/config/site.php
class DBconfiguratorObject implements ArrayAccess, Serializable {
    protected $config = array();
    protected $table = null;

    private static $_instance = null;

    public static function instance($tableName = 'site'){
        if(self::$_instance === null){
            self::$_instance = new self($tableName);
        }
        return self::$_instance;
    }

    private function __construct($tableName = 'site'){
        $this->table = DB::table($tableName);
        $config = $this->table->lists('value', 'key');
        $this->config = array();
        foreach ($config as $key => $value) {
            array_set($this->config, $key, $value);
        }
    }

    public function offsetGet($key){
        // return $this->config[$key];
        return array_get($this->config, $key);
    }

    public function offsetSet($key, $value){
        if($this->offsetExists($key)){
            $this->table->where('key', $key)->update(array(
                'value' => $value
            ));
        } else {
            $this->table->insert(array(
                'key' => $key,
                'value' => $value
            ));
        }
        $this->config[$key] = $value;
    }

    public function offsetExists($key){
        return isset($this->config[$key]);
    }

    public function offsetUnset($key){
        unset($this->config[$key]);
        $this->table->where('key', $key)->delete();
    }

    public function serialize(){
        return serialize($this->config);
    }

    public function unserialize($serialized){
        $config = unserialize($serialized);
        foreach($config as $key => $value){
            $this[$key] = $value;
        }
    }

    public function toJson(){
        return json_encode($this->config);
    }
}

return DBconfiguratorObject::instance();

php正则匹配出错的问题

发现

因为用了laravel4的

Response::json(array())->setCallback('callback')

然后始终报

The callback name is not valid.

然后单独写了个test.php文件测试该语句在不同的机器上测下来的结果不一样。

var_dump(preg_match('/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*+$/u', 'sad'));

解决

本以为是系统哪边的设置的问题,于是将envphp -i的结果都比对了一遍,都一样。后来想到看一下pcre的版本是否一致pcre-config --version,结果都是6.6;最后没办法rmp -qa | grep pcre,好家伙最后的小版本不一样;再然后你懂的,升级了一下pcre就正常了。

附注

  • 有问题的版本: pcre-6.6-2.el5_1.7
  • 升级后的版本: pcre-6.6-9.el5

php重启apache服务

这里有个矛盾的地方,就是 php是作为Apache的一个模块来运行的,所以一旦重启Apache,在Apache停掉的时候,php调用的shell命令就不会继续执行了;也就是说,只能关闭Apache,不能启动Apache。

我想到的办法就是将命令交给其他程序去运行,于是就想到了at命令。man at只看到at -f [file] now从文件读取,但是我就一个命令,不想再生成一个文件,然后就想到了管道,试一下,成功了。

echo 'sudo service httpd restart' | at now

注:at命令,apache用户需要有登录权限(/etc/passwd)

<time datetime="2013-11-03">2013-11-03 修改</time>

不知为何用apache去启动的服务,在apache服务退出的时候会接管apache的端口

AfterEffects打字效果

效果

效果

QQ20131020-1.png
代码:

l = text.sourceText.length
ti = time - thisLayer.inPoint
t = ti * effect('speed')('滑块') - effect('speed')('滑块') * effect('startAt')('滑块');
cursor = Math.round(ti % 1) || (t < l && t > 0) ? '|' : '';
substr(0, t) + cursor;

效果下载

typing.ffx.zip

CentOS6.4 上编译 pdf2htmlex

编译fontforge

直接git clone下来的代码,貌似和glib2的版本不太匹配。于是我是下的他的一个tag,然后编译的。

wget https://github.com/fontforge/fontforge/archive/v20120731-b.tar.gz
./configure --without-libzmq --without-x --without-iconv --disable-python-scripting --disable-python-extension

编译pdf2htmlex

我在编译pdf2htmlex的时候遇到了下面的错误

Linking CXX executable pdf2htmlEX
/usr/local/lib/libfontforge.so: undefined reference to `PyTuple_SetItem'
/usr/local/lib/libfontforge.so: undefined reference to `PyObject_SelfIter'

修改一下link.txt就可以了

vim CMakeFiles/pdf2htmlEX.dir/link.txt
# 加上一个编译参数 -lpython2.6

php opcode的反解

查看opcode的扩展安装方法:《编译php vld扩展》

手动反解步骤

opcode的对照表 opcode的对照表
换行的ascii是10,换算成16进制就是A
1.png
2.png

反解出的文件和源文件的对比

<?php
$a = 1;
echo $a + $a++;
echo "\n";
$a = 1;
echo $a + $a + $a++;
echo "\n";</code></pre><p><a href="http://type.so/usr/uploads/2013/10/1563209402.png" title="3.png"><img src="http://type.so/usr/uploads/2013/10/1563209402.png" alt="3.png" /></a></p>

编译php vld扩展

wget http://pecl.php.net/get/vld-0.12.0.tgz
tar zxf vld-0.12.0.tgz
phpize
./configure
make && make install

# vim /usr/local/php/etc/php.ini
# extension=vld.so

# 查看扩展是否已经加载
php -m | grep vld

# 试一试
php -dvld.active=1 test.php

树莓派 开关控制LED

接线

Untitled Sketch_bb.jpg

代码实现

通过读取GPIO PIN的值,在按钮按下并松开之后更改LED的状态;从而进行灯的亮灭的切换。

#!/usr/local/env python
# encoding: utf-8

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(17, GPIO.IN)

light = False

while 1:
	i = GPIO.input(17)
	if i:
		print('检测到按钮按下')
		while 1:
			i = GPIO.input(17)
			if not i:
				print('检测到按钮松开')
				GPIO.output(18, light)
				light = not light
				break
	time.sleep(.2)

树莓派 LED呼吸灯

预览

2013-09-03 22_00_48.gif

接线

+接个3.3v的电源,-接18口Untitled Sketch_bb.jpg

代码实现

#!/usr/bin/env python
# encoding: utf-8

import RPi.GPIO
import time
# 正常呼吸为3s一次,深呼吸6s一次
'''
RPi.GPIO.setmode(RPi.GPIO.BOARD)
RPi.GPIO.setup(12, RPi.GPIO.OUT)

pwm = RPi.GPIO.PWM(12, 50)
pwm.start(0)
'''
RPi.GPIO.setmode(RPi.GPIO.BCM)
RPi.GPIO.setup(18, RPi.GPIO.OUT)

pwm = RPi.GPIO.PWM(18, 50)
pwm.start(0)
try:
	while True:
		for i in xrange(0, 101, 2):
			pwm.ChangeDutyCycle(i)
			time.sleep(.03)
		for i in xrange(100, -1, -2):
			pwm.ChangeDutyCycle(i)
			time.sleep(.03)
except KeyboardInterrupt:
	pass

pwm.stop()

RPi.GPIO.cleanup()