CrawlSpider
提问:如果想要通过爬虫程序去爬取”糗百“全站数据新闻数据的话,有几种实现方法?
方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Request模块递归回调parse方法)。
方法二:基于CrawlSpider的自动爬取进行实现(更加简洁和高效)。
全栈120页数据
---------------------------------------------------------------------------
CrawlSpider:
问题:如果我们想要对某一个网站的全站数据进行爬取?
解决方案:
1. 手动请求的发送
2. CrawlSpider(推荐)
之前的事基于Spider类
CrawlSpider概念:CrawlSpider其实就是Spider的一个子类。CrawlSpider功能更加强大(链接提取器,规则解析器)。 代码: 1. 创建一个基于CrawlSpider的爬虫文件 a) scrapy genspider –t crawl 爬虫名称 起始url
-------
创建工程scrapy startproject crawlSpiderPro
cd crawlSpiderPro
创建爬虫文件 scrapy genspider -t crawl chouti dig.chouti.com
基于scrapySpider爬虫文件的和基于spider的不同之处
爬虫文件chouti.py
区别:
class ChoutiSpider(CrawlSpider): name = 'chouti' #allowed_domains = ['dig.chouti.com'] start_urls = ['https://dig.chouti.com/'] #实例化了一个链接提取器对象 #链接提取器:用来提取指定的链接(url) #allow参数:赋值一个正则表达式 #链接提取器就可以根据正则表达式在页面中提取指定的链接 #提取到的链接会全部交给规则解析器 link = LinkExtractor(allow=r'/all/hot/recent/\d+') rules = ( #实例化了一个规则解析器对象 #规则解析器接受了链接提取器发送的链接后,就会对这些链接发起请求,获取链接对应的页面内容,就会根据指定的规则对页面内容中指定的数据值进行解析 #callback:指定一个解析规则(方法/函数) #follow:是否将链接提取器继续作用到连接提取器提取出的链接所表示的页面数据中 Rule(link, callback='parse_item', follow=), ) def parse_item(self, response): print(response)
# 对应的编写response.xpath()---存到items ----将items传给管道---在管道进行持久化存储
# follow=True 所有的页面数据
link = LinkExtractor(allow=r'/all/hot/recent/\d+')
---------------------------------------------
Rule(link, callback='parse_item', follow=True),
分布式爬虫
分布式爬虫:
1. 概念:多台机器上可以执行同一个爬虫程序,实现网站数据的分布爬取。
2. 原生的scrapy是不可以实现分布式爬虫?
a) 调度器无法共享
b) 管道无法共享
3. scrapy-redis组件:专门为scrapy开发的一套组件。该组件可以让scrapy实现分布式。
a) 下载:pip install scrapy-redis
4. 分布式爬取的流程:
a) redis配置文件的配置:
i. bind 127.0.0.1 进行注释
ii. protected-mode no 关闭保护模式
b) redis服务器的开启:基于配置配置文件
c) 创建scrapy工程后,创建基于crawlSpider的爬虫文件
d) 导入RedisCrawlSpider类,然后将爬虫文件修改成基于该类的源文件
e) 将start_url修改成redis_key = ‘XXX’
f) 在配置文件中进行相应配置:将管道配置成scrapy-redis集成的管道
g) 在配置文件中将调度器切换成scrapy-redis集成好的调度器
h) 执行爬虫程序:scrapy runspider xxx.py
i) redis客户端:lpush 调度器队列的名称 “起始url”
-------------------------
分布式爬虫:
1. 概念:多台机器上可以执行同一个爬虫程序,实现网站数据的分布爬取。
2. 原生的scrapy是不可以实现分布式爬虫?
a) 调度器无法共享
b) 管道无法共享
3. scrapy-redis组件:专门为scrapy开发的一套组件。该组件可以让scrapy实现分布式。
a) 下载:pip install scrapy-redis
4. 分布式爬取的流程:
下载redis----我用的是windows版本的
在redis数据库所在文件进行配置
a) redis配置文件的配置:
i. bind 127.0.0.1 进行注释
ii. protected-mode no 关闭保护模式
b) redis服务器的开启:基于配置配置文件----
c) 创建scrapy工程后,创建基于crawlSpider的爬虫文件
d) 导入RedisCrawlSpider类,然后将爬虫文件修改成基于该类的源文件
from scrapy_redis.spiders import RedisCrawlSpider class QiubaiSpider(RedisCrawlSpider):
e) 将start_url修改成redis_key = ‘XXX’
f) 在配置文件中进行相应配置:将管道配置成scrapy-redis集成的管道
默认的为:
g) 在配置文件中将调度器切换成scrapy-redis集成好的调度器
在settings.py粘贴如下配置
调度器:
、
h) 执行爬虫程序:scrapy runspider xxx.py
不同之处是要cd 到爬虫文件
i)
起始url:
https://www.qiushibaike.com/pic/
【补充】 #如果redis服务器不在自己本机,则需要在setting中进行如下配置 REDIS_HOST = 'redis服务的ip地址' REDIS_PORT = 6379
【注意】近期糗事百科更新了糗图板块的反爬机制,更新后该板块的页码链接/pic/page/2/s=5135066,末尾的数字每次页面刷新都会变化,
因此爬虫文件中链接提取器的正则不可写为/pic/page/\d+/s=5135066而应该修改成/pic/page/\d+
分布式爬虫代码:
qiubai.py
import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from redisPro.items import RedisproItem from scrapy_redis.spiders import RedisCrawlSpider class QiubaiSpider(RedisCrawlSpider):#继承的类不同,功能也就不一样 name = 'qiubai' #allowed_domains = ['www.qiushibaike.com/pic'] #start_urls = ['http://www.qiushibaike.com/pic/'] # 调度器队列的名称 redis_key = 'qiubaispider' # 表示跟start_urls含义是一样 rules = ( Rule(LinkExtractor(allow=r'/pic/page/\d+'), callback='parse_item', follow=True), ) # img src //pic.qiushibaike.com/system/pictures/12133/121333058/medium/8ULD8612VVF6T0NR.jpg def parse_item(self, response): div_list = response.xpath('//*[@id="content-left"]/div') for div in div_list: # 相对于div_list .// img_url img_url = div.xpath('./div[@class="thumb"]/a/img/@src').extract_first() # 在items.py中声明 ---导入items # 实例化items对象 item = RedisproItem() item['img_url'] = img_url yield item
-------------------
1、打开redis服务器:
2、再执行:
h) 执行爬虫程序:scrapy runspider xxx.py
不同之处是要cd 到爬虫文件
3、打开客户端:
redis客户端:lpush 调度器队列的名称 “起始url”
---------------------------
keys *
测试成功
悟已往之不谏,知来者之可追。