盗墓笔记案例

目录

目标网址:http://www.daomubiji.com/

数据内容:

scrapy项目

实现分布式的步骤

代码的实现

 Spider.py

1.Python中os.mkdir()与os.makedirs()的区别及用法

2.copy与deepcopy的区别与用法

3.meta传参

4.列表合并

5.正则表达式替换

items.py 

管道保存pipeline.py

settings.py

启动

注意事项:


目标网址:http://www.daomubiji.com/

数据内容:

  1. 书的名称
  2. 章节名称
  3. 文本内容

scrapy项目

  1. 创建项目
  2. 创建爬虫
  3. 定义item
  4. 编写spider
  5. 定义初始请求
  6. 解析响应内容
  7. 定义管道
  8. 运行项目

实现分布式的步骤

  1. 安装:pip install scrapy-redis.
  2. 将爬虫主文件中继承自Scrapy中的scrapy.SpiderCrawlSpider替换成Scrapy-Redis的RedisSpiderRedisCrawlSpider
  3. 初始的start_urls改为redis_kev
  4. settings.py文件中修改Scrapy自带的调度器类和去重类Scrapy-Redis提供的类。
    # 调度器 使用scrapy-redis 
    SCHEDULER = "scrapy redis.scheduler.Scheduler" 
    # 去重的 使用scrapy-redis 
    DUPEFILTER_CLASS = "scrapy_redis.dupeŨ lter.RFPDupeFilter" 
    # 断点续爬 请求持久化 
    SCHEDULER_PERSIST = True
  5. setting里打开管道
    ITEM_PIPELINES = {
       'dmbj.pipelines.DmbjPipeline': 300,
       # 数据保存到redis
       'scrapy_redis.pipelines.RedisPipeline': 400,
    }

代码的实现

 Spider.py

import scrapy
from dmbj.items import DmbjItem
import re, os
from copy import deepcopy

# redis要导入的内容
from scrapy_redis.spiders import RedisSpider

class SpiderSpider(RedisSpider):

    name = 'spider'
    # allowed_domains = ['daomubiji.com']
    # start_urls = ['http://daomubiji.com/']

    # redis要写成这个
    redis_key = 'dmbj'

    def parse(self, response):
        """一级爬取"""
        text = response.text

        html = response.xpath('//ul[@class="sub-menu"]//a')

        for i in html:
            item = DmbjItem()
            # 书名
            item['book_name'] = i.xpath('./text()').get()
            # 连接
            book_link = i.xpath('./@href').get()

            # 书名记得替换特殊字符,预防引发爬取时变成转义字符
            book_path = re.sub(r'[\\\/\:\*\?\"\<\>\|]', '_', item['book_name'])
            # 书本存放路径 
            dirpath = f'./noval/{book_path}'
            # 每本书一个文件见存放
            if not os.path.exists(dirpath):
                os.makedirs(dirpath)
            
            # 发送请求到下一级爬取 记得用深拷贝
            yield scrapy.Request(url=book_link, callback=self.second_parse, meta={'item': deepcopy(item)})

    def second_parse(self, response):
        """二级爬取"""

        # 接受上一个参数的传参
        item = response.meta.get('item')
        article_list = response.xpath('//div[@class="excerpts"]//article')

        for i in article_list:
            # 章节名字
            item['chapter_title'] = i.xpath('./a/text()').get()

            # 章节链接
            content_link = i.xpath('./a/@href').get()

            yield scrapy.Request(url=content_link, callback=self.third_parse, meta={'item': deepcopy(item)})


    def third_parse(self,response):
        """三级爬取"""
        item = response.meta.get('item')

        content = response.xpath('//article[@class="article-content"]/p/text()').getall()
        # 每个段落用换行代替
        item['content'] = '\n'.join(content)

        yield item

设计知识点:

1.Python中os.mkdir()与os.makedirs()的区别及用法

首先说os.mkdir(path),他的功能是一级一级的创建目录,前提是前面的目录已存在,如果不存在会报异常。

import os
 
os.mkdir('d:\hello')    #  正常
os.mkdir('d:\hello\hi') #  正常
 
#  如果d:\hello目录不存在
#  则os.mkdir('d:\hello\hi')执行失败

然后是os.makedirs(path),可以一次创建多级目录,中间目录不存在也能正常的创建。

import os
 
os.makedirs('d:\hello')    #  正常
os.makedirs('d:\hello\hi') #  正常
 
#  如果d:\hello目录不存在
#  则os.makedirs('d:\hello\hi')  #  仍然正常

2.copy与deepcopy的区别与用法

参考这篇博客:copy与deepcopy的区别

3.meta传参

上一级爬虫发送

yield scrapy.Request(url=content_link, callback=self.third_parse, meta={'item': deepcopy(item)})

下级爬虫接受 

item = response.meta.get('item')

4.列表合并

每个段落用换行合并

 # 每个段落用换行代替
 item['content'] = '\n'.join(content)

5.正则表达式替换

 # 书名记得替换特殊字符,预防引发爬取时变成转义字符
 book_path = re.sub(r'[\\\/\:\*\?\"\<\>\|]', '_', item['book_name'])

items.py 

import scrapy


class DmbjItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 书名
    book_name = scrapy.Field()
    # 章节名
    chapter_title = scrapy.Field()
    # 章节内容
    content = scrapy.Field()

管道保存pipeline.py

import re

class DmbjPipeline:

    def open_spider(self,spider):
        pass


    def process_item(self, item, spider):
        # 替换字符
        self.book_name = re.sub(r'[\\\/\:\*\?\"\<\>\|]', '_', item['book_name'])
        self.chapter_title = re.sub(r'[\\\/\:\*\?\"\<\>\|]', '_', item['chapter_title'])

        # 创建文件
        self.f = open(f'./noval/{self.book_name}/{self.chapter_title}.txt','w',encoding='utf-8')
        # 写入
        self.f.write(item["content"])

        return item


    def close_spider(self,spider):
        self.f.close()

settings.py

# 调度器  使用scrapy_redis
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 去重     使用scrapy_redis
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 断点续爬   请求持久化
SCHEDULER_PERSIST = True


ITEM_PIPELINES = {
   'dmbj.pipelines.DmbjPipeline': 300,
   # 数据保存到redis
   'scrapy_redis.pipelines.RedisPipeline': 400,
}

启动

需要打开redis.py,而且创建redis列表,和起始地址

然后开启多个终端模拟多台电脑运行即可

注意事项:

python3.10之后要做出的修改,在spiders.py的源代码里面

from collections import Iterable from collections.abc import Iterable

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依恋、阳光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值