#!/usr/bin/env python
# -*- encoding: utf-8 -*-
# Created on 2018-11-29 15:51:21
# Project: DBDY01
from pyspider.libs.base_handler import *
import os;
#让 Handler 类继承 BaseHandler 类
class Handler(BaseHandler):
#指定目标文件存放目录
base_dir = "D:\\DouBanMovies"
#如果这个目录不存在就创建它
if not os.path.exists(base_dir):
os.makedirs(base_dir)
crawl_config = {
}
#该注解表示该程序每天爬一次
@every(minutes=24 * 60)
#声明程序入口方法
def on_start(self):
#指定爬取的页面(该地址为局部刷新的地址 AJAX 地址,实际上是一个 json 字符串,
page_limit=50&page_start=0:代表每次拿 50 个,从第 0 个开始拿),并且要求爬取完毕回
调 self.index_page 方法,免验证
self.crawl('https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%A7%91%E5%B
9%BB&sort=recommend&page_limit=50&page_start=0'
,validate_cert=False
,callback=self.index_page)
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
#从 response 中获取 json 串,因为里面是字典,所以通过传入键:subjects,来获得
相应的值,进而得到每一部电影的相关信息的数组
movieArray=response.json["subjects"]
#遍历这个数组,获取每个元素的 url 的值,然后进行爬取这些 url,免验证,完毕后
回调下一个函数
for m in movieArray:
self.crawl(m["url"],validate_cert=False, callback=self.mv_page)
@config(age=10 * 24 * 60 * 60)
#response 代表当前页面的响应消息
def mv_page(self, response):
#通过 css 选择器,获取每个电影的标题(名称),返回的是一个文本对象,用 gbk
编码处理此文本
mv_name=response.doc("h1 > span").text().encode("gbk")
#通过 css 选择器,获取每个电影的描述信息,返回的是一个文本对象,用 gbk 编码
处理此文本
mv_desc=response.doc("#info").text().encode("gbk")
#获取电影封面的地址,先获取页面中该图片的 img 标签,再获取该标签的 src 属性,
可以得到该图片的 url 地址
mv_img_url=response.doc("#mainpic img").attr.src;
#创建该电影的文件夹
#指向一个文件夹作为存放该电影的文件夹,以该电影的名字命名
mv_dir = self.base_dir+"\\"+mv_name
#如果这个目录不存在就创建它
if not os.path.exists(mv_dir):
os.makedirs(mv_dir)
#创建文本文件保存电影描述信息
#在 mv-dir 目录下创建一个以该电影名字命名的 txt 文档
mv_file = open(mv_dir+"\\"+mv_name+".txt","w")
#向该文档中写入该电影的描述信息
mv_file.write(mv_desc)
#冲刷缓冲区,关流
mv_file.flush()
mv_file.close()
#下载电影封面图片
#在 mv-dir 目录下指定一个文件夹作为电影封面储存路径
#将封面图片地址用/分割,取最后一位,作为电影图片存储路径,然后再与电影存
放路径进行拼接
mv_img_path = mv_dir+"\\"+mv_img_url.split("/")[-1]
#爬取封面图片,并将储存图片的路径以字典的形式传递给回调方法
self.crawl(mv_img_url,validate_cert=False,
callback=self.mv_img_down,save={"mv_img_path":mv_img_path})
#访问电影剧照图片,剧照为选择器的第四个子元素,从该元素的属性里面获取 href
标签即可得到该电影所有剧照的 url,然后爬取
mv_photos_url=response.doc(".related-pic .pl > a:nth-child(4)").attr.href
#爬取剧照页面,并将存放电影文件夹的路径往下传
self.crawl(mv_photos_url,validate_cert=False,
callback=self.mv_photos_page,save={"mv_dir":mv_dir})
@config(age=10 * 24 * 60 * 60)
def mv_photos_page(self, response):
#筛选剧照页面 img 标签,获取全部剧照的超链接数组
photoArr=response.doc(".article li > a").items()
#遍历这些数组,得到每一张剧照的超链接
for photoancr in photoArr:
#从这些超链接的属性中获取 href,就是该剧照的 url 进行爬取
self.crawl(photoancr.attr.href,validate_cert=False,
callback=self.mv_photo_page,save=response.save)
@config(age=10 * 24 * 60 * 60)
def mv_photo_page(self, response):
#从 save 中获取存放电影的路径,再与 photo 拼接,作为存放剧照的文件夹
Juzhao_path=response.save["mv_dir"]+"\\photo"
#判断是否存在,如果不存在就直接创建
if not os.path.exists(Juzhao_path):
os.makedirs(Juzhao_path)
#从 src 属性中获取这个图片的 url 地址
juzhaophotoURL=response.doc(".mainphoto > img").attr.src
#爬取剧照,回调下载方法
self.crawl(juzhaophotoURL,validate_cert=False,
callback=self.mv_img_down,save={"mv_img_path":Juzhao_path+"\\"+juzhaophotoURL.split("
/")[-1]})
@config(age=10 * 24 * 60 * 60)
def mv_img_down(self, response):
#获取封面图片的二进制数据
img_data=response.content
#创建文件指向要写出的图片的二进制数据,以字节流写出
img_file=open(response.save["mv_img_path"],"wb")
#将数据写出
img_file.write(img_data)
#冲刷缓冲区,关流
img_file.flush()
img_file.close()