爬虫--CrawlSpider及深度全站爬取

CrawlSpider:

--是Spider的一个子类.Spider是爬虫文件中爬虫类的父类

--作用:被用于专业实现全站数据爬取,将一个页面上所有页码对应的数据进行爬取

--基本使用:

  --创建一个基于CrawlSpider的爬虫文件

    --scrapy genspider -t crawl SpiderName www.xxx.com

--注意:

  1.一个链接提取器对应一个规则解析器

  2.在实现深度爬取的过程中需要和scrapy.Request()结合使用

 

基本代码:

复制代码
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class BlueSpider(CrawlSpider):
    name = 'blue'
    # allowed_domains = ['www.xxx.com'] # 域名限定,只允许该域名下的链接
    start_urls = ['https://www.xxx.com/category/xxx/page/1']

    # 实例化LinkExtractor对象
    # 链接提取器:指定规则(allow参数)在页面中提取url
    # allow='正则':提取链接的规则
    link = LinkExtractor(allow=r'category/xxx/page/\d+')
    rules = (
        # 实例化一个Rule对象
        # 规则解析器:接收链接提取器提取到的链接,发起请求,然后根据指定规则(callback)解析数据
        # 一个链接提取器对应一个规则解析器
        # follow=True:可以将链接提取器继续作用到链接提取器提取到的链接所对应的页面中
        Rule(link, callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        # 基于response实现数据解析
        print(response)
复制代码

 

多规则(Rule)全站深度数据爬取示例:

# 爬虫文件blue.py

复制代码
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from bluespider.items import BluespiderItem,DetailItem


class BlueSpider(CrawlSpider):
    name = 'blue'
    # allowed_domains = ['www.xxx.com'] # 域名限定,只允许该域名下的链接
    start_urls = ['https://www.fuzokuu.com/category/xxx/page/1']

    # 实例化LinkExtractor对象
    # 链接提取器:指定规则(allow参数)在页面中提取url
    # allow='正则':提取链接的规则
    # link = LinkExtractor(allow=r'category/xxx/page/d+|category/xxx')
    link = LinkExtractor(allow=r'category/xxx/page/2')
    link_detail = LinkExtractor(allow=r'https://www.xxx.com/\d+')
    rules = (
        # 实例化一个Rule对象
        # 规则解析器:接收链接提取器提取到的链接,发起请求,然后根据指定规则(callback)解析数据
        # 一个链接提取器对应一个规则解析器
        Rule(link, callback='parse_item', follow=True),
        Rule(link_detail, callback='parse_detail', follow=False)
    )

    # 只有手动传参scrapy.Request能够自动传参item
    # 此处两个函数无法传参item,因此就建立两个item
    def parse_item(self, response):
        # 基于response实现数据解析
        # 注意:xpath表达式中不可以出现tbody iframe等标签
        article_list = response.xpath('//article')
        for article in article_list:
            article_title = article.xpath('./div[2]/header/h2/a/@title').extract_first()
            article_url = article.xpath('./div[2]/header/h2/a/@href').extract_first()
            article_author = article.xpath('./div[2]/div[2]/span[1]/span/a/@title').extract_first()
            # 因为有两个item分别存储数据,因此用article_id作为两个item数据之间联系的唯一标识
            article_id = article_url.split('/')[-1]
            item = BluespiderItem()
            item['article_title'] = article_title
            item['article_url'] = article_url
            item['article_author'] = article_author
            item['article_id'] = article_id
            yield item
            # print(article_title, article_url, article_author)


    # 内容详情页解析
    def parse_detail(self, response):
        content = response.xpath('//article//p/text()').extract()
        article_id = response.xpath('//article/@id').extract_first()
        content = ''.join(content)
        article_id = article_id.split('-')[-1]
        item = DetailItem()
        item['content'] = content
        item['article_id'] = article_id
        yield item
        # print(content)
复制代码

 

# items.py

复制代码
import scrapy


class BluespiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    article_title = scrapy.Field()
    article_url = scrapy.Field()
    article_author = scrapy.Field()
    # article_id作为两个item的共同标识,方便数据库存储
    article_id = scrapy.Field()

class DetailItem(scrapy.Item):
    article_id = scrapy.Field()
    content = scrapy.Field()
复制代码

 

# pipelines.py

复制代码
from itemadapter import ItemAdapter


class BluespiderPipeline:
    def process_item(self, item, spider):
        # 如何判断item的类型
        if item.__class__.__name__ == 'DetailItem':
            print(item['article_id'],item['content'])
        else:
            print(item['article_id'],item['article_title'])
        return item
复制代码

 

posted @   EricYJChung  阅读(206)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示