Scrapy爬取豆瓣电影top250数据并保存mysql/json/csv

文章目录

*
1. 项目简介
2. 代码解析
3. 总结

帮一个大一的小朋友做作业,看了一下Scrapy,这里也记录一下吧,有需要的可以参考一下。

1. 项目简介

Scrapy爬取豆瓣电影top250的代码网上有很多,之前没用过这个框架,也懒得细看了,这里借鉴了Scrapy实战 这篇文章的爬取方式。爬取的部分就不细说了,大家可以直接看代码,博客上也有很多讲解的,这里主要分享一下爬取到的数据如何存储。
先展示一下我的目录结构,files和picture文件夹备用来放置爬取的数据保存文件和图片,其他文件是新建Scrapy项目后自动生成的。

Scrapy爬取豆瓣电影top250数据并保存mysql/json/csv

; 2. 代码解析

main.py文件是自建的,用来作为项目执行文件,可以在pycharm中直接运行,代码如下:

#!/usr/bin/env python
-*- encoding: utf-8 -*-
"""
@File    :   main
@Author :   GrowingSnake
@Version :   1.0
@Desciption :
@Modify Time : 2021/6/8 17:22
"""
from scrapy.cmdline import execute

import sys
import os

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(['scrapy', 'crawl', 'moviespider'])
Scrapy给出的将数据保存为json文件和csv文件的方式
execute(['scrapy', 'crawl', 'moviespider', '-o', 'moviespider.json'])
execute(['scrapy', 'crawl', 'moviespider', '-o', 'moviespider.csv'])

其实,Scrapy给出了将数据保存为json文件和csv文件的方式,大家可以执行main文件中注释掉的的命令即可,但是这种方式不够灵活,仅作为最简单的保存方式,下面还会介绍其他方式。

items.py中包含了想要爬取的电影相关数据

-*- coding: utf-8 -*-

Define here the models for your scraped items
#
See documentation in:
https://doc.scrapy.org/en/latest/topics/items.html

import scrapy

class DoubanmovieItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 设置需要采集的项
    # 电影排行
    rank = scrapy.Field()
    # 电影名称
    title = scrapy.Field()
    # 导演
    director = scrapy.Field()
    # 评分
    score = scrapy.Field()
    # 介绍
    introduction = scrapy.Field()
    # 电影海报图及地址
    picture = scrapy.Field()
    pass

moviespider.py包含了具体的xpath爬取规则,并且在爬取到电影海报图片地址后,这里我自己使用urllib库的request请求下载了电影海报,保存到picture文件夹下

-*- coding: utf-8 -*-
from urllib import request

import scrapy
from items import DoubanmovieItem

class BookspiderSpider(scrapy.Spider):
    name = 'moviespider'
    allowed_domains = ['douban.com']
    start_urls = ['https://movie.douban.com/top250']

    def parse(self, response):
        # 获取xpath过滤起始位置
        movie_item = response.xpath('//div[@class="item"]')
        # 遍历起始位置选择器解析数据
        for item in movie_item:
            # 创建实体对象
            movie = DoubanmovieItem()
            # 获取电影排行
            movie['rank'] = item.xpath('div[@class="pic"]/em/text()').extract()
            # 获取电影名称
            movie['title'] = item.xpath('div[@class="info"]/div[@class="hd"]/a/span[1]/text()').extract()
            # 获取电影导演
            movie['director'] = item.xpath('div[@class="info"]/div[@class="bd"]/p/text()').extract()
            # 获取电影评分
            movie['score'] = item.xpath(
                'div[@class="info"]/div[@class="bd"]/div[@class="star"]/span[2]/text()').extract()
            # 获取电影介绍
            movie['introduction'] = item.xpath('div[@class="info"]/div[@class="bd"]/p[2]/span/text()').extract()
            # 获取电影海报图及地址
            movie['picture'] = item.xpath('div[@class="pic"]/a/img/@src').extract()
            # 保存图片到本地
            try:
                if movie['picture']:
                    #   创建新的Request对象,将url传入
                    req_img = request.Request(url=movie['picture'][0])
                    img_data = request.urlopen(req_img)
                    img_name = str(movie['title'][0]) + '.jpg'# 保存图片
                    with open('./picture/'+img_name, 'wb') as f:
                        f.write(img_data.read())
            except Exception:
                print('获取图片失败')
            # 加入生成器
            yield movie
        next_page = response.css('span.next a::attr(href)').extract_first()
        if next_page is not None:
            yield response.follow(next_page, self.parse)

pipelines.py
这里我构建了3个Pipline,分别用于将爬取到的数据存储到mysql数据库,以及保存为json文件和csv文件

-*- coding: utf-8 -*-

Define your item pipelines here
#
Don't forget to add your pipeline to the ITEM_PIPELINES setting
See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
import pymysql
from scrapy.exporters import JsonItemExporter, CsvItemExporter, JsonLinesItemExporter

class DoubanmoviePipeline(object):
"""
    数据库pipline
"""
    def __init__(self):
        # 连接MySQL数据库
        self.connect = pymysql.connect(host='localhost', user='数据库用户名', password='密码', db='数据库名', port=3306)
        self.cursor = self.connect.cursor()

    def process_item(self, item, spider):
        print('电影排行:', item['rank'][0])
        print('电影名称:', item['title'][0])
        print(item['director'][0].strip().split('\xa0\xa0\xa0主演: ')[0])
        print('评分:', item['score'][0])
        if len(item['introduction']) > 0:
            introduction = item['introduction'][0]
            print('介绍:', item['introduction'][0])
        else:
            introduction = 0
        print('电影海报图及地址:', item['picture'][0])

        self.cursor.execute(
            'insert into doubanmovie(id,name,director,score,introduction,picture) '
            'VALUES ("{}","{}","{}","{}","{}","{}")'
                .format(item['rank'][0], item['title'][0].strip(),
                        item['director'][0].strip().split('\xa0\xa0\xa0主演: ')[0], item['score'][0],
                        introduction, item['picture'][0]))

        self.connect.commit()
        return item

    def close_spider(self, spider):
        self.cursor.close()
        # 关闭游标
        self.connect.close()

class JsonPipeline(object):
"""
    json存储pipline
"""
    def __init__(self):
        self.file = open('./files/movie.json', 'wb')
        # self.exporter = JsonLinesItemExporter(self.file, encoding="utf-8", ensure_ascii=False)
        self.exporter = JsonItemExporter(self.file, encoding="utf-8", ensure_ascii=False)
        self.exporter.start_exporting()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item

    def close_spider(self, spider):
        self.exporter.finish_exporting()
        self.file.close()

class CsvPipeline(object):
"""
    csv存储pipline
"""
    def __init__(self):
        self.file = open('./files/booksdata.csv', 'wb')
        self.exporter = CsvItemExporter(self.file,  encoding='utf-8-sig')
        self.exporter.start_exporting()

    def process_item(self, item, spider):
        self.exporter.export_item(item)
        return item

    def close_spider(self, spider):
        self.exporter.finish_exporting()
        self.file.close()

注意:在构建好Pipline后,要注意在settings.py中配置自定义的Pipline

ITEM_PIPELINES = {
    'doubanmovie.pipelines.DoubanmoviePipeline': 300,
    'doubanmovie.pipelines.JsonPipeline': 200,
    'doubanmovie.pipelines.CsvPipeline': 100
}

3. 总结

之前也没用过Scrapy,但是现在的框架都太完善了,一些基础问题都能很简便地通过框架实现,真的是方便。本来也是帮大一学生做的作业,就想跟新人们说一下,不要害怕代码,没有那么难搞,多动手多看,入门了就会好起来的。

Original: https://blog.csdn.net/nc514819873/article/details/117918051
Author: Growing_Snake
Title: Scrapy爬取豆瓣电影top250数据并保存mysql/json/csv

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/788778/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球