天天看点

爬取豆瓣电影TP250(文字信息+保存图片)

思路:

1、豆瓣电影TOP250 url=https://movie.douban.com/top250

2、使用crawlspider获取250个电影详情页url

3、使用xpath解析数据:获取电影标题、导演、演员、简介、热门第一评论、评论人数等详细信息

4、保存250部电影海报图片

一、准备工作

创建一个scrapy project:

scrapy startproject DBMOVIE
           

创建spider file

scrapy genspider -t crawl douban douban.com
           

二、构建框架

(1)items.py / 定义item

import scrapy

class DbmovieItem(scrapy.Item):
    Rank = scrapy.Field()
    Title =scrapy.Field()
    Attr =scrapy.Field()
    Actor =scrapy.Field()
    Type_ = scrapy.Field()
    Rating_num =scrapy.Field()
    Time_ =scrapy.Field()
    Short =scrapy.Field()
    Image_url = scrapy.Field()
    Hot_comment = scrapy.Field()
           

(2) spider.py

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
import time
from DBMOVIE.items import DbmovieItem

class DoubanSpider(CrawlSpider):
    name = 'douban'
    allowed_domains = ['douban.com']
    #豆瓣电影top250共有10页,将每页的url都加入start_url列表中
    base_urls = 'https://movie.douban.com/top250?start={}&filter='
    start_urls =[]
    #设置index用来查看爬取进度,可不要
    index = 0
    for i in range(10):
        url = base_urls.format(i*25)
        start_urls.append(url)
    #设置crawl爬取规则,获取每页中的25个详情页url
    #CrawlSpider框架获取url有去重功能
    rules = (
        Rule(LinkExtractor(allow='subject/'), callback='parse_item', follow=False),
    )

    def parse_item(self, response):
        self.index +=1
        #导入item
        item = DbmovieItem()
        #获取排名,得到的数据顺序是随机的,后续可以使用排名重新排序
        item['Rank'] = response.xpath('//*[@id="content"]/div[1]/span[1]/text()').extract_first()[3:]
        #电影名称
        item['Title'] = response.xpath('//*[@id="content"]/h1/span[1]/text()').extract_first()
        #导演
        item['Attr'] = response.xpath('//*[@id="info"]/span[1]/span[2]/a/text()').extract_first()
        #演员,演员有多个,在多个同级标签中,使用join将获取到的列表中多个导演名字连成一个完整字符串
        item['Actor'] = ','.join(response.xpath('//*[@id="info"]/span[@class="actor"]/span[2]/a/text()').extract())
        #电影类别
        item['Type_'] =  ','.join(response.xpath('//*[@id="info"]/span[@property="v:genre"]/text()').extract())
        #电影评论人数
        item['Rating_num'] = response.xpath('//*[@id="interest_sectl"]//a[@class="rating_people"]/span/text()').extract_first()
        #上映时间
        item['Time_'] = ','.join(response.xpath('//*[@id="info"]/span[@property="v:initialReleaseDate"]/text()').extract())
        #简介
        item['Short'] = (((''.join(response.xpath('//*[@id="link-report"]//span[1]/text()').extract())).replace('\n','')).strip()).replace(' ','')
        #图片url,后面用来下载图片
        item['Image_url'] = response.xpath('//*[@id="mainpic"]/a/img/@src').extract_first()
        #热评第一个
        item['Hot_comment'] = (response.xpath('//*[@id="hot-comments"]/div[1]/div/p/span/text()').extract_first().strip()).replace('\t','')
        print('获取到第%d个' % self.index)
        print(item['Rank'],item['Title']) 
        yield item
           

(3) middlewares.py

#在项目下创建了一个user_agent.py文件保存了user_agents池
#使用scrapy的UserAgentMiddleware模块获取user_agent
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware
from DBMOVIE.user_agent import user_agents
import random

class RotateUserAgentMiddleware(UserAgentMiddleware):

    def process_request(self, request, spider):
    	#随机选取一个user_agent,传入请求头
        user_agent = random.choice(user_agents)
        if user_agent:
            print('**********user ug:%s***********' % user_agent)
            request.headers['User-Agent'] = user_agent
        return None
           

(4)pipelines.py

from scrapy.exporters import CsvItemExporter
import DBMOVIE.settings as setting
import urllib.request
import os
import pymongo
#将获取的数据保存到MongoDB数据库中
class DbmoviePipeline(object):
    def open_spider(self,spider):
    	#连接服务器,使用默认地址端口
        self.client = pymongo.MongoClient()
        #创建/选择数据库
        self.mydb = self.client['test']
        #创建/选择表
        self.collection = self.mydb['dbmovie']

    def process_item(self, item, spider):
        #插入数据
        self.collection.insert(dict(item))
        return item


#重写一个保存图片的管道
class DbmovieImgPipline(object):

    def process_item(self,item,spider):
		#设置保存图片的文件夹地址
        dir_path = '%s/%s' % (setting.IMAGES_STORE,spider.name)
        #若不存在则创建它
        if not os.path.exists(dir_path):
            os.makedirs(dir_path)
        #获取图片url
        img_url = item['Image_url']
        #创建图片名称
        file_name = item['Rank'] + item['Title'] + '.jpg'
        #拼接文件夹地址和图片名称创建文件保存路径
        file_path = '%s/%s' % (dir_path,file_name)
        #去重
        if os.path.exists(file_path):
            print('重复,跳过',+img_url)
        #保存图片
        with open(file_path,'wb') as f:
            print('正在下载图片',img_url)
            #使用图片url发生请求获取到图片,保存到对应的路径中
            conn = urllib.request.urlopen(img_url)
            f.write(conn.read())
            f.close()
        return item
           

5)设置setting

一般写好一部分代码就开启相应的设置,以防忘记

BOT_NAME = 'DBMOVIE'

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

LOG_FILE = 'douban.log'
LOG_LEVEL = 'WARNING'
#保存图片的文件地址
IMAGES_STORE = './img'
#不遵守robort协议
ROBOTSTXT_OBEY = False
#下载延迟
DOWNLOAD_DELAY = 3
#打开设置user_agent的下载中间件
DOWNLOADER_MIDDLEWARES = {
   'DBMOVIE.middlewares.RotateUserAgentMiddleware': 543,
}
#打开保存数据和图片的管道
ITEM_PIPELINES = {
   'DBMOVIE.pipelines.DbmoviePipeline': 300,
    'DBMOVIE.pipelines.DbmovieImgPipline':350,
}
           

三、运行spider

(1)打开MongoDB服务器,启动客户端

sudo mongod
           
mongo
           

(2)运行spider

scrapy crawl maitian
           

四、完成以上几步即可以查看数据啦

如果需要可以对MongoDB中的数据CSV可视化处理

爬取豆瓣电影TP250(文字信息+保存图片)
爬取豆瓣电影TP250(文字信息+保存图片)