运用scrapy爬虫框架爬取fgowiki上的礼装图片
一、scrapy框架的安装使用
1、安装基础环境
一般的python包可以直接使用pip安装
安装lxml
pip install lxml
如果没有任何报错,则证明安装成功。
如果出现报错,比如提示缺少libxml2库等信息,可以采用wheel方式安装。
直接到这里下载对应的whl文件,找到本地安装Python版本和系统对应的lxml版本,将其下载到本地。
然后利用pip安装即可,命令如下:
pip install lxml‑4.2.5‑cp35‑cp35m‑win_amd64.whl
安装pyOpenSSL
在官方网站点击 Download files,下载whl文件,同样使用pip安装
安装Twisted
直接到这里下载对应的whl文件,找到本地安装Python版本和系统对应的lxml版本下载,同样使用pip安装
安装PyWin32
从官方网站下载对应版本的安装包即可,
2、安装scrapy
有了依赖库之后,安装scrapy本体非常简单,使用以下命令安装即可
pip install Scrapy
如果需要对js进行渲染的话,还需要使用scrapy-splash与docker。
其中scrapy-splash直接pip install scrapy_splash
就行。
docker需要docker pull scrapinghub/splash ,并开启8050端口docker run -p 8050:8050 scrapinghub/splash
详情可以参考Scrapy学习篇(十三)之scrapy-splash
不需要js渲染的话就不用折腾docker了。
二、scrapy框架构成
Scrapy使用Twisted作为框架,采用异步事件驱动,具体架构图如下:
Scrapy数据流是由执行的核心引擎(engine)控制,流程是这样的:
- 爬虫引擎获得初始请求开始抓取。
- 爬虫引擎开始请求调度程序,并准备对下一次的请求进行抓取。
- 爬虫调度器返回下一个请求给爬虫引擎。
- 引擎请求发送到下载器,通过下载中间件下载网络数据。
- 一旦下载器完成页面下载,将下载结果返回给爬虫引擎。
- 引擎将下载器的响应通过中间件返回给爬虫进行处理。
- 爬虫处理响应,并通过中间件返回处理后的items,以及新的请求给引擎。
- 引擎发送处理后的items到项目管道,然后把处理结果返回给调度器,调度器计划处理下一个请求抓取。
- 重复该过程(继续步骤1),直到爬取完所有的url请求。
爬虫引擎(Engine)
爬虫引擎负责控制各个组件之间的数据流,当某些操作触发事件后都是通过engine来处理。
调度器(Scheduler)
调度接收来engine的请求并将请求放入队列中,并通过事件返回给engine。
下载器(Downloader)
通过engine请求下载网络数据并将结果响应给engine。
爬虫模块(Spider)
Spider发出请求,并处理engine返回给它下载器响应数据,以items和规则内的数据请求(urls)返回给engine。
管道项目(item pipeline)
负责处理engine返回spider解析后的数据,并且将数据持久化,例如将数据存入数据库或者文件。
下载中间件(Downloader middlewares)
下载中间件是engine和下载器交互组件,以钩子(插件)的形式存在,可以代替接收请求、处理数据的下载以及将结果响应给engine。
spider中间件(Spider middlewares)
spider中间件是engine和spider之间的交互组件,以钩子(插件)的形式存在,可以代替处理response以及返回给engine items及新的请求集。
三、scrapy入门
如果可以的话配合使用virtualenv,可以单独配置爬虫环境,具体使用方法应该会另外说明(咕咕)。
在virtualenv环境中,进入想要创建的目录中,输入:
scrapy startproject tutorial
例如:
scrapy会自动创建一个tutorial文件夹(可改名),文件夹内目录如下:
scrapy.cfg #scrapy基础配置
tutorial/
__init__.py
items.py #负责数据模型的建立,类似于实体类
middlewares.py #自己定义的中间件
pipelines.py #负责对spider返回数据的处理
settings.py #爬虫项目主要配置文件
spiders/ #自定义的文件夹,里面填写自己写的爬虫文件
__init__.py
...
四、爬取礼装的关键代码
具体可参见该项目的Github:scrapy-FGOwiki-spider
在spiders文件夹内可以自定义自己的爬虫文件,py文件名随意,但需要在class里面使用name
属性定义自己的爬虫名字。至于类的名字可以自由定义,反正也不直接使用它。
其中这个爬虫类需要有几个重要的属性:
– start_urls 用于设定爬虫开始爬取的初始URL
– allowed_domains 设定爬虫可以爬取的范围,一般是某一个域名
– headers 爬虫的请求头,作用和模拟登录中发起请求的header是一样的
– headers 爬虫的请求头,作用和模拟登录中发起请求的header是一样的
– parse(self, response) 爬虫爬取到网站信息之后返回处理的函数,提取出我们需要的信息并把它置于item中,下一步交由对应的处理函数或者pineline处理。
# -*- coding: utf-8 -*-
import scrapy
import re
from ..items import TutorialItem #..代表上一级
from scrapy_splash import SplashRequest
class DmozSpider(scrapy.Spider):
#定义爬虫名
name = "fgo-wiki-demo"
#搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页
allowed_domains = [""]
#用for构造url
start_urls = []
for i in range(901):
start_urls.append('https://fgowiki.com/guide/equipdetail/%s'%i)
print(start_urls)
# 设置爬虫的请求头,防止爬取失败
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36',
}
# 定义主页面爬取规则,有其他链接则继续深挖
#rules = (Rule(LinkExtractor(allow=('.+?\.html')), follow=True),
def start_requests(self):
for url in self.start_urls:
yield SplashRequest(url
,self.parse
,args={'wait':'0.5'}
)
pass
#该函数名不能改变,因为Scrapy源码中默认callback函数的函数名就是parse
def parse(self, response):
item = TutorialItem()
image_style = response.xpath('//li[@class="swiper-slide eq Card"]/@style').extract() #返回一个list,但这个list里只有一条
item['image_urls'] = re.search(r'http.*?jpg',image_style[0]).group()
item['name'] = response.xpath('//div[@class="textsmall NAME_CN"]//text()').extract_first()
item['author'] = response.xpath('//div[@class="textsmall ILLUST"]//text()').extract_first()
yield item
print("返回item成功")
在爬虫中引用的item需要在items.py
中定义:
import scrapy
class TutorialItem(scrapy.Item):
image_urls=scrapy.Field()
name = scrapy.Field()
author = scrapy.Field()
如果需要下载文件的话,则需要在pipelines.py
中定义处理函数。这个函数比较自由发挥,能实现自己需要的功能即可。
# -*- coding: utf-8 -*-
import scrapy
from scrapy.pipelines.images import ImagesPipeline
class TutorialPipeline(ImagesPipeline):
def get_media_requests(self, item, info):
print("获取URL")
yield scrapy.Request(item['image_urls'], meta={'item': item, 'index': item['image_urls']})
def file_path(self, request, response=None, info=None):
item = request.meta['item'] # 通过上面的meta传递过来item
image_name = "礼装-" + item['name'] + "." + request.url.split('/')[-1].split('.')[-1]
down_file_name = u'/{0}/{1}'.format(item['author'], image_name)
return down_file_name
在项目下使用scrapy crawl 爬虫名
即可运行爬虫
参考链接:
崔庆才的个人博客
scrapy中文文档
Scrapy修改下载图片名字