一、概况

这段时间在本科毕设和考研复试,所以PAT甲的题目暂缓了,会及时更新,这篇是我的毕设,欢迎大家的指导和交流!
本项目主要是Docker容器下利用Scrapy-Redis框架实现了分布式爬虫,爬取的是豆瓣图书的信息,然后在Django下,写了一个简易的图书搜索系统,这里图书搜索系统就不展示了,网上有很多的系统模板,主要介绍的是容器下的分布式爬虫实现。本科的论文相对而言我认为表达更全面更完善,所以在这里就是一个简易版本,重点在步骤和过程。

二、系统设计

1、分布式爬虫框架

在这里插入图片描述分布式爬虫架构是由一个master服务器和多个slave服务器共同组成。master服务器和slave服务器之间可以通信,共享master端的redis数据库。同时将分布式爬虫框架中的服务器均搭建成容器,包括1个master容器、3个slave服务器以及一个用来查看mysql数据库中具体数据并方便操作的admin容器,共五个容器。

2、分布式爬虫流程

在这里插入图片描述(1)爬虫预处理
首先,master端对豆瓣图书的各个标签进行爬取。在https://book.douban.com/tag/?view=type&icn=index-sorttags-all中列举了豆瓣图书的标签,如小说、外国文学等。在数据库中以https://book.douban.com/tag/小说的形式保存。

(2)master爬取url
master服务器负责解析豆瓣图书中的tags(标签)下的图书url,将每一个具体的图书url存入redis数据库

(3)slave爬取详情页
slave服务器端负责获取具体图书的url,爬取图书详情页的具体信息并将其转换成json格式,存入master端的redis数据库,使得各个slave服务器爬取获得的详情信息可以汇总。

三、系统实现与测试

1、系统开发环境

工具/环境软件名称
操作系统windows10
docker容器docker 20.10.6
docker容器下的操作系统ubuntu 20.10
开发语言python 3.8.6
浏览器firefox 88.0.1
数据库redis 4.0.9
数据库mysql 8.0.21

2、Docker集群部署

本系统采用一个master端与三个slave端的分布式爬虫框架进行实现与测试,其中master和slave均为容器,另外使用docker官方库中的admin镜像搭建myspider_admin(数据库图形化管理界面),在分布式爬虫完成后,对实验结果进行验证。

容器名容器IDIP地址
masterac74172.17.0.2
slave1c32e172.17.0.3
slave2abfd172.17.0.5
slave333a8172.17.0.6
myspider_adminf84f172.17.0.4

这里的容器ID每个人都会不一样。

(1) Docker的安装
在安装docker完成后,输入以下命令对docker安装进行检验。

docker –version

输入以下命令,查看现有镜像(image),ps -a查看目前存在的容器,发现有docker自带的Ubuntu,Admin等镜像。

docker image ls
docker ps -a

(2) 利用Ubuntu镜像创建容器Master
命令:

docker run -it ubuntu /bin/bash –name master

安装redis,python3,mysql,pip,scrapy-redis等一些基本软件和库。测试master登录redis和mysql数据库,由于redis和mysql都是在容器上运行,不能用本地连接(127.0.0.1),所以在配置相关软件时,要修改其配置文件,将其修改成容器的IP地址。配置完毕后,测试连接
在这里插入图片描述
(3) 创建myspider_admin
利用admin镜像创建容器myspider_admin,并连接到master的mysql数据库,开放8080端口,方便对mysql数据库里的数据访问和下载。在master下创建新的数据库后,进行简单测试,可以在admin中查看到master的数据操作。
在这里插入图片描述
(4) 创建slave容器
将容器master映射成镜像myspider,并用myspider的镜像创建容器slave1连接master,利用命令:

docker run -tid --name slave1 --link master my_spider

对slave1进行测试后,发现可以登录master的redis和mysql的数据库,即表示,slave1和master通信完成,可共享master的数据库。紧接着再创建容器slave2,slave3,和slave1的创建方式一样,利用master所映射的镜像myspider,并连接master,并对其进行测试,测试成功
在这里插入图片描述
这里就把分布式爬虫的框架部署完毕。

3、爬虫实现与测试

(1) 爬虫预处理

对豆瓣图书的标签进行爬取。首先定义Http请求中的Headers相关参数,浏览器信息User-agent,以及url:https://book.douban.com/tag/?view=type&icn=index-sorttags-all。并发送一个完整的请求,返回200,成功处理。当爬虫过于频繁的时候,会返回403错误,显示异常IP的登录。随后连接redis数据库,并读取网页中

下的所有 ,即读取所有标签,并存入redis数据库。在这里插入图片描述

(2)master端爬取图书的url

master端负责爬取redis数据库中book标签下的具体图书url,并再次存入redis数据库。master采用的是scrapy的爬虫框架,所以进入master容器后,确认安装scrapy和scrapy-redis完毕后,利用命令scrapy startproject douban_master(项目名)创建master的爬虫项目。

scrapy爬虫框架中包括部署爬虫项目的配置文件scrapy.cfg和4个组件文件分别为items.py、middlewares.py、pipelines.py、settings.py,以及一个管理多个爬虫的目录spiders。

① items.py
此文件类似于django中的models.py,用于声明数据类型,用来保存数据。由于master端只需要对url进行爬虫,所以在items.py文件中仅存放url这一数据。
② middleware.py
爬虫中间件可以对请求和响应进行处理。from_crawler函数表示创建爬虫。process_spider_input函数表示在response对象交给spider爬虫进行解析前,可以对response进行处理,只能返回None或者抛出一个异常,以及process_spider_output函数表示从response返回的结果中,对后续的item和request进行处理,必须返回request或者item对象。同时,为了防止反爬虫,可以在请求被发起之前对request进行处理,设置请求头一些字段User_agent_type。
③ pipelines.py
管道文件的作用是将每一个item对象进行存储,存进数据库如mysql,redis,mongodb中。代码中使用正则表达式判断url是否有效,并把有效url写入redis数据库。
④ settings.py
此文件是对爬虫项目进行配置的文件。scrapy默认遵守robot.txt协议规则,robots规定了一个网站中,哪些地址可以请求,哪些地址不请求,在配置时,选择False,表示不遵守这个协议。下载延时是请求和请求之间的间隔,降低爬取速度,可以避免被识别到在对豆瓣图书进行爬虫操作。随后配置默认的请求头Headers,自定义的pipelines,指定使scrapy-redis的去重,调度器。在redis中保持scrapy-redis用到的各个队列,从而允许暂停和暂停后恢复,也就是不清理redis queues。最后指定排序爬取地址时使用的队列,默认的按优先级排序(scrapy默认),由sorted set实现的一种非FIFO、LIFO方式。
⑤ spiders目录
这是管理多个爬虫文件的目录,具体的爬虫逻辑都在该目录内。在master端创建book_master.py,自定义爬虫名称name,在运行爬虫项目时,是通过这个唯一值name运行的。随后设置允许访问的网站域名book.douban.com、连接redis数据库信息、爬虫的初始url。在爬虫启动之后,Engine就会提取第一个url,将url构造成一个request对象,交给调度器。在url的请求成功后,便可以解析每个tag下对应的图书详情信息中,及其所对应的url,如:https://book.douban.com/subject/27080946/,将每一个详情页的请求对象,yield到调度器队列中,等待被执行。最后获取下一页的地址,循环,爬取每一本图书的url。
在这里插入图片描述

(3) slave端爬取图书详情信息
首先获取每一个url,通过此url对图书的详细信息进行爬取,并采用json格式存入redis数据库中。进入slave容器,与master容器一样,创建scrapy项目,同样拥有4个组件文件,和管理爬虫的spiders的目录。代码实现方式与master端相同,两者只在爬取的数据内容上具有差别。最后将爬取的内容以json格式存入redis数据库中,直到redis中的url被全部读取完毕后停止。
在这里插入图片描述

最后将redis中存储的每个url所对应的数据转存到mysql中。首先,在mysql中建立数据库doubandb,并建立相应的表books。接着在Python代码中,分别与redis数据库和mysql数据库进行连接,并使用游标的方式读入相关数据。从redis中读取,book_detail:items中的key和value值,将redis中的url所对应的json数据格式的value值解析,组成sql语句,将每一个属性指定其参数,执行insert语句,并将事务提交,直到redis中所有book_detail中的信息被读完,测试成功。
在这里插入图片描述

总结

对于爬虫频繁的豆瓣网站反馈的403问题,还可以利用代理池的代理IP方式解决。整个过程需要一点Linux的基础知识和爬虫代码能力。欢迎大家的指导和交流!

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐