使用scrapy来爬图文

这样的关键字能搜到很多很多文章,可是,在我的实践过程中,没有一篇文章能够待我穿过山和大海,也走过人山人海,相反,都是带着我掉进了坑,陷进了沼泽,挂在了树上…

环境

python 叫做 Python3,版本 v3.6.1
os 是 Mac os
scrapy 版本 v1.3.3

我有一个小目标,先扒下来几百张图再说

感谢douban,让我一次一次又一次地爬…
目标网页: https://www.douban.com/doulist/1295618/
它看起来是这样的

《使用scrapy来爬图文》 中国内地电影票房总排行

而我们的目标,是将这些
下载下来电影海报,顺便记录一下排行榜到csv文件

使用Scrapy创建一个项目

如果没有安装Scrapy,可以参考我的另一篇文章安装scrapy。我们这里使用命令生成一个脚手架

scrapy startproject douban

生成后的项目结构如下(根目录):

├── scrapy.cfg
└── scrapyspider                         # 项目目录
    ├── items.py                         # 模型文件,定义要抓取的对象,后期修改
    ├── middlewares.py
    ├── pipelines.py                     # 以管道方式处理模型,后期修改
    ├── settings.py                      # 项目配置文件,后期修改
    └── spiders                          # 爬虫文件夹
        └── douban_spider.py             # 后期新增的爬虫文件

需要注意:

  • 由于使用我们的管道继承了scrapy的图片管道,所以项目依赖Pillow的库,使用
python3 -m pip install pillow

来安装PIL的依赖

  • 运行爬虫时,需要切换到项目根目录下,然后
scrapy crawl xxx

其中xxx是爬虫的名字(注:不是文件名哦,是爬虫的name属性)

文件如下

setting.py

import os

BOT_NAME = 'douban'

SPIDER_MODULES = ['douban.spiders']
NEWSPIDER_MODULE = 'douban.spiders'

DOWNLOADER_DEBUG = True              #这5行不是必须的,只是为了调试方便
CONCURRENT_REQUESTS = 200         
AUTOTHROTTLE_DEBUG = True
AUTOTHROTTLE_ENABLED= True
DEPTH_STATS_VERBOSE = True           # 5行到这里

CUR_DIR = os.path.dirname(os.path.realpath(__file__))
IMAGES_STORE = os.path.join(CUR_DIR, '..', 'images')


ITEM_PIPELINES = {
    'douban.pipelines.DoubanPicPipelines': 1
}

COOKIE_ENABLE = False    # 建议有,不要记着我的脸,不要cookie
DOWNLOAD_DELAY = 0.5    # 建议有,步子不要太大,否则容易扯着蛋

ROBOTSTXT_OBEY = False     # 必须有,否则你的爬虫会按照robot.txt规则来决定能否爬当前内容

ITEM_PIPELINES 属性描述了管道流,key是管道类的类名,value是一个数字,用来描述任务优先级,1就是最早执行,数字越大,执行顺序就越晚

pipelines.py

from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request

class DoubanPicPipelines(ImagesPipeline):

    def get_media_requests(self,item,info):
        for image_url in item['image_urls']:
            yield Request(image_url)
    def item_completed(self,results,item,info):
        image_paths=[x['path'] for ok,x in results if ok]    # 这里的path是item自动加上的
        if not image_paths:
            raise DropItem('图片未下载好 %s'%image_paths)

items.py

import scrapy

class DoubanItem(scrapy.Item):
    ranking = scrapy.Field()
    # movie's name
    movie_name = scrapy.Field()
    # score
    score = scrapy.Field()
    # comment count
    score_num = scrapy.Field()
    # image_urls
    image_urls = scrapy.Field()
    # image name
    images = scrapy.Field()

spiders/douban_spider.py

from scrapy.spiders import Spider
from scrapy.http import Request
from douban.items import DoubanItem
import re


class DoubanMovieSpider(Spider):
    name = 'movie'    # 这个名字决定了使用scrapy crawl movie来启动爬虫
    headers = {       # 没有UA,网站不待见你
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:54.0) Gecko/20100101 Firefox/54.0'
    }

    def start_requests(self):
        url = 'https://www.douban.com/doulist/1295618/'
        yield Request(url, headers=self.headers)

    def parse(self, response):
        item = DoubanItem()
        movies = response.xpath('//div[@class="doulist-item"]/div')
        for movie in movies:
            item['ranking'] = movie.xpath(
                './/span[@class="pos"]/text()').extract()[0]
            item['movie_name'] = movie.xpath(
                './/div[@class="title"]/a/text()').extract()[0]

            score = movie.xpath('.//span[@class="rating_nums"]/text()').extract()
            if score:
                score = score[0]
            else:
                score = 'N/A'
            item['score'] = score

            score_num = movie.xpath('.//div[@class="rating"]/span[3]').re(r'(\d+)')
            if score_num:
                score_num = score_num[0]
            else:
                score_num = 'N/A'
            item['score_num'] = score_num

            image_urls = movie.xpath('.//div[@class="post"]/a/img/@src').extract()
            item['image_urls'] = image_urls

            item['images'] = movie.xpath(
                './/div[@class="post"]/a/img/@src').re(r'[^/]*.[jpg|png|gif|webp]$')

            yield item

        # 处理分页
        next_url = response.xpath('//span[@class="next"]/a/@href').extract()
        if next_url:
            yield Request(next_url[0], headers = self.headers)

运行爬虫,

scrapy crawl movie -o movies.cvs

稍等片刻,就能够看到生成出来的cvs文件了,使用wps打开,能够看到漂亮的中文(office貌似是乱码)

《使用scrapy来爬图文》 cvs文件,可以很方便排序
《使用scrapy来爬图文》 下载下来的海报

    原文作者:天秤座的牛宝宝
    原文地址: https://www.jianshu.com/p/7dab5a38b8e5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞