pyspider 爬虫使用与解析

pyspider 是一个实时爬虫框架,提供了强大的调度控制,支持分布式部署,Docker 部署,提供可替换组建,可以使用任何html解析包(内置 pyquery)。

同时 pyspider 还提供了一套WEB客户端工具,在WEBUI中可以编写,调试脚本,监控实时状态,download抓取结果,dashboard 中对 task 进行管理。(localhost:5000)

项目的 github 主页:https://github.com/binux/pyspider
英文文档:http://docs.pyspider.org/en/latest/
架构设计:http://blog.binux.me/2014/02/pyspider-architecture/

作者的三篇中文教程(文档翻译):
http://blog.binux.me/2015/01/pyspider-tutorial-level-1-html-and-css-selector/
http://blog.binux.me/2015/01/pyspider-tutorial-level-2-ajax-and-more-http/
http://blog.binux.me/2015/01/pyspider-tutorial-level-3-render-with-phantomjs/

一、 爬取搜狗问问为例讲解 pyspider 的简单使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2016-09-06 13:52:54
# Project: zhidao

from pyspider.libs.base_handler import *
import re


class Handler(BaseHandler):
crawl_config = {
}
def __init__(self):
# 这个构造函数可以没有,对初始链接进行一些预处理
key_words = ['空调','家居装修','家居','家电','电饭煲','微波炉','烤箱','洗衣机','空调','冰箱','电视']
url_list = []
# 关键词列表
for key_word in key_words:
# 页码拼接
start_url1 = 'http://wenwen.qq.com/s/?w='+key_word+'&pg='
start_url2 = '&ch=sp.pt'
for i in range(100):
su = start_url1+str(i)+start_url2
url_list.append(su)
self.url_list = url_list
@every(minutes=24 * 60)
def on_start(self):
# 爬取的入口
for url in self.url_list:
start_url = url
# headers 设置,这里可以设置代理,cookie等
self.crawl(start_url,headers={
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
}, callback=self.index_page)


@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
# response.doc('#result_list > div > h3 > a') 这里是 css selector
# pyspider 的 WEBUI 提供了 css selector helper,可以在单步调试下逐步选取
for each in response.doc('#result_list > div > h3 > a').items():
if (response.doc('a > span').text() == u'略懂社'):
# 这里的 if 逻辑主要是因为 sougou 问问的搜索结果中有来自 略懂社的链接
# 需要进行一次连接跳转 拼接url
qid = str(re.findall(r'/z/q\d+',each.attr.href))[7:-2]
url = 'http://wenwen.qq.com/qunapp/world/question?qid='+qid+'&viewsrc=1&ch=fromsearch.pc'
# 略懂社的页面是 AJAX 动态加载的
# 需要 phantomjs 框架的支持来进行爬取
self.crawl(url, callback=self.detail_page,fetch_type='js')
else:
self.crawl(each.attr.href, callback=self.detail_page2)
@config(priority=2)
def detail_page(self, response):
return {
"title": response.doc('.yy-mt1 > pre').text(),
"text": response.doc('.answer_text').text(),
}

@config(priority=2)
def detail_page2(self, response):
# 返回的内容,在 dashboard 里可以以 csv 或 json格式下载
# 也可以直接写函数写在本地
return {
"title": response.doc('.question-tit > h3').text(),
"text": response.doc('.answer-con').text(),
}
"""
def list_page(self, response):
# 这是一个翻页的回调函数 我没有用
for each in response.doc('#wgt-list > dl > dt > a').items():
self.crawl(each.attr.href, callback=self.detail_page)
# 翻页
# 这里加入翻页的 selector
for each in response.doc('#page-main > div > div > div > div.list-inner > div.widget-pager.clearfix.mb-20 > div > a.pager-next').items():
self.crawl(each.attr.href, callback=self.list_page)
"""