使用scrapy爬取糗事百科的的段子,并保存到redis

爬取的初始网址是: https://www.qiushibaike.com/text/page/1/

首先需要创建项目

cd 目录路径进入到对应的目录
然后使用下面的代码进行创建 scrapy 项目

# 项目名: qsbk
scrapy startproject qsbk

在这里插入图片描述

进入目录 qsbk , 并使用crawl模版创建爬虫文件

# -t crawl | 使用 crawl模版
# text | 爬虫文件名 执行爬虫的名字
# www.qiushibaike.com | 爬虫允许的域名
scrapy genspider -t crawl text www.qiushibaike.com

在这里插入图片描述

在这里插入图片描述

进行修改配置文件 settings.py

# ...省略部分代码
# 找到下面一句, 进行复制到下一行, 并把值改为 False
# 是否遵守 robots.txt 的规则
# ROBOTSTXT_OBEY = True
ROBOTSTXT_OBEY = False
# ...省略部分代码
#DOWNLOADER_MIDDLEWARES = {
#    'qsbk.middlewares.QsbkDownloaderMiddleware': 543,
#}
# 找到下面一段, 进行复制到下一行
# 是否启用下载器中间件 (动态ua使用)
DOWNLOADER_MIDDLEWARES = {
   'qsbk.middlewares.QsbkDownloaderMiddleware': 543,
}
# ...省略部分代码
# 找到下面一段, 进行复制到下一行
# 使用什么方式进行数据存储
# ITEM_PIPELINES = {
#    'qsbk.pipelines.QsbkPipeline': 300,
# }
ITEM_PIPELINES = {
   # 'qsbk.pipelines.QsbkPipeline': 300,
   # 这是新增的部分
   # 这里是使用 redis 进行存储, 暂时先不用
   # 'scrapy_redis.pipelines.RedisPipeline': 400,
}
# ...省略部分代码
# 增加这一句
# 日志是否打印输出
LOG_ENABLED = False

# 分布式配置
# 以下3句是分布式redis需要的
# DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# SCHEDULER_PERSIST = True

进行修改下载器中间件 middlewares.py

from scrapy import signals

# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter
# 在 头部导入库的位置加上这一句
# UserAgent 是为了实现多个网页爬取时使用随机ua
from fake_useragent import UserAgent
# ...省略部分代码
# 找到这一句
class QsbkDownloaderMiddleware:
# 找到下面方法
 def process_request(self, request, spider):
 	# 加上这一句, 修改响应头信息的ua 设置为随机ua
	request.headers['User-Agent'] = UserAgent().random

修改爬虫文件 text.py

# 在导入位置加上这一句
# 导入 pyquery 用于页面解析获取数据
from pyquery import PyQuery as pq

# 在爬虫类里面设置这个
start_urls = ['https://www.qiushibaike.com/text/page/1/']

# 加上这一句
redis_key = 'TextSpider:start_urls'  # 第一页由redis传入

# 在规则部分设置这两句
rules = (
        # Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
        # https://www.qiushibaike.com/text/page/1/
        # allow 内使用正则 | \d 表示数字 | + 表示一个或多个
        # follow 爬取后是否继续爬
        # callback 爬取后交给那个函数或方法处理 使用字符串表示当前对象的某个方法 也可以直接 self.parse_item
        Rule(LinkExtractor(allow=r'https://www.qiushibaike.com/text/page/\d+/'), follow=True),  # callback='parse_item',
        # https://www.qiushibaike.com/article/124906526
        Rule(LinkExtractor(allow=r'https://www.qiushibaike.com/article/\d+'), callback='parse_item', follow=False),
    )

# 增加这一个方便知道爬了多少
parseIndex = 0

 def parse_item(self, response):
     u = response.url  # response 是响应对象 url是响应的url, 请求的url和响应的url是可能不同的
     parseIndex = self.parseIndex  # 这就是上面类的 parseIndex 
     
     ua = response.request.headers['User-Agent']  # 获取请求的ua 看看是否实现了动态ua
     _ = pq(response.text)  # 将响应回来的文本放入到 pq对象 获得一个pq实例对象
     t = _('title').text()  # 这是获取 title标签文本
     
     print('-' * 80)  # 打印分割线
     # zfill 是数字字符串进行补全0 在左边补全, 这样会好看点
     print(str(parseIndex).zfill(3), u, t, ua)  # 打印上面需要的参数进行查看
	
	 # 这个是获取 h1标签的 article-title 类 (class 属性) 的文本
     article_title = _('h1.article-title').text()  
     stats_time = _('span.stats-time').text()
     # span标签的 stats-vote 类 的 内 找 .number
     stats_vote = _('span.stats-vote .number').text()  
     content = _('.content').text()
     comment_block = [pq(_).text() for _ in _('.comment-block')]  # 这个是列表生成式

     self.parseIndex += 1
     
     print(article_title)
     print(stats_time, stats_vote)
     print(content)
     print('\n'.join(comment_block))  # 把列表转为字符串
     
     # 使用 yield 推送字典到 数据处理
     yield {
         'article_title': article_title,
         'stats_time': stats_time,
         'stats_vote': stats_vote,
         'content': content,
         'comment_block': comment_block
     }
     
     item = {}
     # item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
     # item['name'] = response.xpath('//div[@id="name"]').get()
     # item['description'] = response.xpath('//div[@id="description"]').get()
     # return item

新建一个 start.py 用于运行

from scrapy.cmdline import execute
execute('scrapy crawl text'.split(' '))  # execute 传入必须列表 所以使用 split 就行分割字符串

基本就这些了, 先测试下
刷刷刷…

在这里插入图片描述

在这里插入图片描述

数据可以了,接入redis测试

开启redis服务
开启\reeNMS web端服务

在这里插入图片描述
在这里插入图片描述
文件自己找或者私聊
开启后效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

settings.py 修改

ITEM_PIPELINES = {
   # 'qsbk.pipelines.QsbkPipeline': 300,
   # 开启这个
   'scrapy_redis.pipelines.RedisPipeline': 400,
}

# 开启这些
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True

修改爬虫文件 text.py

# 增加导入 更改类的继承
from scrapy_redis.spiders import RedisSpider

# class TextSpider(CrawlSpider):
class TextSpider(RedisSpider):

# 注释掉
# start_urls = ['https://www.qiushibaike.com/text/page/1/']

新建 handle_redis.py 用于处理 redis

# CY3761 | 2021-11-17 11:31
import json
import redis

try:
	# 加载redis 
    r = redis.Redis(host='127.0.0.1', port=6379)
    
    k1 = 'TextSpider:start_urls'
    
    # 如果不存在就进行追加第一页的地址
    if not r.llen(k1):
        r.lpush(k1, 'https://www.qiushibaike.com/text/page/1/')
    
    print(r.llen(k1), r.lrange(k1, 0, -1))
    
    k2 = 'text:items'
    d2 = r.lrange(k2, 0, -1)  # 列表
    
    print(r.llen(k2), type(d2))
    
    # 数据处理
    for k, _ in enumerate(d2):
        # print(type(_))  # <class 'bytes'>
        # break
        d2[k] = json.loads(_.decode('utf-8'))
     
     # 数据显示   
    for k, _ in enumerate(d2):
        k = str(k).zfill(3)
        
        print('-' * 80)
        print(k, _.get('article_title'))
        print(_.get('stats_time'), _.get('stats_vote'))
        print(_.get('content'))
        print()
        print('\n'.join(_.get('comment_block')))
    
    k3 = 'text:dupefilter'
    d3 = r.smembers(k3)  # 集合
    
    print()
    print(r.scard(k3), type(d3))
    
    for k, _ in enumerate(d3):
        k = str(k).zfill(3)
        print(k, _)
    
    
except (Exception, BaseException) as e:
    print(e)

再测试吧

发现创建在py有点问题
在这里插入图片描述
等候 start_url
使用客户端添加
在这里插入图片描述
试了好久,发现问题了…

继承这里改一下
爬虫文件的继承
class TextSpider(RedisSpider, CrawlSpider):

在这里插入图片描述
在这里插入图片描述
由于请求过多, ip估计被禁了… 起码能实现… 应该还是有点问题的
暂时先这样…

2021-11-17 补

经过找资料等继承不需要2个的

from scrapy_redis.spiders import RedisCrawlSpider


# class TextSpider(CrawlSpider):
class TextSpider(RedisCrawlSpider):

在这里插入图片描述
在这里插入图片描述
redis 是重新清过的,可能redis一直在等 没发现会结束

git例子 github例子

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CY3761

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

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

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

打赏作者

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

抵扣说明:

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

余额充值