关键时刻,第一时间送达!
【作者】:pk哥
【原文链接】:https://mp.weixin.qq.com/s/WIrepTu-2CGrGifLLRsHjw
全文758字 | 阅读需要7分钟
今天要完成的项目的是用 Scrapy 框架爬取煎蛋网妹子图片,这个项目之前用常规方法已经做过一次,为什么这次还要做这个项目呢?
1.用不同的方法做同一个项目,学习不同方法的特点。
2.上次用常规方法的写的项目有点小瑕疵,文章中有一处代码的配图用错了。关键字获取的源码中有一个方法因粗心多写了一个参数导致下载图片失败(已修正)。之前上传到 Github 上的代码是正确的。
所以这次还是用这个项目来学习下,咳咳,我们真的是用来学习的。
先放两张爬取的图片来给大家一点学习的动力。
项目环境
语言:Python3 编辑器:Pycharm
首先确保电脑已配置好 Scrapy 框架环境和 MongoDB 环境,不清楚的可参考上两篇文章:
初识爬虫框架 Scrapy
你的爬虫数据储存在哪?MongoDB入门篇
创建 Scrapy 项目
cmd 中通过命令创建 Scrapy 项目。
代码语言:javascript复制C:WindowsSystem32>F:
F:>cd scrapy
F:scrapy>scrapy startproject meizi
New Scrapy project 'meizi', using template directory 'e:\py3\lib\site-packages\scrapy\templates\project', created in:
F:scrapymeizi
You can start your first spider with:
cd meizi
scrapy genspider example example.com
然后基于basic模板创建一个名为的「jiandan」爬虫文件。
代码语言:javascript复制F:scrapy>cd meizi
F:scrapymeizi>scrapy genspider -t basic jiandan jiandan.net --nolog
Created spider 'jiandan' using template 'basic' in module:
meizi.spiders.jiandan
Scrapy 框架目录结构
items.py 文件
items.py 文件中定义提取的 Item,这里只定义了图片地址 img_url。
代码语言:javascript复制import scrapy
class MeiziItem(scrapy.Item):
img_url = scrapy.Field()
jiandan.py 文件
在上面创建的爬虫文件 jiandan.py 中编写爬虫代码提取 Item。煎蛋网是通过 js 加载图片信息的,Scrapy 爬虫框架没有提供页面 js 渲染服务,直接用 requests 我们获取不到信息。两种方法解决此问题。
1.继续用自动化测试库 selenium 提取图片信息,selenium 库的优点是可见即可爬。
2.用 scrapy-splash 库获取。scrapy-splash 安装启动比较繁琐,下次再讲解,我们今天用 selenium 库获取图片信息。
在 jiandan.py 文件中编辑代码,用 selenium 库抓取页面信息并提取图片链接。
代码语言:javascript复制# -*- coding: utf-8 -*-
import scrapy
from meizi.items import MeiziItem
from selenium import webdriver
browser = webdriver.Chrome()
browser.maximize_window()
class JiandanSpider(scrapy.Spider):
name = 'jiandan'
allowed_domains = ['jiandan.net']
url = "http://i.jandan.net/ooxx/"
page = 1
start_urls = [url 'page-' str(page) "#comments"]
def parse(self, response):
browser.get(response.url)
browser.implicitly_wait(15)
a_list = browser.find_elements_by_link_text("[查看原图]")
for a in a_list:
item = MeiziItem()
print(a.get_attribute('href'))
item['img_url'] = a.get_attribute('href') # 提取图片链接
yield item
if self.page < 38: # 最大页面数,每天可能有变动,可优化
self.page = 1
yield scrapy.Request(self.url str(self.page) "#comments", self.parse)
settings.py 文件
激活 Item Pipeline 组件,需要在 settin.py 文件中配置指定 pipelines 文件,在 settings 中找到 ITEM_PIPELINES,把这部分注释去除。
代码语言:javascript复制ITEM_PIPELINES = {
'meizi.pipelines.MeiziPipeline': 300,
}
pipelines.py 文件
编写 Pipeline 来存储提取到的数据,保存到本地或者保存到 MongoDB 中。
保存到本地
在本地新建好保存图片的路径。
代码语言:javascript复制import requests
class MeiziPipeline(object): # 保存到本地
count = 1
def process_item(self, item, spider):
result = requests.get(item['img_url'])
with open("E:\img\jiandan\" str(self.count) ".jpg", 'wb') as f:
f.write(result.content)
f.close()
self.count = 1
return item
保存到 MongoDB
MongoDB 和 pymongo 参考前面的文章安装好。新建一个 db 文件夹,用来存放 MongoDB 数据库。然后启动 cmd,cd 进入你下载的 MongoDB 解压的路径的 bin 文件,例如我的为 C:Program FilesMongoDBServer3.2bin,然后输入 mongod --dbpath=E:db 来启动 MongoDB,打开 MongoDB 可视化工具 Robo 3T。
在 pipelines.py 文件中修改代码如下:
代码语言:javascript复制class SaveToMongoPipeline(object): # 将数据保存到mongodb中
def __init__(self, mongo_url, mongo_db):
self.mongo_url = mongo_url
self.mongo_db = mongo_db
def process_item(self, item, spider):
data = [{
'img_url': item['img_url']
}]
self.db.image.insert(data)
return item
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_url)
self.db = self.client[self.mongo_db]
def close_spider(self):
self.client.close()
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_url=crawler.settings.get('MONGO_URL'),
mongo_db=crawler.settings.get('MONGO_DB')
)
在 settings.py 文件中修改配置 ITEM_PIPELINES 内容,定义 MongoDB 配置信息。
代码语言:javascript复制ITEM_PIPELINES = {
'meizi.pipelines.SaveToMongoPipeline': 301
}
MONGO_URL = 'mongodb://localhost:27017'
MONGO_DB = 'jiandan'
但是储存在 MongoDB 中用 Robo 3T 打开只显示图片的链接信息,如何显示图片有待研究。MongoDB 这方面知识点较薄弱,望大佬们赐教!
运行爬虫框架
有两种方法可运行,我用的是第二种。 1. cmd 中输入命令运行
代码语言:javascript复制scrapy crawl jiandan
2. 在编辑器(我用的是 Pycharm)爬虫项目目录下新建 run_spider.py 文件,输入命令,运行此 py 文件即可启动爬虫框架。
代码语言:javascript复制from scrapy.cmdline import execute
execute(['scrapy', 'crawl', 'jiandan'])
下面是储存在本地的图片。