这样的关键字能搜到很多很多文章,可是,在我的实践过程中,没有一篇文章能够待我穿过山和大海,也走过人山人海,相反,都是带着我掉进了坑,陷进了沼泽,挂在了树上...
环境
python 叫做 Python3
,版本 v3.6.1
os 是 Mac os
scrapy 版本 v1.3.3
我有一个小目标,先扒下来几百张图再说
感谢douban,让我一次一次又一次地爬...
目标网页: https://www.douban.com/doulist/1295618/
它看起来是这样的
而我们的目标,是将这些 下载下来电影海报,顺便记录一下排行榜到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貌似是乱码)
cvs文件,可以很方便排序 下载下来的海报
网友评论