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,它多一个队列用来存储元素。
劣势也很明显,如果这棵树一个节点下有无限多个子节点那么显然不适合这样玩。

posted on 2020-12-07 11:17  步孤天  阅读(636)  评论(0编辑  收藏  举报