3. 分布式爬虫-Spider¶
该爬虫支持分布式,使用方式与SingleSpider
类似,常用于抓取大规模数据的生产环境。
阅读建议:根据文档的每一步,动手实操
因爬虫与SingleSpider
使用方式类似,更高级的使用方法参考SingleSpider
1. 创建项目¶
> spider create -s test-spider
test-spider 项目生成成功
生成的项目结构如下:
解释说明
- main.py:代码启动入口
- setting.py:项目配置文件
- parsers/:编写爬虫的位置
- items/:数据item文件存放的位置
2. 快速生成分布式爬虫¶
- 进入parsers目录:
cd test-spider/parsers
- 创建爬虫:
spider create -p test_parsers
创建爬虫后,默认生成的代码模板如下:
import spider
class TestSpider(spider.SingleSpider):
def start_requests(self, *args, **kws):
yield spider.Request("https://www.baidu.com")
def parser(self, request, response):
# print(response.text)
print(response.xpath('//input[@type="submit"]/@value').extract_first())
if __name__ == "__main__":
TestSpider().start()
修改基类, 使其继承spider.Spider:
class TestParsers(spider.Spider):
修改配置文件setting.py, 设置数据库连接地址. redis数据库用来做任务队列,mysql数据库用来存储抓取到的数据,二者均均要配置
# MYSQL MYSQL_IP = "" MYSQL_PORT = 3306 MYSQL_DB = "" MYSQL_USER_NAME = "" MYSQL_USER_PASS = "" # REDIS # IP:PORT 多个逗号分隔 REDISDB_IP_PORTS = "localhost:6379" REDISDB_USER_PASS = "" # 默认 0 到 15 共16个数据库 REDISDB_DB = 0
改造main.py, 改成如下:
from parsers import * if __name__ == "__main__": spider = test_parsers.TestParsers(table_folder="test:test1") spider.start()
运行main.py 即可
3. 数据入库¶
数据入库支持两种方式
- 自己编写入库sql,调用操作数据库的第三方包,如pymsql,将数据入库。不推荐,原因如下:
- pymysql不支持并发操作,及多线程
- 数据建议批量入库,自己组装数据,分批入库比较麻烦
- 拼接sql比较麻烦
- 使用框架的item模块。推荐
3.1 item 模块快速入门¶
首先先介绍下item的含义。item 及为抓取的结构化数据,一个item类对应一张表,每个item对象对应表里的一条数据
首先我们先创建一张表,如:
生成item:
返回项目,cd到items目录下,执行
spider create -i spider_test
(spider_test 为第一步创建的表名),打印如下:MainThread|2020-07-13 13:04:43,655|mysqldb.py|__init__|line:90|DEBUG| 连接到mysql数据库 localhost : spider-demo spider_test_item.py 生成成功
观察当前目录,已生成item文件,内容如下:
from spider import Item
class SpiderTestItem(Item):
def __init__(self, *args, **kwargs):
# self.id = None # type : int(10) unsigned | allow_null : NO | key : PRI | default_value : None | extra : auto_increment | column_comment :
self.title = None # type : varchar(255) | allow_null : YES | key : | default_value : None | extra : | column_comment :
- 使用item将数据入库:
修改 parsers/test_parsers.py, 内容如下:
def parser(self, request, response):
title = response.xpath('//title/text()').extract_first() # 取标题
item = spider_test_item.SpiderTestItem() # 声明一个item
item.title = title # 给item属性赋值
yield item # 返回item, item会自动批量入库
总结:
数据入库, 只需要根据表生成item, 然后给item赋值, 之后直接 yield item 即可
示例代码:https://github.com/Boris-code/boris-spider-demo/tree/master/spider_demo
4.Spider类参数详解¶
def __init__(
self,
table_folder=None,
min_task_count=1,
check_task_interval=5,
parser_count=None,
begin_callback=None,
end_callback=None,
delete_tabs=(),
process_num=None,
auto_stop_when_spider_done=None,
auto_start_requests=None,
send_run_time=False,
batch_interval=0,
*parser_args,
**parser_kwargs
):
"""
@summary: 爬虫
---------
@param table_folder: 爬虫request及item存放redis中的文件夹
@param min_task_count: redis 中最少任务数, 少于这个数量会从mysql的任务表取任务。默认1秒
@param check_task_interval: 检查是否还有任务的时间间隔;默认5秒
@param parser_count: 线程数,默认为配置文件中的线程数
@param begin_callback: 爬虫开始回调函数
@param end_callback: 爬虫结束回调函数
@param delete_tabs: 爬虫启动时删除的表,元组类型。 支持正则
@param process_num: 进程数
@param auto_stop_when_spider_done: 爬虫抓取完毕后是否自动结束或等待任务,默认自动结束
@param auto_start_requests: 爬虫是否自动添加任务
@param send_run_time: 发送运行时间
@param batch_interval: 抓取时间间隔 默认为0 天为单位 多次启动时,只有当前时间与第一次抓取结束的时间间隔大于指定的时间间隔时,爬虫才启动
@param *parser_args: 传给parser下start_requests的参数, tuple()
@param **parser_kwargs: 传给parser下start_requests的参数, dict()
---------
@result:
"""