全栈爬虫
CrawlSpider全栈爬取的一个类
创建项目后创建爬虫文件:scrapy genspider-t crawl spiderName www.xxx.com
当前文件:D:\python_test\scrapyProject\crawl_spider\crawl_spider\spiders\spider_all.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from ..items import CrawlSpiderItem
class SpiderAllSpider(CrawlSpider):
name = 'spider_all'
start_urls = ['https://sc.chinaz.com/jianli/free.html']
# allow带正则表达,表示提取当前响应数据满足该正则的url
link = LinkExtractor(allow=r'/jianli/free_\d+\.html')
# link_detail = LinkExtractor(allow=r'/jianli/free_\d+\.html')
rules = (
# Rule对匹配到的link数据发起请求,然后使用callback调用函数进行解析
# follow=True表示把每一个请求当做首页来处理,一般在页码可以使用到,不需要则不填该参数
# 可填写多个规则进行匹配,但两个Rule是无法直接使用item进行关联的,因此如果想有item关联,还是使用原来的方法
Rule(link, callback='parse_item', follow=False),
# Rule(link_detail, callback='detail_item'),
)
def parse_item(self, response):
div_list = response.xpath('//*[@id="container"]/div')
for div in div_list:
title = div.xpath('./p/a/text()').extract_first()
detail_url = "https:"+div.xpath('./p/a/@href').extract_first()
item=CrawlSpiderItem()
item['title']=title
yield scrapy.Request(url=detail_url,
callback=self.detail_parse,
meta={'item':item})
return item
def detail_parse(self,response):
item = response.meta['item']
downloadurl=response.xpath('//*[@id="down"]/div[2]/ul/li[2]/a/@href').extract_first()
item['url']=downloadurl
return item
分布式爬虫
创建基于crawlSpider的爬虫文件
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy_redis.spiders import RedisCrawlSpider
from ..items import FbsproItem
class FbsSpider(RedisCrawlSpider): # 导入父类
name = 'fenbushi'
redis_key = 'queue' # redis_key表示调度器队列的名称,用来替换start_url,以下就是常规解析操作
rules = (
#提取所有的页码链接,且对其进行请求发送
Rule(LinkExtractor(allow=r'id=1&page=\d+'), callback='parse_item', follow=True),
)
def parse_item(self, response):
li_list = response.xpath('/html/body/div[2]/div[3]/ul[2]/li')
for li in li_list:
title = li.xpath('./span[3]/a/text()').extract_first()
statu = li.xpath('./span[2]/text()').extract_first()
item = FbsproItem()
item['title'] = title
item['status'] = status
yield item
# 修改setting文件
# 所有电脑都执行同一套代码后,在暂停的时候在redis工具输入命令 lpush queue https://mp.youkuaiyun.com/mp_blog/(即起始url)
修改setting文件
1、常规内容修改(robots和ua等)
2、指定可以被共享的管道类
ITEM_PIPELINES = {'scrapy_redis.pipelines.RedisPipeline': 400}
3、指定可以被共享的调度器
# 使用scrapy-redis组件的去重队列
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis组件自己的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 是否允许暂停,当程序中止后重新运行,可以在停止位置继续执行
SCHEDULER_PERSIST = True
4、指定数据库
REDIS_HOST = '指定redis的ip'
REDIS_PORT = 6379
连续本地的话,修改redis数据库的配置文件(redis.windows.conf)
bind 127.0.0.1
#将上述代码注释即可(解除本机绑定,实现外部设备访问本机数据库)
如果配置文件中还存在:protected-mode = true,将true修改为false,
修改为false后表示redis数据库关闭了保护模式,表示其他设备可以远程访问且修改你数据库中的数据
最后,所有电脑都执行同一套代码后,在暂停的时候在redis工具输入命令 lpush queue https://mp.youkuaiyun.com/mp_blog/(即起始url)
增量式爬虫
用来监测网站数据更新的情况,爬取网站最新更新出来的数据。
数据指纹:数据的唯一标识。
import scrapy
import redis
from ..items import Zlsdemo1ProItem
class DuanziSpider(scrapy.Spider):
name = 'duanzi'
start_urls = ['https://ishuo.cn/']
#Redis的链接对象
conn = redis.Redis(host='127.0.0.1',port=6379)
def parse(self, response):
li_list = response.xpath('//*[@id="list"]/ul/li')
for li in li_list:
content = li.xpath('./div[1]/text()').extract_first()
title = li.xpath('./div[2]/a/text()').extract_first()
all_data = title+content
#生成该数据的数据指纹
import hashlib # 导入一个生成数据指纹的模块
m = hashlib.md5()
m.update(all_data.encode('utf-8'))
data_id = m.hexdigest()
ex = self.conn.sadd('data_id',data_id)
if ex == 1:#sadd执行成功(数据指纹在set集合中不存在)
print('有最新数据的更新')
item = Zlsdemo1ProItem()
item['title'] = title
item['content'] = content
yield item
else:#sadd没有执行成功(数据指纹在set集合中存储)
print('暂无最新数据更新')
使用详情页的url充当数据指纹
import scrapy
import redis
from ..items import Zlsdemo2ProItem
class JianliSpider(scrapy.Spider):
name = 'jianli'
start_urls = ['https://sc.chinaz.com/jianli/free.html']
conn = redis.Redis(host='127.0.0.1',port=6379)
def parse(self, response):
div_list = response.xpath('//*[@id="container"]/div')
for div in div_list:
title = div.xpath('./p/a/text()').extract_first()
#充当数据指纹
detail_url = 'https:'+div.xpath('./p/a/@href').extract_first()
ex = self.conn.sadd('data_id',detail_url)
item = Zlsdemo2ProItem()
item['title'] = title
if ex == 1:
print('有最新数据的更新')
yield scrapy.Request(url=detail_url,callback=self.parse_detail,meta={'item':item})
else:
print('暂无数据更新')
def parse_detail(self,response):
item = response.meta['item']
download_url = response.xpath('//*[@id="down"]/div[2]/ul/li[1]/a/@href').extract_first()
item['download_url'] = download_url
yield item