稍微试了一下怎么使用scrapy,确实非常方便.
Scrapy的安装
安装指南可以戳这里因为安装太久了所以也忘了有啥需要的地方
开始用scrapy创建项目
在磁盘的任意位置(最好还是先新建一个文件夹)按住shift,鼠标右键打开CMD,输入以下命令
1
| scrapy startproject wallheaven_download
|
该命令会创建包含下列内容的
1 2 3 4 5 6 7 8 9
| wallheaven_download/ scrapy.cfg tutorial/ __init__.py items.py pipelines.py settings.py spiders/ __init__.py
|
这些文件分别是:
scrapy.cfg: 项目的配置文件
tutorial/: 该项目的python模块。之后您将在此加入代码。
tutorial/items.py: 项目中的item文件.
tutorial/pipelines.py: 项目中的pipelines文件.
tutorial/settings.py: 项目的设置文件.
tutorial/spiders/: 放置spider代码的目录.
定义Item
Item
是保存爬取到数据的一个容易,在抓wallheaven这个项目里,我们需要保存的信息都储存在里面,主要是图片的下载地址还有在本地保存的地址.
我们编辑wallheaven
文件夹里的items.py
1 2 3 4 5 6 7 8 9
| import scrapy class WallheavenDownloadItem(scrapy.Item): image_urls = scrapy.Field() images = scrapy.Field() image_paths = scrapy.Field()
|
编写第一个爬虫
编辑wallheaven
文件夹里的wallheaven_spider.py
一个正常的spider需要包含以下三个属性:
- name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同 的Spider设定相同的名字。
- start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
- parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class WallHeaven(Spider): name = 'wallheaven_image' allowed_domains = ['wallhaven.cc'] start_urls = ['http://alpha.wallhaven.cc/random?page=1'] for i in range(2, 5288): new_url = 'http://alpha.wallhaven.cc/random?page=' + str(i) start_urls.append(new_url) def parse(self, response): req = [] hxs = Selector(response) page_urls = hxs.xpath('//div[@id="thumbs"]//ul/li/figure/a/@href').extract() for url in page_urls: r = Request(url, callback=self.parse_image_page) req.append(r) return req def parse_image_page(self, response): hxs = Selector(response) download_link = hxs.xpath('//img[@id="wallpaper"]/@src').extract() for link in download_link: real_download_link = re.split(r'//', link)[1] postfix = re.split(r'/', link)[-1] Item = WallheavenDownloadItem() Item['image_urls'] = ["http://" + real_download_link] return Item
|
修改配置文件settings.py
1 2 3 4 5
| BOT_NAME = 'wallheaven_download' SPIDER_MODULES = ['wallheaven_download.spiders'] NEWSPIDER_MODULE = 'wallheaven_download.spiders' ITEM_PIPELINES = {'wallheaven_download.pipelines.MyImagesPipeline': 1} # 处理图片下载的管道,将对应的权值调大 IMAGES_STORE = './image'
|
下载图片
Scrapy
提供了一个Item pipeline
用来下载这个项目的图片
这条管道,被称作图片管道,在 ImagesPipeline 类中实现,提供了一个方便并具有额外特性的方法,来下载并本地存储图片:
将所有下载的图片转换成通用的格式(JPG)和模式(RGB)
避免重新下载最近已经下载过的图片
缩略图生成
检测图像的宽/高,确保它们满足最小限制
在我们这个项目里没有下载缩略图,壁纸当然要下载原始的
使用图片管道
当使用 ImagesPipeline
,典型的工作流程如下所示:
在一个爬虫里,你抓取一个项目,把其中图片的URL放入 image_urls 组内,就是我们在spider里面做的
项目从爬虫内返回,进入项目管道。
当项目进入 ImagesPipeline,image_urls 组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成图片的下载(或者由于某些原因未完成下载)。
当图片下载完,另一个组(images)将被更新到结构中。这个组将包含一个字典列表,其中包括下载图片的信息,比如下载路径、源抓取地址(从 image_urls 组获得)和图片的校验码。 images 列表中的图片顺序将和源 image_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 images 组中。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import scrapy from scrapy.contrib.pipeline.images import ImagesPipeline from scrapy.exceptions import DropItem class MyImagesPipeline(ImagesPipeline): def file_path(self, request, response=None, info=None): image_guid = request.url.split('/')[-1] return 'full/%s' % (image_guid) def get_media_requests(self, item, info): for image_url in item['image_urls']: yield scrapy.Request(image_url) def item_completed(self, results, item, info): image_paths = [x['path'] for ok, x in results if ok] if not image_paths: raise DropItem("Item contains no images") item['image_paths'] = image_paths return item class WallheavenDownloadPipeline(object): def process_item(self, item, spider): return item
|
最后在根目录输入
1
| scrapy crawl wallheaven_image
|
就可以了
在目录下会新建一个full文件夹,图片会源源不断的下载进来
不过有一个问题,停不下来,接不上去,我还没想好怎么去解决,sigh