阅读文本大概需要 10 分钟。
很多人说爬虫这门技术非常有趣,但不知道如何入门。其实爬虫入门非常简单,难的部分在于各大网站的反爬机制。当然对于一些简单的网站,还是非常容易爬取。
学习爬虫首先要明确你的驱动力,是想爬一些知乎的数据,还是一些电影的资源。驱动力非常重要,这决定你是否有足够的兴趣继续学下去。
很多人学习爬虫的第一驱动力就是爬取各大网站的妹子图片,比如比较有名的 mzitu。在爬这些网站的时候,即可以欣赏漂亮的妹子图,又能学习到技术,非常的 nice。
今天我就结合非常好用的 scrapy 框架,去抓取一些妹子图片,并把爬取的数据保存到 mongodb 数据库中。本次要爬取的网站是 360 的图片搜索网站,
360 图片的妹子质量还是非常可以的,我随意放几张大家感受下。
清纯可爱的
文艺又气质的
仙气十足的
非常的赏心悦目。
程序思路
本次程序运行的环境是 windows 10 + python 3.6,运行本次程序前首先确保你已经安装好了 scrapy、pymongo 以及 mongodb 数据库。
简单的分析了下 360 图片网站,并没有很强的反爬措施,并且网站的数据是以 Ajax 请求呈现。
我们进一步查看请求的详情,观察返回的数据结构。
返回的是 JSON 数据格式,其中 list 字段把图片的一些信息都保存在这里面。比如我们需要的图片地址信息 cover_imgurl。另外观察 Ajax 请求的参数信息,还有一个 sn 一直在变化,这个参数很明显就是偏移量。当 sn 为 30 时,返回的是前 30 张图片,依次类推,我们只需要改变 sn 的值就可以一直获取图片的信息。
接下来我们只需要通过 scrapy 高性能的框架,把网站上的图片保存到本地即可。
新建项目
首先在本地创建一个 scrapy 项目并命名为 images360。通过已下的命名即可创建。
scrapystartproject images360
随后就会有如下的项目结构
接下来就是在 spiders 目录下新建一个 Spider,命令如下:
这样我们的项目都已创建好,最后项目的结构如下。
程序代码
settings.py
在 settings.py 里面会先定义一个变量 MAX_PAGE,表示我们需要爬取的最大页面,比如在此次的程序中我们设置的是 50,也就是爬取 50 页,每页 30 张,一共 1500 张图片。
MAX_PAGE=50
settings.py 文件中我们还设置一些数据库相关的配置信息。
MONGO_URI='localhost'
MONGO_DB='test'
IMAGES_STORE='./images'
并且需要注意的是我们要修改 settings.py 中的 ROBOTSTXT_OBEY 变量,将其设置为 False,否则无法抓取。
ROBOTSTXT_OBEY=False
start_requests()
这个函数用来构造最开始的请求,用来生成 50 次请求。
defstart_requests(self):
data = {'ch':'photogtaphy','listtype':'new'}
base_url ='https://image.so.com/zj?0'
forpageinrange(1,self.settings.get('MAX_PAGE') +1):
data['sn'] = page *30
params = urlencode(data)
url = base_url + params
yieldRequest(url,self.parse
提取信息
我们会在 items.py 文件中定义一个 Images360Item 类,用来定义我们的数据结构。
classImages360Item(Item):
# define the fields for your item here like:
# name = scrapy.Field()
collection = table ='images'
id = Field()
url = Field()
title = Field()
thumb = Field()
其中包括图片的 ID、链接、标题、缩略图。另外还有两个属性 collection 和 table,都定义为 images 字符串,代表 MongoDB 存储的 Collection 名称。
接下来我们提取 Spider 里有关信息,在 parse() 方法改写成如下所示:
defparse(self, response):
result= json.loads(response.text)
forimageinresult.get('list'):
item = Images360Item()
item['id'] = image.get('imageid')
item['url'] = image.get('qhimg_url')
item['title'] = image.get('group_title')
item['thumb'] = image.get('qhimg_thumb_url')
yielditem
这样我们就完成了信息的提取,接下来就需要把抓取的信息保存到 MongoDB 中。
MongoDB
首先确保你本地已经安装好了 MongoDB,并且已经正常启动。我们用一个 MongoPipeline 将信息保存到 MongoDB 中,在 pipelines.py 里添加如下类的实现:
classMongoPipeline(object):
def__init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
deffrom_crawler(cls, crawler):
returncls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DB')
)
defopen_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db =self.client[self.mongo_db]
defprocess_item(self, item, spider):
self.db[item.collection].insert(dict(item))
returnitem
defclose_spider(self, spider):
self.client.close()
ImagePipeline
Scrapy 提供了专门处理下载的 Pipeline,包括文件下载和图片下载。下载文件和图片的原理与抓取页面的原理一样,因此下载过程支持异步和多线程,下载十分高效。
我们首先在 settings.py 定义一个 IMAGES_STORE 变量,用来表示图片存储的路径。
IMAGES_STORE='./images'
内置的 ImagesPipeline 会默认读取 Item 的 image_urls 字段,并认为该字段是一个列表形式,它会遍历 Item 的 image_urls 字段,然后取出每个 URL 进行图片下载。
但是现在生成的 Item 的图片链接字段并不是 image_urls 字符表示的,也不是列表形式,而是单个的 URL。所以为了实现下载,我们需要重新定义下载的部分逻辑,即要自定义 ImagePipeline,继承内置的 ImagesPipeline,从而实现我们自己的图片下载逻辑。
classImagePipeline(ImagesPipeline):
deffile_path(self, request, response=None, info=None):
url = request.url
file_name = url.split('/')[-1]
returnfile_name
defitem_completed(self, results, item, info):
image_paths = [x['path']forok, xinresultsifok]
ifnotimage_paths:
raise DropItem('Image Downloaded Failed')
returnitem
defget_media_requests(self, item, info):
yieldRequest(item['url'])
最后我们需要在 settings.py 中把我们定义好的 Item Pipeline 打开,修改 settings.py 中的 ITEM_PIPELINES 即可。
ITEM_PIPELINES = {
'images360.pipelines.ImagePipeline': 300,
'images360.pipelines.MongoPipeline': 301
}
最后我们只需要运行程序,即可执行爬取,程序运行命名如下:
scrapycrawl images
Python 进阶之路
最后打个小广告,我的知识星球也已经运营了一个月的时间了。星球里有个「K 计划」,每天带大家学习一个 Python 知识,每周一个实战项目练习。
每个知识点我都非常认真的整理出一个思维导图。现在基础知识已经差不多讲完了,马上开启下个阶段「K 计划之爬虫」,一步步的带大家学习爬虫。
现在加入星球即可免费获取之前的「K 计划之基础篇」所有的思维导图,每个知识点我都有参考的文章。
领取专属 10元无门槛券
私享最新 技术干货