本来呢,一开始想爬取的是这个网站,http://www.mzitu.com/,但是呢?问题发现比较多,所以先爬取了http://www.meizitu.com/这个网站,下一步再去爬取第一个。 GitHub地址:https://github.com/zhangpu1211/scrapy/tree/master/MeiZitu 首先看一下爬取结果
是不是很激动。。。下面开始正式工作
创建项目
这个就很简单啦,scrapy startproject MeiziTu
创建模板
也是我们之前提到了,用genspider创建一个basic模板
scrapy genspider image http://www.meizitu.com/tag/keai_64_1.html
建立main文件方便调试
和自动生成的scrapy.cfg在同一层,写入下面代码
代码语言:javascript复制from scrapy.cmdline import execute
import sys,os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(['scrapy','crawl','image'])
创建item
我们要爬取的内容,就是图集的地址,名称,以及图片的地址
代码语言:javascript复制class MeizituItem(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
imgs_url = scrapy.Field()
url = scrapy.Field()
分析页面,确定爬取逻辑
目标是爬取可爱目录下的所有图集的图片,并把图片按名称归档,方便查看。 剩下的内容就是简单的用css提取名称和地址了
代码语言:javascript复制class MeiZituSpider(scrapy.Spider):
name = 'image'
allowed_domains = ['meizitu.com']
start_urls = ['http://www.meizitu.com/tag/keai_64_1.html']
def parse(self, response):
nodes = response.css('.wp-list .tit a')
for node in nodes:
url = node.css('::attr(href)').extract_first().strip()
yield Request(url=parse.urljoin(response.url, url), callback=self.parse_detail)
index = response.css('#wp_page_numbers li a::text').extract()
if '下一页' in index:
next_urls = response.css('#wp_page_numbers li a')[-2].css('a::attr(href)').extract_first()
yield Request(url=parse.urljoin(response.url, next_urls),callback=self.parse)
def parse_detail(self, response):
item = MeizituItem()
name = response.css('.postmeta h2 a::text').extract_first()
imgs_url = response.css('.postContent p img::attr(src)').extract()
item['name'] = name
item['imgs_url'] = imgs_url
item['url'] = response.url
yield item
编辑pipeline实现图片归档
本来呢,我们可以用scrapy自己的'scrapy.pipelines.images.ImagesPipeline': 1
,实现图片下载,但是这样下载下来乱糟糟的,没有美感,对于轻微的强迫症或者那就接受不了了。必须要按图集名字分个类
下面的代码继承自ImagesPipeline,通过重写file_path方法实现了图片分类,一开始只重写这个方法,发现不行,图片没有下载,后来发现必须要加上get_media_requests这个方法才可以。
class ArticleImagePipeline(ImagesPipeline):
def file_path(self, request, response=None, info=None):
item = request.meta['item']
title = item['name']
image_guid = request.url.split('/')[-1]
filename = 'full/{0}/{1}'.format(title, image_guid)
return filename
def get_media_requests(self, item, info):
"""
:param item: spider.py中返回的item
:param info:
:return:
"""
for img_url in item['imgs_url']:
referer = item['url']
yield Request(img_url, meta={'item': item,
'referer': referer})
编辑setting文件
- 设置遵循爬虫协议为False
ROBOTSTXT_OBEY = False
- 设置item图片字段为imgs_url,设置保存路径为同级目录下images
IMAGES_URLS_FIELD = "imgs_url"
project_dir = os.path.abspath(os.path.dirname(__file__))
IMAGES_STORE = os.path.join(project_dir, 'images')
- 增加浏览器头
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0'
- 开启pipeline
ITEM_PIPELINES = {
'MeiZitu.pipelines.ArticleImagePipeline': 1,
#'scrapy.pipelines.images.ImagesPipeline': 1,
}
至此,爬取结束,下一步就是爬取http://www.mzitu.com/,代码会更新在GitHub上!