本文发自 http://www.binss.me/blog/write-a-spider-in-ten-minutes-to-fetch-the-images/,转载请注明出处。
今晚无聊刷微博,无意中发现一张鹿岛的cos十分传神,经过强大的搜图引擎,获知其在半次元有完整套图。
老司机先开一波车:http://bcy.net/coser/detail/16016/417762
作为一名老司机,对于喜爱的套图,当然是down下来珍藏,然而很显然这种站不会有类似“一键下载”的按钮,于是写个脚本把它搞下来。当然为了一个这么简单的需求,我们当然不能花太多时间去从头到尾搞只爬虫,于是我选择了pyspider。由于先前有学习过这个框架,所以飞速地撸了个脚本把图都抓下来了。
思路
-
通过”审查元素“发现,网页上的图片链接,如
http://img9.bcyimg.com/coser/16016/post/177ne/b43cda60c0c711e5b0892d9b80c834ad.jpg/w650
是缩放过的,完整图片为
http://img9.bcyimg.com/coser/16016/post/177ne/b43cda60c0c711e5b0892d9b80c834ad.jpg
即去掉尾部的w650即可。写个正则进行匹配。
-
开启pyspider的css selector helper,在web页面选中图片,得到css选择器
.detail_clickable
。同理得到character和coser的选择器为
.post__role-headline > a
和.maxw700 > h3 > a
-
正则匹配图片url得到原图url和后缀名,拼接character和coser得到文件夹名
-
根据文件夹名,如
优歌yuuka - 鹿岛
创建下载文件夹,然后根据url将所有原图下载到该文件夹内 -
顺手伪装下headers,比如User-Agent、Referer之类的
完整脚本
# !/usr/bin/env python
# -*- coding: utf-8 -*-
#
# FileName: bcy.py
# Author: binss
# Create: 2016-09-03 22:50:32
# Description: No Description
#
import re
import urllib2
import os
from pyspider.libs.base_handler import *
DOWNLOAD_DIR = '/home/binss/pyspider/download'
fetch_url = 'http://bcy.net/coser/detail/16016/417762'
# e.g. http://img9.bcyimg.com/coser/16016/post/177ne/b43cda60c0c711e5b0892d9b80c834ad.jpg/w650
def download(url, folder, index):
match = re.search('(.*\.(.*))\/', url)
if match:
url = match.group(1)
print 'downloading {}'.format(url)
image = urllib2.urlopen(url).read()
path = os.path.join(DOWNLOAD_DIR, folder)
if not os.path.exists(path):
os.makedirs(path)
filename = os.path.join(path, '{}.{}'.format(index, match.group(2)))
with open(filename, 'w+') as f:
f.write(image)
class Handler(BaseHandler):
crawl_config = {
'headers': {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
'Referer': fetch_url,
'Accept-Language': 'zh-CN,zh;q=0.8',
'Accept': 'image/webp,image/*,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, sdch',
}
}
def on_start(self):
self.crawl(fetch_url, callback=self.index_page)
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
image_urls = []
character = response.doc('.post__role-headline > a').text()
coser = response.doc('.maxw700 > h3 > a').text()
folder = u'{} - {}'.format(coser, character)
index = 1
for x in response.doc('.detail_clickable').items():
image_urls.append(x.attr.src)
download(x.attr.src, folder, index)
index += 1
return {
'character': character,
'coser': coser,
'total': index - 1,
'debug': image_urls,
}
流程
-
通过
pyspider -c config.json
启动pyspider -
访问webui,由于我通过config.json重定义了端口,所以是
http://127.0.0.1:8888/
-
点击Create创建新的Project
-
在
http://127.0.0.1:8888/debug/bcy
的代码框中粘入完整脚本 -
点击run执行第一步
然后点击结果中的
>
后继续点击run -
等待下载完毕,在相应位置得到套图
缺陷
-
目测半次元对抓图有流量限制,每次满速抓到一半就没流量了,然后等待几十秒后会继续满速下载。可以考虑代理池
-
在run过程中,webui其他页面无法访问(阻塞),目测是
urllib2.urlopen(url).read()
阻塞了web server。可以考虑异步get。
总结
利用pyspider可以快速开发爬虫,实在是居家必备的利器。作为爬虫爱好者,我裸写过许多爬虫脚本,也开发过简易的爬虫框架,最后发现还是别人的轮子好用。本文仅作抛砖引玉,更多用法请参考文档http://docs.pyspider.org/en/latest/。
1F Wong arrhenius 5 years, 3 months ago 回复
爬虫啥的没兴趣,套图哪里还有,老司机现在还开车吗