pyspider用起来比较简单,还带UI,作为一个存在这么久的系统,其爬虫的框架和设计思路,能让小白们学到很多东西。
对于不常使用爬虫的人来说,整理和复用代码很麻烦。不如用pyspider省事。
pyspider的官方文档地址:http://docs.pyspider.org/en/latest/
安装配置
安装方法
pip install pyspider
其他的参考互联网吧。
配置
新建一个文件config.ini
{
"webui": {
"username":"admin",
"password":"admin113",
"need_auth":"ture",
"port":9220
}
}
启动方法
mkdir -p data
nohup pyspider --phantomjs-proxy="localhost:25555" -c config.ini &
data是数据存储目录;"nohup和&"保障后台启动
如果启动成功就可以访问9220进入UI了。
停止方法
killall -9 pyspider
pkill -9 phantomjs
错误处理
1.启动的时候报错"connect to scheduler rpc error"(python 2.7环境)
原因:tornado版本不匹配,降到4.5即可
解决方法:
# 查看tornado版本
pip list | grep tornado
# 发现比4.5高,卸载原版本
pip uninstall tornado
# 下载并安装指定版本
wget https://pypi.python.org/pypi/tornado/4.5
tar -zxvf tornado-4.5.tar.gz
cd tornado-4.5
python setup.py build
python setup.py install
另外有人也说要更新six的,好像没必要。
pip install -U six
使用
数据目录
一般在启动命令执行的同级目录下的data文件夹下
主要有三个sqlite数据库
project.db: 存储项目信息,包括代码,就是UI里看到的数据
result.db: 爬取之后的结果,如果没自定义on_result函数就会爬取到这里。
task.db:存储项目运行的一些过程数据, 后面分析为什么pyspider总是运行后不爬取内容时,你会对这个库印象很深。
新建任务
直接在UI上新建一个任务,代码就被创建好了
from pyspider.libs.base_handler import *
class Handler(BaseHandler):
crawl_config = {
}
@every(minutes=24 * 60)
def on_start(self):
self.crawl('https://www.cnblogs.com/xxx/p/113222216.html', callback=self.index_page)
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
for each in response.doc('a[href^="http"]').items():
self.crawl(each.attr.href, callback=self.detail_page)
@config(priority=2)
def detail_page(self, response):
return {
"url": response.url,
"title": response.doc('title').text(),
}
主要就调用一下self.crawl('http://scrapy.org/', callback=self.index_page)
传入一个网址,给一个回调函数,内容就被爬取出来传给回调函数了。
response.doc可以传入一些DOM元素,包括class标签之类的, 识别的方法类似于jquery,但要更强大
比如你要选"class='xxx'"下的a标签可以写成"for each in response.doc('.xxx > a').items():"
如果不知道怎么写还可以借助UI上的"enable css selector helper"分析出字符串填入response.doc函数中。
代码写完之后,点击UI上的RUN调试。
调试完成之后,在project的网页中把status改成"RUNNING"或"DEBUG"任务就会自动运行了。
主要字段
@every(minutes=24 * 60)
@config(age=10 * 24 * 60 * 60)
@config(priority=2)
every: 表示每隔多长时间执行一次
age: 表示当前访问的网页多长时间过期,没过期就不会重新请求。
如上文中的示例,every是每天执行一次,age过期时间是10天,显然中间有9天的定时任务是会直接丢弃请求的。
priority:priority越高越先执行。
priority有什么用呢?
编过程的同学都应该知道DFS和BFS。我们把要爬取的网页类比成一棵树。
如果优先级都一样,不必然,但多数情况会是DFS,如果是二叉树,大概就是先序遍历的样子。
如果要实现BFS需要先让元素入队,每出队一个元素,就把它的子节点入队。
priority就是干这个用的,它可以保障优先级高的先入队。相比于DFS,它多一个队列用来存储元素。
劣势也很明显,如果这棵树一个节点下有无限多个子节点那么显然不适合这样玩。