1.需求
抓取豆瓣top250的电影名称,评分,简介,并保存在本地。
2.分析
抓取的起始url:
https://movie.douban.com/top250
分析源码
可以看到电影名称,评分都在源码中包含,继续点进去查看电影详情页面
可以看到在详情页面也有我们需要的数据,这思路不就出来了
通过
https://movie.douban.com/top250
循环获取250部电影的详情页url,在使用方法解析每个url或取出来的数据,保存。
3.代码
1.创建scrapy项目DouBanTOP250 我是全程在pycharm的终端进行的
scrapy startproject DouBanTOP250
2.创建爬虫文件
cd DouBanTOP250
scrapy genspider movie https://movie.douban.com/top250
创建完成时候项目文件结构如下:
3.配置settings.py
避免被豆瓣反爬拦截,我们进入settings.py文件进行一些请求头cookie等一些反扒措施的设置:
设置useragent:
君子协议我们不需要遵守,修改为false
ROBOTSTXT_OBEY = False
设置下载器的延迟
把注释取消,单位为秒,看需要设置
DOWNLOAD_DELAY = 1
全局cookie设置一下改为true
配置请求头,把我们登陆过后的cookie添加上去,避免豆瓣检测异常请求:
爬虫中间件,下载器中间件暂时先不进行设置,这就已经够用了
4.写parse解析方法
打开spiders下的movie文件:
我们需要对parse方法进行补充,其中response是起始url通过爬虫器构造->调度器调度->下载器下载,最后通过引擎返回给我们的起始url的响应数据,我们对这个响应数据使用xpath进行提取:
1.提取每一部电影的详情页url
//div[@class='hd']/a/@href
2.提取下一页的链接
//a[text()='后页>']/@href
这里注意一下?start=25&filter=提取出来的下一页链接只是一个url中的参数,一会需要使用response的follow方法进行构造下一页的请求对象
3.代码
对起始url的解析代码如下:
import scrapy
class MovieSpider(scrapy.Spider):
name = 'movie'
allowed_domains = ['https://movie.douban.com/top250']
start_urls = ['http://movie.douban.com/top250/']
def parse(self, response):
# getall()获取匹配的所有电影详情页url,返回一个list
movie_list=response.xpath("//div[@class='hd']/a/@href").getall()
# get返回第一个匹配到的对象返回一个str
next_page=response.xpath("//a[text()='后页>']/@href").get()
for movie_url in movie_list:
# 把新构造的对电影详情页的请求对象抛给引擎 callback传入回调函数,解析这个请求
yield scrapy.Request(movie_url, callback=self.parse_movie_url )
# 把对下一页的请求对象抛给引擎
yield response.follow(next_page,callback=self.parse)
# 对电影详情页解析的方法
def parse_movie_url(self,response):
pass
我们保存数据需要一个item类,下面我们根据模板配置一下,打开items.py
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class Doubantop250Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 电影名称
name = scrapy.Field()
# 电影评分
score = scrapy.Field()
# 电影详情简介
text = scrapy.Field()
其中pipelines.py是负责保存文件的,这里我们就不进行配置了,一会我们直接调用scrapy自带的方法进行保存,有想保存数据库或者别的想法的话可以自行修改
5.写parse_movie_url方法
该方法解析新构造的请求对象的相应内容
1.创建一个容器
item_ = Doubantop250Item()
2.提取电影名称,简介,评分
item_['name'] = response.xpath("//span[@property='v:itemreviewed']/text()").get()
item_['score'] = response.xpath("//strong[@property='v:average']/text()").get()
item_['text'] = response.xpath("//span[@property='v:summary']/text()").get().strip() # strip把空格去掉
3.代码
import scrapy
from ..items import *
class MovieSpider(scrapy.Spider):
name = 'movie'
allowed_domains = ['https://movie.douban.com/top250']
start_urls = ['http://movie.douban.com/top250/']
def parse(self, response):
# getall()获取匹配的所有电影详情页url,返回一个list
movie_list = response.xpath("//div[@class='hd']/a/@href").getall()
# get返回第一个匹配到的对象返回一个str
next_page = response.xpath("//a[text()='后页>']/@href").get()
for movie_url in movie_list:
# 把新构造的对电影详情页的请求对象抛给引擎 callback传入回调函数,解析这个请求
yield scrapy.Request(movie_url, callback=self.parse_movie_url)
# 把对下一页的请求对象抛给引擎
yield response.follow(next_page, callback=self.parse)
# 对电影详情页解析的方法
def parse_movie_url(self, response):
item_ = Doubantop250Item()
# 分别用xpath把电影名称,评分,简介提取出来
item_['name'] = response.xpath("//span[@property='v:itemreviewed']/text()").get()
item_['score'] = response.xpath("//strong[@property='v:average']/text()").get()
item_['text'] = response.xpath("//span[@property='v:summary']/text()").get().strip() # strip把空格去掉
# 抛出item
yield item_
代码基本已经完成
4.结果
这里调试信息显示这个电影详情页被过滤掉了,很明显这是我们在设置爬取域的时候设置错误造成只需要把爬取域改一下即可
class MovieSpider(scrapy.Spider):
name = 'movie'
#控制爬取域
allowed_domains = ['douban.com']
start_urls = ['http://movie.douban.com/top250/']
开始爬取:
等待一下即可:
任务完成.