golang写文件OpenFile默认不会自动覆写

0 条评论

在golang中,写文件可以这样操作,先用OpenFile打开句柄,然后写入。

fd, err := os.OpenFile(fname, os.O_WRONLY|os.O_CREATE, os.ModePerm)

这个句柄是打开写模式并且如果文件不存在就创建,看起来没有任何问题,但事实上如果文件之前存在了,并且本次写入的内容少于之前的内容,文件的内容将会乱套。

原因是OpenFile打开的句柄必须显式地声明覆写文件,要不然它不会执行清空文件就直接写入新内容,如果本次内容较少,得到的将会是本次内容+上次内部的后面部分,也就是一个乱掉的文件。

解决办法是显式地声明 O_TRUNC,如下:

fd, err := os.OpenFile(dst, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)

2014年10月28日阅读全文

phantomjs抓取https(ssl)页面失败

0 条评论

用phantomjs抓取网页一直运行稳定,但近期却发现抓取https(ssl)页面会失败,而返回的原因是:fail reason: SSL handshake failed。

很明显,原因显示了 SSL 握手失败,已经很明显了,回想一下近来出现的 SSLv3 POODLE,肯定是这些网站禁用了SSLv3导致的。

phantomjs 默认就是使用 SSLv3 协议的,所以失败是正常的。

发了一下文档,有个参数可以指定 SSL 协议,--ssl-protocol=val,于是将参数指定为 --ssl-protocol=TLSv1,问题解决。

2014年10月21日阅读全文

phantomjs页面抓取失败时返回失败原因

0 条评论

我有这么一个phantomjs脚本,用于抓取网页的标题。

var page = require('webpage').create();

page.open(phantom.args[0], function(status) {

if (status == 'success') {

var title = page.evaluate(function() {

return document.title;

});

console.log(title)

phantom.exit(0);

} else {

console.log(status);

phantom.exit(1);

}

});

有的时候,抓取网页会失败,它会打印出来一个fail,但没有打印fail的原因。

根据官方文档,原因不会传到callback里面,得自己写一个新的callback加到page的事件里面,代码如下:

var page = require('webpage').create();

page.onResourceError = function(e) {

page.reason = e.errorString;

}

page.open(phantom.args[0], function(status) {

if (status == 'success') {

var title = page.evaluate(function() {

return document.title;

});

console.log(title)

phantom.exit(0);

} else {

console.log(status, 'reason: ', page.reason);

phantom.exit(1);

}

});

这个时候如果出错了,就会清楚地打印出原因了,如:fail reason: Host not found。

2014年10月21日阅读全文

python Error: Can't use str...

0 条评论

如果您在python中看到了这个错误,那么说明您正在用python 3。

python 3 针对 unicode 的支持做了很多的改进,这就是其中一个特性。

遇到这个问题的时候,我正在用 python 的 urllib 库抓取一个网页,然后将返回放到 re.match 中,然后就出来这个错误了。

例如:data = urllib.urlopen('http://www.zhetenga.com').read(); re.match(r'xxx', data)。

原因是:urllib 返回的 response 是 bytes,而不是期望的 strings,直接传给 re.match 就出现了:

Error: Can't use string pattern on a byte-like object。

而解决办法是将 bytes 转为 string,再传进去,例如:re.match(r'xxx', data.decode('utf-8'))。

2014年08月07日阅读全文

给python的requests提交了关于中文乱码的p...

0 条评论

前面提到 python 的 requests 默认只从http返回的headers去获取页面编码,如果获取不到就用默认的 ISO-8859-1,这样一来很多中文的页面抓取回来都乱码了。

为了解决这个办法,我改了一点代码,基本上达到了这个目标,虽然代码一点都不优雅。

requests 的代码结构十分复杂,为了实现这一愿望折腾了很久,包括改代码的位置、方法等都折腾了很久才达到效果。

最后推上去发现python3下一直无法通过自动测试,这里又折腾了很久,主要还是 byte 和 str 的一些问题。

问题都解决了,自动测试也写了,代码也推了,最后自动测试也终于通过了,现在只等着看他们愿意不愿意合并了。

不管怎样,这是我第一次在github提交pull request,不管结果怎样,都是折腾得很高兴的。

给python的requests提交了关于中文乱码的pull request 图1

给python的requests提交了关于中文乱码的pull request 图2

给python的requests提交了关于中文乱码的pull request 图3

2014年08月07日阅读全文

python的requests类抓取中文页面出现乱码

0 条评论

requests 是一个python的http请求类库,基于urllib3,但支持更多的特性以及更人性化的API。

最近用requests抓取一个中文gb2312编码的页面时,整个页面的中文都乱码了。

基本上乱码就肯定是编码了,首先想到了是不是requests识别编码的时候识别错了,转到其它编码去了。

于是加上调试,打印出来 response.encoding,发现居然是:ISO-8859-1 这个奇怪的编码。

搜索了一下相关的说明,发现 requests 只会简单地从服务器返回的响应头的 Content-Type 去获取编码,如果有 Charset 才能正确识别编码,否则就使用默认的 ISO-8859-1,这样一来某些不规范的服务器返回就必然乱码了。

requests 内部的 utils 提供了一个从返回 body 获取页面编码的函数,get_encodings_from_content,这样如果服务器返回的头不含 Charset,再通过 get_encodings_from_content 就可以知道页面的正确编码了。

知道了原因,解决就容易了,一个方法是写一个 patch 将 requests.models.Response.content 打上补丁,而这明显比较麻烦。

而另一个办法就是先用 ISO-8859-1 再 encode 一次,再用获取的准确的 charset 去decode,这样省事了,不过肯定影响效率并且可能会有转换丢失。

代码:response.text.encode('ISO-8859-1').decode(requests.utils.get_encodings_from_content(response.text)[0]) 。

2014年08月06日阅读全文

python通过字符串的函数名称执行指定函数

0 条评论

例如我在python中定义了函数 zhetenga,现在根据某些条件,得到了要执行的函数名称的字符串 'zhetenga'。

要通过字符串的函数名称执行指定函数,可以直接 exec 'zhetenga' + '()'。

但是这样一点都不优雅,写得不爽看着更不爽,于是我来看看有没有优雅的办法。

假如有类 test,里面有个函数 zhetenga,现在要想调用 zheteng 的话,可以执行:getattr(test, 'zheteng')()。

但是如果不是类的函数的话,这样就不行了,但还是可以变通一下的,通过执行:locals()["zheteng"]()。

2014年08月06日阅读全文

gunicorn重启时日志出现警告:epoll_wai...

0 条评论

在gunicorn的启动参数增加了timeout之后,再重启gunicorn,发现日志中出现了一个警告。

[warn] epoll_wait: Invalid argument

Restarting gevent.core.dispatch() after an error [1]: [Errno 22] Invalid argument

虽然只是警告不是错误,但很明显看着也很不爽。

日志的内容看不懂说了什么,也不知道代表哪里有问题,还好我清楚地记得只是增加了timeout参数。

回想本地环境加了timeout参数都没有这个问题,然后再看,发现区别只是gunicorn版本不同而已。

Google一查,果然有人说某版本的gevent有bug,然后果断升级了gevent和gunicorn,再重启,果然日志很干净了。

这就是传说中的升级版本解决问题。

2014年08月04日阅读全文

UDP数据包允许的最大数据长度

0 条评论

理论上,一个UDP数据包最大为2^16,也就是65536,那么最大的数据长度就是:65536 - 20(IP头) - 8(UDP头) = 65507 bytes。

但是,在网络传输的时候有一个MTU(最大传输单元),如果包大小超出了MTU,将会被拆分传输,由于UDP并不是可靠的传输,分片可能会丢失,所以一般情况下都不会这样做,也就是UDP数据包最大不超过MTU。

以太网(Ethernet)MTU的默认值是1500,所以这个时候UDP包的最大数据长度就是:1472 = 1500 - 20 -8 bytes。

而在因特网(Internet)标准MTU值为576,所以这个时候UDP包的最大数据长度就是:508 = 576 - 60(IP头) - 8(UDP头) bytes。

基于以上原因,一般情况下一个DNS的UDP包的最大长度是512 bytes。

2014年07月31日阅读全文

无法用ssh key登录centos6

0 条评论

装好 centos 6.x 后,通过 ssh-copy-id 将 ssh key 复制到了服务器上,尝试 ssh 上去的时候依然提示输入密码。

折腾了无数次都没有解决,包括修改并确认了 sshd_config,authorized_keys 文件权限等,始终无法解决。

后来通过搜索引擎,在看了一堆无效的办法后最终发现是 SELinux 的问题,终于明白过来了。

解决办法也很简,直接执行:echo 0 > /selinux/enforce 。

2014年07月17日阅读全文
  1. «
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. 10
  12. 11
  13. 12
  14. 13
  15. 14
  16. 15
  17. ...
  18. 17
  19. »