Scrapy实战-爬取豆瓣漫画

背景知识

(一)什么是Scrapy呢?Python上优秀的爬虫框架。什么是爬虫?可以看自己的经验感悟,也足以自行Google百度。

(二)提议看下初识Scrapy后边准备安装Scrapy。

(三)Selectors遵照XPath和CSS表明式从网页中甄选数据。XPath和CSS表达式是何许东西,我们不要太过于纠结,只需要知道能够采纳它们在网页中挑选数据。用法:利用chrome去复制所需数据的地点信息。当然进阶的话可以看这里

右击

拷贝

骨干用法与认证:

  • response.selector.xpath(‘//title/text()’)##用xpath采取了title的文字内容
  • response.selector.css(‘title::text’)
    ##用css拔取了title的文字内容
    出于selector.xpath和selector.css使用相比普遍,所以专门定义了xpath和css,所以地方也得以写成:
  • response.xpath(‘//title/text()’)
  • response.css(‘title::text’)
    是因为<code>.xpath</code>和<code>.css</code>重临的都是<class
    ‘scrapy.selector.unified.SelectorList’>,因而可以这么写<code>response.css(‘img’).xpath(‘@src’).extract()</code>
  • 领到全部内容: .extract(),拿到是一个列表
  • 领取第一个:.extract_first(),得到是一个字符串
  • 采纳链接:
    .response.css('base::attr(href)').response.xpath('//base/@href')

规范开班

1. 新建工程 scrapy startproject tutorial

2. 创办爬虫 scrapy genspider -t basic douban douban.com

上边两步会创设如下的目录结构:

Scrapy目录树

简短说下每一个文件的效能,固然在初识Scrapy已经说过了。

  1. spiders文件夹存放你的爬虫,
  2. items.py用于定义存放网页数据的item。
  3. middlewares.py是后加的,近年来不需要
  4. pipelines.py 用于拍卖从spiders再次回到的item,比如说清洗、存储。
  5. settings.py是大局设定,比如说接下去提到的DEFAULT_REQUEST_HEADERA和USER_AGENT都在这里。

3. 修改settings.py

因为Scrapy非凡诚实,爬取网页的时候会标明自己是一只爬虫,然则豆瓣不给这么些注脚身份的爬虫活路。所以大家只可以换个地方。

先是步:chrome用急迅键F12开拓开发者工具,接纳Network一栏,可能需要F5刷新页面:

开发者工具之Network

其次步:在上图红框部分随机选拔一个,会并发下图:

浏览器消息

俺们首要需要的是里面红框的Request Headers的音信。

第三步:在settings.py中修改DEFAULT_REQUEST_HEADERA和USER_AGENT。

settings.py

里面的USER_AGENT填写浏览器图中的User-Agent对应新闻,DEFAULT_REQUEST_HEADERA里的新闻遵照字典的写法,从浏览器消息图中各类对应相应填上去。
PS:
顺便启用DOWNLOAD_DELAY=3减慢爬取速度,不要给人家的服务器扩大太多压力。
除此以外启用ITEM_PIPELINES = { 'tutorial.pipelines.DoubanPipeline': 300,}用于拍卖数量

4. 用爬虫的眼光看网页,

在命令行中输入scrapy shell https://movie.douban.com/chart
这时候会跻身scrapy版的ipython,输入view(response)就能够查阅网页。

5. 概念要爬取的始末

在items.py中作如下修改

import scrapy
class DoubanItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    link = scrapy.Field()
    info = scrapy.Field()
    desc = scrapy.Field()

6. 单页逻辑

爬取多少个网页前,大家第一得要学有所成提取一个网页的信息。在spiders/douban.py做如下修改
# –– coding: utf-8 –
import scrapy
from scrapy.http import Request
from ..items import DoubanItem

class DoubanSpider(scrapy.Spider):
    name = "douban"
    allowed_domains = ["douban.com"]
    start_urls = (
        'https://book.douban.com/tag/%E6%BC%AB%E7%94%BB?start=0&type=T',
    )

    def parse(self, response):
        item = DoubanItem()
        for sel in response.css('#subject_list > ul > li > div.info'):
            item['title']= sel.css('h2 > a::text').extract_first()
            item['link'] = sel.css('h2 > a::attr(href)').extract_first()
            item['info'] = sel.css('div.pub::text').extract_first()
            item['desc'] = sel.css('p::text').extract_first()
            yield item

大体的爬虫就完事了。用scrapy crawl douban发端工作。由于scrap构建在python2.7上,所以对闽南语帮助不太好,在指令行中会以unicode编码的办法映现,所以在shell上观看一堆不认得的\xxx也无须太操心。

7.数码存储

为了有利于之后调用数据,我们需要用pipelines.py将爬取的多少存储在一定的文书中。可以用json等格式储存,也足以存放在数据库中。网页爬取数据往往不太正统,提议使用mongodb(NoSQL)。

import json
import codecs
Import pymongo #python中用来操作mongodb的库
##存储为json格式
class DoubanPipeline(object):
    def __init__(self):
        self.file = codecs.open('douban_movie.json','wb',encoding='utf-8')

    def process_item(self, item, spider):
        line = json.dumps(dict(item)) + '\n'
        self.file.write(line.decode("unicode_escape"))
        return item

class MongoPipeline(object):

    collection_name = 'douban_cartoon' # mongo的collection相当于sql的table

    def __init__(self, mongo_uri,mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    ## 配置mongo
    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'), #从settings中mongo的uri
            mongo_db=crawler.settings.get('MONGO_DATABASE','douban') #从settings中获取数据库,默认为douban
        )

    # 在spider工作开始前连接mongodb
    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]
    ## 在spider工作结束后关闭连接
    def close_spider(self, spider):
        self.client.close()
    ## 在mongodb中插入数据
    def process_item(self, item, spider):
        # for i in item:

        self.db[self.collection_name].insert(dict(item))
        return item

运转后就足以在档次所在目录找到douban_movie.json,mongodb的话需要团结去查询了。

多页逻辑(一)

俺们需要在这一页获取下一个的链接,然后再一次调用parse函数爬取这多少个链接。

     def parse(self, response):
        .....
        ## 获取下一个的链接
        href = response.xpath('//*[@id="subject_list"]/div[2]/span[4]/a')
        url = u'https://book.douban.com'+ href.css('a::attr(href)').extract_first()
        yield Request(url, callback=self.parse)

多页逻辑(二)

咱俩还足以通过Scrapy提供的CrawlSpider做到多页爬取。CrawlSpider比Spider多了一步即设置Rule,具体可以看我的[Scrapy基础之详解Spider]的CrawlSpider。

第一步shell试错

为了保险LinkExtractor能领到到科学的链接,我们需要在shell中开展试验。

scrapy shell https://book.douban.com/tag/漫画
 from scrapy.linkextractors import LinkExtractor ##导入LinkExtractor
 item=LinkExtractor(allow='/tag/漫画',restrict_xpaths=('//*[@id="subject_list"]/div[2]/span/a')).extract_links(response) ##需要反复修改

第二步修改爬虫

修改后的爬虫如下:
# –– coding: utf-8 –
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from tutorial.items import DoubanItem

class ManhuaSpider(CrawlSpider):
    name = 'manhua'
    allowed_domains = ['book.douban.com']
    start_urls = ['https://book.douban.com/tag/漫画']

    rules = (
        Rule(LinkExtractor(allow=r'/tag/漫画',
                           restrict_xpaths=('//*[@id="subject_list"]/div[2]/span/a')),
             callback='parse_item',
             follow=True),
    )

    def parse_item(self, response):
        item = DoubanItem()
        for sel in response.css('#subject_list > ul > li > div.info'):
            item['title']= sel.css('h2 > a::text').extract_first()
            item['link'] = sel.css('h2 > a::attr(href)').extract_first()
            item['info'] = sel.css('div.pub::text').extract_first()
            item['desc'] = sel.css('p::text').extract_first()
            yield item

运转结果和多页逻辑(一)的如出一辙。


进而,你能够看再识Scrapy-下载豆瓣图书封面,在这多少个的根基上加码图片下载功用。
假若怕被ban,可以看再识Scrapy-防ban策略


本文参考了Andrew_liuPython爬虫(六)–Scrapy框架学习
scrapy商讨探索(二)——爬w3school.com.cn,以及最着重的合法文档。


写在最后:
网络上有那么多的Scrapy的学科,为何我还要写一个呢?因为我以为真的学会用自己语言去抒发一门技术的时候,才算入门了。
再有写出来的事物才能让别人发现自己的欠缺,希望各位大大批评指正。
自身的源代码托管在GitHub上,有需要的话可以去看

网站地图xml地图