前几天写了一个爬虫,现在放出来,希望大家在学习爬虫的时候可以少走一点弯路
项目的需求如下:爬取起点网上所有作者的所有作品的链接
先说明一点,这个项目的主要目的是练习,因此会有一些不合理的地方,请大家不要在意这些细节
我们来看一下主要的架构图:
整个架构使用了生产者-消费者模式,AuthorSpider负责爬作者的链接,BookSpider负责爬取该作者的所有作品。
在本项目中,由于只是练习,我直接把AuthorList放在内存的(实际项目中千万别这样做),可以本地化存储(当然这样很难做到实时去重,可以采用广度优先策略,先爬所有的作者,然后去重,再去爬作者名下的所有作品),在分布式系统中,一般用一些消息中间件去取代AuthorList。
下面我们来看看目录结构
mycmd 是我自己写的同时启动多个爬虫的命令(主要是为了保证爬虫运行在同一个进程,不然运行在不同的进程,AuthorList就不能保证是同一个了)
repository 是一些存取数据的逻辑
spiders 是爬虫的逻辑
tool 由于我的IP是买的,也没有用他们直接提供的接口,直接就是复制过来的,我用IPTransform来得到我想要的IP格式
items定义了 需要提取的数据
middlewares里面我主要写了一个IP池和一个用户池
pipelines是一些数据处理的逻辑,把处理后的数据往repository里丢
setting是一些配置文件
sql是建数据库的sql语句
run是启动爬虫的方法
下面我讲一下关键的代码
import scrapy
from qidianspider.items import AuthorItem
from scrapy.http import Request
import time
#这是获取作者的爬虫
class AuthorspiderSpider(scrapy.Spider):
#定义一个计数的全局变量
global i
i = 1
name = 'AuthorSpider'
allowed_domains = ['qidian.com']
#从第一页开始爬
start_urls = ['http://www.qidian.com/all?page=1']
def parse(self, response):
global i
item=AuthorItem()
#提取需要的信息,作者名和其主页链接
item["name"]=response.xpath("//p[@class='author']/a[@class='name']/text()").extract()
item["link"] = response.xpath("//p[@class='au