爬虫神器--scrapy

 Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。

01

srcapy架构

Scrapy是一个适用爬取网站数据、提取结构性数据的应用程序框架,它可以应用在广泛领域:Scrapy 常应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。通常我们可以很简单的通过 Scrapy 框架实现一个爬虫,抓取指定网站的内容或图片。 尽管Scrapy原本是设计用来屏幕抓取(更精确的说,是网络抓取),但它也可以用来访问API来提取数据。

Scrapy Engine(引擎):负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。

Scheduler(调度器):它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。

Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理。

Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)。

Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。

Downloader Middlewares(下载中间件):一个可以自定义扩展下载功能的组件。

Spider Middlewares(Spider中间件):一个可以自定扩展和操作引擎和Spider中间通信的功能组件。

02


如何构造一个爬虫

老样子,我们还是用IDE Pycharm来实现一个爬虫,大概分为以下几个步骤:

1、python 安装scrapy,因为我使用的interpreter是anaconda3的库,所以我这边在Anaconda Prompt输入pip install scrapy

2、新建一个目录,比如在D盘新建目录mySpider,然后在pycharm的terminal命令行界面输入scrapy startscrapy wulianquanzhan 

3、然后进入到相应的目录可以看到已经创建了一个工程wulianquanzhan,通过Pycharm导入整个工程就可以开始用IDE来进行爬虫构建了

4、terminal命令行界面输入scrapy genspider  scrapyname example.com,

03


某小说网站小说爬取实例

这里我们演示爬取一个小说网站的小说内容。小说网站qxs.la,所以我们terminal命令行界面输入scrapy genspider  qxs  qxs.la,在工程目录spiders中会出现一个qxs.py的文件内容如下所示:

class QxsSpider(scrapy.Spider):
    name = 'qxs'
    allowed_domains = ['qxs.la']
    start_urls = ['http://qxs.la/']

    def parse(self, response):
        pass

接下来我们需要完善这里面的内容,需要根据网站的实际情况进行数据提取,主要是通过浏览器检查功能,查找小说内容所在,当然小说内容是比较分散的,需要分类去爬取,所有的小说具体内容都需要翻页跳转来进行爬取

class QxsSpider(scrapy.Spider):
    name = 'qxs'
    allowed_domains = ['qxs.la']
    start_urls = ['http://qxs.la/']

    def parse(self, response):
        item = {}
        url_list_r = response.xpath("//div[@class='item_div_r']")
        url_list_ul = response.xpath("//div[@class='item_content']//ul")
        for url in url_list_r:
            item['novel_name'] = url.xpath('.//h4//a//text()').extract_first()
            item['novel_url'] = url.xpath('.//h4//a//@href').extract_first()
            next_url = "https://qxs.la"+item['novel_url']
            yield scrapy.Request(next_url, callback=self.parse_content_url, meta={"item": deepcopy(item)})

        for url in url_list_ul:
            item['novel_name'] = url.xpath('.//li//a//text()').extract_first()
            item['novel_url']  = url.xpath('.//li//a//@href').extract_first()
            next_url = "https://qxs.la" + item['novel_url']
            yield scrapy.Request(next_url, callback=self.parse_content_url, meta={"item": deepcopy(item)})


    def parse_content_url(self,response):
        url_list = response.xpath("//div[@class='chapter']")
        item = response.meta['item']
        for url in url_list:
            response.meta['item']['novel_chapter_url'] = url.xpath('.//a//@href').extract_first()
            response.meta['item']['novel_chapter_name'] = url.xpath('.//a//text()').extract_first()
            if response.meta['item']['novel_chapter_url']:
                next_url = "https://qxs.la" + response.meta['item']['novel_chapter_url']
                response.meta['item']['complete_url'] = next_url
                yield scrapy.Request(next_url, callback=self.parse_content, meta={"item": deepcopy(item)})
                # yield response.meta['item']

    def parse_content(self,response):
        content = response.xpath("//div[@id='content']//text()")[7:-7].extract()
        for con in content:
            response.meta['item']['content'] = con.replace(u'\u3000',u'').strip()
            yield response.meta['item']

有兴趣的同学可以打开网页去实际去研究下,基本都是用xpath来提取内容,分两步走:

1、提取小说目录的url_list

2、根据每部小说的url进行跳转,在对应的网页检查中找出每一部小说的章节内容进行提取url

3、根据每一部小说的每一个章节的内容进行xpath内容提取

4、章节内容保存,scrapy有个item pipline的功能,只需要在将章节内容传递到这个pipline中,然后在pipline进行内容的保存

class MyspiderPipeline:
    def process_item(self, item, spider):
        if spider.name == 'qxs':
            logger.warning(item)
            novel_folder_path = os.path.join(novel_folder_base,item['novel_name'])
            if not os.path.exists(novel_folder_path):
                os.makedirs(novel_folder_path)
            file_path = os.path.join(novel_folder_path,item['novel_chapter_name'])
            if 'content' in item.keys():
                with open(file_path+".txt","a") as f:
                    f.write(str(item['content'])+'\n')
        return item

有两个配置的问题需要注意:

1、在settings文件中配置好piplines,不然item_pipeline功能无法使用

ITEM_PIPELINES = {
   'mySpider.pipelines.MyspiderPipeline': 300,
}

2、修改User-Agent为一个正常的值

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.87 Safari/537.36 Edg/88.0.705.45'

04


Scrapy Redis的使用

大家在初入Scrapy进行内容爬取的时候,如果爬取的内容很多,可能短时间爬不完,有可能电脑就中断了,或者想把爬虫分布在不同的IP上来躲避反爬虫。这个时候用redis来进行断点续爬就是一个很好的方法了,在scrapy框架中使用redis也是非常的方便,在需在settings文件中配置如下即可:

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True
REDIS_URL = "redis://127.0.0.1:6379"

当然piplines也是需要配置的

ITEM_PIPELINES = {
   'mySpider.pipelines.MyspiderPipeline': 300,
   'scrapy_redis.pipelines.RedisPipeline': 400,
}

配置好后,就可以在terminal输入scrapy crawl qxs是内容爬取了,ctl+c打断,重新爬取的时候也是从断开的url开始爬取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值