一、技术选型
本来最开始的想法是统一一种脚本语言完成WEB端以及爬虫代码开发,如PHP+PHP爬虫框架(如Beanbun)、Python Django+Python爬虫框架(这个就比较多的选择如Scrapy),因为之前用PHP做WEB项目较多,有一些现成的代码积累,所有最开始是想选PHP+PHP爬虫框架,后面在预研过程中发现Beanbun虽然它的架构我很喜欢,但与自己的需求相差较大,一些功能很难做到,需要做比较多的订制开发,Beanbun数据处理流程:
而Python Django+Python爬虫框架正常来说更符合爬虫的需求,WEB框架Django Python编写与Python爬虫完美集成,但无奈Django了解的不多,又不想从0开始开发WEB管理平台。最终选择的是PHP+Python爬虫框架,下面对WEB服务端和Python爬虫框架选型进行具体介绍:
一、WEB服务:爬虫管理
WEB服务用的PHP, 一个MVC框架,应用和系统管理可以独立开,插件式开发。
项目目录结构:
爬虫模块代码结构:
爬虫管理界面:
爬虫新增:
爬虫执行:
爬虫执行日志和数据(关键指标还没开发完 # —— #):
主体流程已经开发完成,主要的核心在URL导航规则和采集内容的规则,选择器支持XPATH和CSS,导航决定采集的深度和过滤方式,采集内容决定具体需要的结果,后面定义了一些数据加工的选项(部分还未实现哈),如下图:
(2017年9月12更新)
二、Python爬虫Scrapy自动生成
1、Scrapy爬虫模板
生成通用Scrapy爬虫模板,PHP调用Smarty模板引擎,根据WEB界面配置管理的爬虫参数,自动生成目标爬虫代码。部分代码实现如下:
模板工程结构:
scrapy.sh爬虫执行脚本(待Smarty解析):
items.py爬取需要的字段:
spider.py核心代码也比较少:
看一个自动生成的代码:
目录结构
spider.py最终自动生成是下面这样(还有一些通用的Proxy IP 池,Agent等):
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import logging
"""Topic: sampleDesc :"""
from zhihu1504782015.items import zhihu1504782015Item
import scrapy
class zhihu1504782015Spider(scrapy.Spider):
name = "zhihu1504782015"
allowed_domains = ['huxiu.com']
start_urls = ['http://www.huxiu.com/index.php']
def parse(self, response):
for sel in response.xpath('//div[@class="mod-info-flow"]/div/div[@class="mob-ctt"]'):
item = zhihu1504782015Item()
item['hqC1c2DTi883y8Zyxq8i'] = sel.xpath('h2/a/text()')[0].extract()
item['x11kyk61C1P4e66qa111'] = sel.xpath('h2/a/@href')[0].extract()
url = response.urljoin(item['x11kyk61C1P4e66qa111'])
self.logger.info('Parse function called on%s',url)
item['w4Dd8W28ff3Em84GFB7s'] = sel.xpath('//div[@class="mob-sub"]/text()')[0].extract()
yield scrapy.Request(url, callback=self.parse_article)
def parse_article(self, response):
detail = response.xpath('//div[@class="article-wrap"]')
item = zhihu1504782015Item()
item['hqC1c2DTi883y8Zyxq8i'] = detail.xpath('h1/text()')[0].extract()
item['x11kyk61C1P4e66qa111'] = response.url
self.logger.info('Parse function called on%s',item['x11kyk61C1P4e66qa111'])
item['w4Dd8W28ff3Em84GFB7s'] =''
self.logger.info(item['hqC1c2DTi883y8Zyxq8i']+item['x11kyk61C1P4e66qa111']+item['w4Dd8W28ff3Em84GFB7s'])
yield item
代码中变量多为自动生成的, 所以可读性不太好,代码还有很多可完善的地方,现在至少整个流程已跑通,哈哈
(更新于2017-09-26 20点)
后面将主要实现字段加工部份
待续~~~