发布于2021-07-25 07:24 阅读(998) 评论(0) 点赞(28) 收藏(1)
这里修改我们 Scrapy框架(三):CrawSpider模板的案例实现伪分布式(下面我仅写有修改部分的代码)
import json
import datetime
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from ..items import BookItem,ChapterItem,CatalogItem
from scrapy_redis.spiders import RedisCrawlSpider #1.导入RedisCrawlSpider
class ZhSpider(RedisCrawlSpider): #2.原来是继承CrawlSpider 现在改为RedisCrawlSpider
name = 'zh'
# allowed_domains = ['book.zongheng.com']
# start_urls = ['http://book.zongheng.com/store/c0/c0/b0/u0/p1/v9/s1/t1/u0/i1/ALL.html'] #一定要注释掉start_urls
redis_key = "zh:start_urls" #3.设置 redis_key
rules = (
Rule(LinkExtractor(allow=r'http://book.zongheng.com/book/\d+.html',restrict_xpaths='//div[@class="bookname"]'), callback='parse_book', follow=True,process_links='get_booklink'),
Rule(LinkExtractor(allow=r'http://book.zongheng.com/showchapter/\d+.html'), callback='parse_catalog', follow=True),
Rule(LinkExtractor(allow=r'http://book.zongheng.com/chapter/\d+/\d+.html',restrict_xpaths='//ul[@class="chapter-list clearfix"]'), callback='parse_chapter',follow=False,process_links='get_chapterlink'),
)
def get_booklink(self,links):
for index,link in enumerate(links):
print(index,link.url)
if index<=30:
yield link
else:
return
def get_chapterlink(self,links):
for index,link in enumerate(links):
if index<=1:
yield link
else:
return
·············
# 启用调度将请求存储进redis
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 确保所有spider通过redis共享相同的重复过滤。
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
#公共管道 与 本地管道
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline':300,
'zhnovel.pipelines.ZhnovelPipeline': 200,
}
# 指定连接到Redis时要使用的主机和端口。
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
# 不清理redis队列,允许暂停/恢复抓取。
# 可选 允许暂定,redis数据不丢失
SCHEDULER_PERSIST = True
#日志时间输出格式
LOG_DATEFORMAT='%Y'
结果执行步骤:
1、准备(除了写入的表名,这两文件代码完全一模一样):
数据库的novel(存储书名及相关信息)和chapter(存储各个章节)表都复制一份
2、在终端分布运行这两个文件(由于还没在redis设置钥匙,所以这两文件都处于等待状态)
3、再开启一个终端(redis写入钥匙)
最后让我们来看看结果是什么样的(这里我爬取了31本书):
① 首先我们先看下redis数据库里面的数据:
可以看到总共有31本书
② 然后我们先打开MySQL数据库:
两个张表里的数据加起来刚好31条,说明我们的伪分布式是成功的(这里章节结果爬取不演示了)。
因为开启了公共管道,所以两个项目的公共区域 redis 里会有两个项目的数据,是完整的数据,可以持久化到MySQL里进行持久化的存储
原因:redis存储是基于内存的,数据多可能会影响运行速度,所以要对redis中的数据进行持久化
下面的是 redis数据存储到MySQL 的一般书写形式(仅供参考):
import redis
import pymysql
import json
# 创建redis数据库连
rediscli = redis.StrictRedis(host= '127.0.0.1', port = 6379, db = 0)
# 创建mysql数据库连接
mysql_conn = pymysql.connect(host="127.0.0.1", port=3306, user="xxx", passwd="xxx", db="数据库名")
while True:
# 将数据从redis里取出来
source, data = rediscli.blpop("表名:items")
item = json.loads(data)
# 创建mysql 操作游标对象,可以执行mysql语句
cursor = mysql_conn.cursor()
cursor.execute("insert into 表名 (username, age) values (%s, %s)", [item['username'], item['age']])
# 提交事务
mysql_conn.commit()
# 关闭游标
cursor.close()
示例:
(redis里的数据是案例存进去的)
import redis
import pymysql
import json
# 创建redis数据库连
rediscli = redis.StrictRedis(host= '127.0.0.1', port = 6379, db = 0)
# 创建mysql数据库连接
mysql_conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="123456", db="zhnovel",charset="utf8")
while True:
# 将数据从redis里取出来
source, data = rediscli.blpop("zh:items")
item = json.loads(data)
print('source = ',source)
print('data = ',data)
# 创建mysql 操作游标对象,可以执行mysql语句
cur = mysql_conn.cursor()
# 注意!!! 要提前建表
if 'book_name' in data:
sql = "select id from novel_copy where book_name=%s and author=%s"
cur.execute(sql, (item['book_name'], item['author']))
if not cur.fetchone():
sql = "insert into novel_copy(category,book_name,author,status,book_nums,description,book_url,catalog_url) values(%s,%s,%s,%s,%s,%s,%s,%s)"
cur.execute(sql, (
item['category'], item['book_name'], item['author'], item['status'], item['book_nums'], item['description'],
item['book_url'], item['catalog_url']))
elif 'chapter_list' in data:
sql = 'insert into chapter_redisTomysql(title,ord_num,chapter_url,catalog_url) values(%s,%s,%s,%s)'
data_list = []
for index, chapter in enumerate(item['chapter_list']):
ord_num = index + 1
title, chapter_url, catalog_url = chapter
data_list.append((title, ord_num, chapter_url, catalog_url))
cur.executemany(sql, data_list)
elif 'content' in data:
sql = "update chapter_redisTomysql set content=%s where chapter_url=%s"
cur.execute(sql, (item['content'], item['chapter_url']))
mysql_conn.commit()
# 关闭游标
cur.close()
mysql_conn.close()
结果:
命令1:
pip install scrapyd
验证:
输入 scrapyd
,可以点击页面则成功
命令2:
pip install scrapyd-client
验证:
到 scrapy 项目下面,输入 scrapyd-deploy
,出现
Unknown target: defaultg
[settings]
default = zhnovel.settings
[deploy:novel] ;#novel:部署名称随便取 可以无 默认为空
;取消注释 url必须有,可以是远程服务器
url = http://localhost:6800/
;项目名称
project = zhnovel
;访问服务器需要的用户名和密码 (可以不写)
;username=xxx
;password=xxx
终端输入命令 scrapyd-deploy -l
查看设置的部署名称 和 url
位置: 在有scrapy.cfg 的目录下
输入 scrapyd-deploy spider(部署名称) -p zongheng(项目名称)
终端显示如下:
Deploying to project "zhnovel" in http://localhost:6800/addversion.json
Server response (200):
{"node_name": "DESKTOP-ISNG60N", "status": "ok", "project": "zhnovel", "version": "1626959536", "spiders": 1}
输入 http://127.0.0.1:6800
网页端显示如下:
命令:
curl http://localhost:6800/schedule.json -d project=项目名称 -d spider=爬虫文件名
显示如下:
建议使用cmd,打开命令行执行该语句,不然可能会出现报错
命令:curl http://localhost:6800/cancel.json -d project=项目名 -d job=填jobid值
原文链接:https://blog.csdn.net/qq_46485161/article/details/118903187
作者:woshidakeai
链接:http://www.pythonpdf.com/blog/article/416/b6a1e84c65db0694d3e0/
来源:编程知识网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!