第一次使用Scrapy框架遇到不少坑,坚持去搜索,修改代码就能够解决问题。此次爬取的是一个斗图网站的最新表情图片www.doutula.com/photo/list,练习使用Scrapy框架而且使用的随机user agent防止被ban,斗图表情包每日更新,一共能够抓取5万张左右的表情到硬盘中。为了节省时间我就抓取了1万多张。html
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 能够应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。git
使用过程github
- 建立一个Scrapy项目
- 定义提取的Item
- 编写爬取网站的 spider 并提取 Item
- 编写 Item Pipeline 来存储提取到的Item(即数据)
接下来的图表展示了Scrapy的架构,包括组件及在系统中发生的数据流的概览(绿色箭头所示)。 下面对每一个组件都作了简单介绍,并给出了详细内容的连接。数据流以下所描述数据库
组件服务器
Scrapy Engine
引擎负责控制数据流在系统中全部组件中流动,并在相应动做发生时触发事件。 详细内容查看下面的数据流(Data Flow)部分。cookie
调度器(Scheduler)
调度器从引擎接受request并将他们入队,以便以后引擎请求他们时提供给引擎。架构
下载器(Downloader)
下载器负责获取页面数据并提供给引擎,然后提供给spider。并发
Spiders
Spider是Scrapy用户编写用于分析response并提取item(即获取到的item)或额外跟进的URL的类。 每一个spider负责处理一个特定(或一些)网站。 更多内容请看 Spiders 。框架
Item Pipeline
Item Pipeline负责处理被spider提取出来的item。典型的处理有清理、 验证及持久化(例如存取到数据库中)。 更多内容查看 Item Pipeline 。dom
下载器中间件(Downloader middlewares)
下载器中间件是在引擎及下载器之间的特定钩子(specific hook),处理Downloader传递给引擎的response。 其提供了一个简便的机制,经过插入自定义代码来扩展Scrapy功能。更多内容请看 下载器中间件(Downloader Middleware) 。
Spider中间件(Spider middlewares)
Spider中间件是在引擎及Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items及requests)。 其提供了一个简便的机制,经过插入自定义代码来扩展Scrapy功能。更多内容请看 Spider中间件(Middleware) 。
1.从网站的主页进入最新斗图表情后网址是https://www.doutula.com/photo/list/ ,点击第二页后看到网址变成了https://www.doutula.com/photo/list/?page=2 ,那咱们就知道了网址的构成最后的page就是不一样的页数。那么spider中的start_urls开始入口就以下定义,爬取1到20页的图片表情。想下载更多表情页数你能够再增长。
start_urls = ['https://www.doutula.com/photo/list/?page={}'.format(i) for i in range(1, 20)]
2.进入开发者模式分析网页结构,能够看到以下结构。右击复制一下xpath地址便可获得所有的表情所在的a标签内容。a[1]表示第一个a,去掉[1]就是所有的a。
//*[@id="pic-detail"]/div/div[1]/div[2]/a
值得注意的是这里的表情有两种:一个jpg,一个gif动图。若是获取图片地址时只抓取a标签下面第一个img的src就会出错,因此咱们要抓取img中的含有data-original的值。这里a标签下面还一个p标签是图片简介,咱们也抓取下来做为图片文件的名称。
图片的链接是 'http:' + content.xpath('//img/@data-original') 图片的名称是 content.xpath('//p/text()')
完整代码地址 github.com/rieuse/learnPython
1.首先使用命令行工具输入代码建立一个新的Scrapy项目,以后建立一个爬虫。
scrapy startproject ScrapyDoutu cd ScrapyDoutu\ScrapyDoutu\spiders scrapy genspider doutula doutula.com
2.打开Doutu文件夹中的items.py,改成如下代码,定义咱们爬取的项目。
import scrapy class DoutuItem(scrapy.Item): img_url = scrapy.Field() name = scrapy.Field()
3.打开spiders文件夹中的doutula.py,改成如下代码,这个是爬虫主程序。
# -*- coding: utf-8 -*- import os import scrapy import requests from ScrapyDoutu.items import DoutuItems class Doutu(scrapy.Spider): name = "doutu" allowed_domains = ["doutula.com", "sinaimg.cn"] start_urls = ['https://www.doutula.com/photo/list/?page={}'.format(i) for i in range(1, 40)] # 咱们暂且爬取40页图片 def parse(self, response): i = 0 for content in response.xpath('//*[@id="pic-detail"]/div/div[1]/div[2]/a'): i += 1 item = DoutuItems() item['img_url'] = 'http:' + content.xpath('//img/@data-original').extract()[i] item['name'] = content.xpath('//p/text()').extract()[i] try: if not os.path.exists('doutu'): os.makedirs('doutu') r = requests.get(item['img_url']) filename = 'doutu\\{}'.format(item['name']) + item['img_url'][-4:] with open(filename, 'wb') as fo: fo.write(r.content) except: print('Error') yield item
3.这里面有不少值得注意的部分:
content.xpath('//img/@data-original').extract()[i]
中extract()用来返回一个list(就是系统自带的那个) 里面是一些你提取的内容,[i]是结合前面的i的循环每次获取下一个标签内容,若是不这样设置,就会把所有的标签内容放入一个字典的值中。filename = 'doutu\{}'.format(item['name']) + item['img_url'][-4:]
是用来获取图片的名称,最后item['img_url'][-4:]是获取图片地址的最后四位这样就能够保证不一样的文件格式使用各自的后缀。4.配置settings.py,若是想抓取快一点CONCURRENT_REQUESTS设置大一些,DOWNLOAD_DELAY设置小一些,或者为0.
# -*- coding: utf-8 -*- BOT_NAME = 'ScrapyDoutu' SPIDER_MODULES = ['ScrapyDoutu.spiders'] NEWSPIDER_MODULE = 'ScrapyDoutu.spiders' DOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, 'ScrapyDoutu.middlewares.RotateUserAgentMiddleware': 400, } ROBOTSTXT_OBEY = False # 不遵循网站的robots.txt策略 CONCURRENT_REQUESTS = 16 #Scrapy downloader 并发请求(concurrent requests)的最大值 DOWNLOAD_DELAY = 0.2 # 下载同一个网站页面前等待的时间,能够用来限制爬取速度减轻服务器压力。 COOKIES_ENABLED = False # 关闭cookies
5.配置middleware.py配合settings中的UA设置能够在下载中随机选择UA有必定的反ban效果,在原有代码基础上加入下面代码。这里的user_agent_list能够加入更多。
import random from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware class RotateUserAgentMiddleware(UserAgentMiddleware): def __init__(self, user_agent=''): self.user_agent = user_agent def process_request(self, request, spider): ua = random.choice(self.user_agent_list) if ua: print(ua) request.headers.setdefault('User-Agent', ua) user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24" ]
6.到如今为止,代码都已经完成了。那么开始执行吧!scrapy crawl doutu
以后能够看到一边下载,一边修改User Agent。
学习使用Scrapy遇到不少坑,可是强大的搜索系统不会让我感受孤单。因此感受Scrapy仍是很强大的也很意思,后面继续学习Scrapy的其余方面内容。源码加群
学习过程当中遇到什么问题或者想获取学习资源的话,欢迎加入学习交流群626062078,咱们一块儿学Python!