利用scrapy框架爬取并下载天堂图片网的图片和数据
2018-03-01 18:55
399 查看
1. 通过命令创建项目
scrapy startproject IvskySpider
2. 用pycharm打开项目
3. 通过命令创建爬虫(Terminal中输入以下命令)
scrapy genspider ivsky ivsky.com
4. 配置settings
robots_obey=False
Download_delay=0.5
Cookie_enable=False
5. 在middlewares.py文件中:自定义UserAgentMiddleWare
法一:
可以直接粘现成的
法二:
或者自己通过研究源码实现
6. ivsky.py文件中,开始解析数据
1) 先大致规划一下需要几个函数
2) 函数1跳转到函数2使用 yield scrapy.Request(url,callback,meta,dont_filter)
具体代码如下:
item中数据封装的代码为:
9.useragent相关问题
用charles抓包我们会发现UserAgent并不是我们想要的结果,因此需要,自定义获取useragent函数
但是,结果显示的确实系统的UserAgent,我们可以在settings.py文件中做以下处理,优先使用自定义的useragent
useragent:
scrapy startproject IvskySpider
2. 用pycharm打开项目
3. 通过命令创建爬虫(Terminal中输入以下命令)
scrapy genspider ivsky ivsky.com
4. 配置settings
robots_obey=False
Download_delay=0.5
Cookie_enable=False
5. 在middlewares.py文件中:自定义UserAgentMiddleWare
法一:
可以直接粘现成的
from fake_useragent import UserAgent class UserAgentMiddleware(object): """This middleware allows spiders to override the user_agent""" def __init__(self): self.user_agent = UserAgent() @classmethod def from_crawler(cls, crawler): o = cls() # crawler.signals.connect(o.spider_opened, signal=signals.spider_opened) return o # 这个函数不能删,否则会报错 def spider_opened(self, spider): # self.user_agent = getattr(spider, 'user_agent', self.user_agent) pass def process_request(self, request, spider): if self.user_agent: # b 转换为二进制,不能改 request.headers.setdefault(b'User-Agent', self.user_agent.random)
法二:
或者自己通过研究源码实现
6. ivsky.py文件中,开始解析数据
1) 先大致规划一下需要几个函数
2) 函数1跳转到函数2使用 yield scrapy.Request(url,callback,meta,dont_filter)
具体代码如下:
# -*- coding: utf-8 -*- import scrapy # scrapy框架自带一种解析方式,基于lxml 所以不用导入etree # form lxml import etree # 创建文件夹 import os # 下载图片 import requests from ..items import ImgInfoItem class IvskySpider(scrapy.Spider): name = 'ivsky' allowed_domains = ['ivsky.com'] # start_url 可以替换为自己需要的网址 start_urls = ['http://www.ivsky.com/tupian/ziranfengguang/'] # 只有parse这个函数是自动调用的 def parse(self, response): # 这里的response跟之前我们写的不太一样,没有content属性 # print(response.text) # 调用函数(法一) # self.parse_big_category() # 调用函数(法二) """ 参数1:url,爬取的网址 参数2:callback回调,当网页下载好以后传给谁去解析 参数3:method,默认get headers cookies meta """ yield scrapy.Request( url=response.url, # 把url的值传递给调用的parse_big_category函数 # 注意parse_big_category后面没有括号!!! callback=self.parse_big_category, # scrapy会自动过滤已经爬过的文件,因此设置为True,表示不过滤 dont_filter=True, ) def parse_big_category(self, response): """ 函数注释用三个双引号 解析网页大分类 :param response: :return: """ # 以下三种方式都可以,推荐使用xpath # response.selector.xpath() 简写成 response.xpath() # response.selector.css() # response.selector.re() big_a_list = response.xpath("//ul[@class='tpmenu']/li/a") for big_a in big_a_list[1:]: # extract_first :将列表中的元素转换为字符串并且取第0个,如果取不到返回默认值 big_title = big_a.xpath("text()").extract_first("没有标题") big_href = big_a.xpath("@href").extract_first("没有地址") big_href = "http://www.ivsky.com" + big_href # print(big_title, big_href) yield scrapy.Request( url=big_href, callback=self.parse_small_category, # meta 1.用于传递数据 2.类型为字典 meta={ "big_title": big_title, }, dont_filter=True, ) # 解析小分类 def parse_small_category(self, response): """ 解析网页小分类 response指的是big_href :param response: :return: """ # 将big_title传递进来 # 法一 # big_title = response.meta.get("big_title") small_a_list = response.xpath("//div[@class='sline']/div/a") for small_a in small_a_list: # extract_first :将列表中的元素转换为字符串并且取第0个,如果取不到返回默认值 small_title = small_a.xpath("text()").extract_first("没有标题") # 法二 response.meta['small_title'] = small_title small_href = small_a.xpath("@href").extract_first("没有地址") small_href = "http://www.ivsky.com" + small_href # print(small_title, small_href) yield scrapy.Request( url=small_href, callback=self.parse_img_list, # 法一 # meta={ # "big_title": big_title, # "small_title": small_title, # } # 法二 meta=response.meta, dont_filter=True, ) def parse_img_list(self, response): """ 解析图片缩略图 :param response: response指的是small_href :return: """ img_a_list = response.xpath("//ul[@class='pli']/li/div/a") for img_a in img_a_list: detail_href = img_a.xpath("@href").extract_first("没有详细地址") detail_href = "http://www.ivsky.com" + detail_href thumb_src = img_a.xpath("img/@src").extract_first("没有图片地址") thumb_alt = img_a.xpath("img/@alt").extract_first("没有图片名称") # print(thumb_alt, thumb_src) response.meta['thumb_src'] = thumb_src response.meta['thumb_alt'] = thumb_alt yield scrapy.Request( url=detail_href, callback=self.parse_img_detail, meta=response.meta, dont_filter=True, ) def parse_img_detail(self, response): """ 解析图片详情 :param response: :return: """ # 在最后一个函数中,把所有的数据传递过来 big_title = response.meta.get("big_title").strip() small_title = response.meta.get("small_title").strip() thumb_src = response.meta.get("thumb_src").strip() thumb_alt = response.meta.get("thumb_alt").strip() img_detail_src = response.xpath("//img[@id='imgis']/@src").extract_first("没有图片详情地址") # print(img_detail_src) path = "big/" + big_title + '/' + small_title + '/' + thumb_alt if not os.path.exists(path): os.makedirs(path) picture_name = thumb_src.split('/')[-1] thumb_name = "缩略图" + picture_name detail_name = "高清图" + picture_name # 定义对象 item = ImgInfoItem() # 将数据封装到item中 item["big_title"] = big_title item["small_title"] = small_title item["thumb_src"] = thumb_src item["thumb_alt"] = thumb_alt item["img_detail_src"] = img_detail_src item["path"] = path # 类似于return 如果用return,效果没问题,但是return以后的代码不执行 # 但yield可返回数据,并且之后的代码照样执行 yield item with open(path+"/"+thumb_name, "wb") as f: # thumb_src 缩略图网址 img_response = requests.get(thumb_src) f.write(img_response.content) with open(path+"/"+detail_name, "wb") as f: # img_detail_src 高清图网址 img_response = requests.get(img_detail_src) f.write(img_response.content) """ 1.进程: 2.线程:与进程相关,一个进程相当于一个人,一个线程相当于一个脑子 4000 默认线程只有一个,叫主线程 一个线程每次只能做一件事,例如:迅雷 同时下载任务量为1 多个线程可以“同时”做多件事,例如:迅雷同时下载的任务量为5,可以显著提高下载效率 注意:线程不是越多越好,(10个左右)例如:火车站卖票 窗口越多成本越高,速度越快 注意:Scrapy默认使用多线程 注意:python没有多线程 3.协成:负责协助线程的资源切换 """7. 将数据封装到items(用于存储数据),记得在ivsky.py文件中yield item
item中数据封装的代码为:
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # https://doc.scrapy.org/en/latest/topics/items.html import scrapy class IvskyspiderItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() pass class ImgInfoItem(scrapy.Item): """ item用于组装爬虫数据 里面的字段根据实际情况定义即可,一般字段名和变量名保持一致 item封装后的数据 可以经过管道做一些数据 """ big_title = scrapy.Field() small_title = scrapy.Field() thumb_src = scrapy.Field() thumb_alt = scrapy.Field() img_detail_src = scrapy.Field() path = scrapy.Field()8. 自定义pipelines将数据存储到数据库/文件中
9.useragent相关问题
用charles抓包我们会发现UserAgent并不是我们想要的结果,因此需要,自定义获取useragent函数
但是,结果显示的确实系统的UserAgent,我们可以在settings.py文件中做以下处理,优先使用自定义的useragent
DOWNLOADER_MIDDLEWARES = { # 改为自己在Middleware中添加的获取useragent类 'IvskySpider.middlewares.UserAgentMiddleware': 543, # 优先选择系统的useragent,下面的一行代码设置禁用系统的useragent 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None # 数字表示优先级 越小越先执行 如果填为none,表示不执行 }10.运行结果如下:
useragent:
相关文章推荐
- Scrapy框架之利用ImagesPipeline下载图片
- 玩转数据系列:利用阿里云机器学习在深度学习框架下实现智能图片分类
- 爬虫 scrapy 框架学习 2. Scrapy框架业务逻辑的理解 + 爬虫案例 下载指定网站所有图片
- JAVA:利用Apache poi在服务器传输带有数据和图片的excel的数据流至浏览器供其下载至本地
- Scrapy框架学习 - 使用内置的ImagesPipeline下载图片
- 数据可视化 三步走(一):数据采集与存储,利用python爬虫框架scrapy爬取网络数据并存储
- 利用NSOperation进行异步图片下载——设置UITabView数据,图片下载,占位图。解决异步下载和Cell重用造成的图片设置混乱。和多次重复下载的问题
- 利用第三方开源框架 PullToRefreshListView 实现下拉刷新(从网上下载图片)
- Scrapy框架下载一个意大利网站所有植物图片并重命名归科
- Android开发利用Volley框架下载和缓存网络图片
- scrapy框架下载图片
- scrapy框架图片下载注意点
- Python:使用Scrapy框架的ImagesPipeline下载图片如何保持原图片名称呢?
- 利用开源框架Volley来下载文本和图片。
- Scrapy框架学习 - 扩展内置的ImagesPipeline实现图片下载
- Android开发利用Volley框架下载和缓存网络图片
- 利用python scrapy 框架抓取豆瓣小组数据
- 利用javascript从数据库取数据来实现CSDN首页图片的切换效果(新增下载地址)
- python爬虫框架scrapy学习图片下载
- javaWeb项目springMVC框架下利用ITextpdf 工具打印PDF文件的方法(打印表单、插入图片)