内容简介:超级易懂爬虫系列之使用scrapy框架爬取妹纸图
在前面一节中带领大家了解了scrapy框架的基本架构与使用,且与前面我们自己写的简单的架构进行了比较,让大家能够很容易明白这个框架的数据流的流程。然后带领大家爬取了一个页面的妹纸图让大家更容易上手,接下来就带领大家正式使用scrapy框架爬取全部页面的妹纸图,为了心仪的妹纸一定要学会哦,哈哈哈.
在前面一节中我们说过scrapy框架自动帮我们创建的工程包括一下几个板块:
- spider:这个是需要我们自定义实现的spider组件,主要是重写其parse函数来解析传进来的Response对象
- items:用来定义我们需要解析的数据的字段,如为例爬取妹纸图,我们需要知道妹纸图的下载地址,因此可以定义一个img_src字段用来表示妹纸图的下载地址
- pipelines:用来处理数据,不需要继承自scrapy框架类,但需要我们在setting.py中进行配置说明,然后重写其def process_item(self, item, spider)函数,在改函数中对传入的item数据对象进行处理
- settings 整个工程的配置文件,如果我们需要使用pipelines模块,需要在改文件中打开pipelines配置代码,即去掉框架自动生成的注释
那么当我们要爬取当前页面相关联的全部页面很显然需要修改的是spider组件中的代码,在parse函数回调时我们不仅需要获取妹纸图的下载地址,同样也需要获取相关联的url,在前面也讲过,我们需要使用Request对象来向scrapy引擎传递下一个请求,同时在Request对象中指定回调函数,代码如下:
# -*- coding: utf-8 -*- import re import scrapy from bs4 import BeautifulSoup from scrapy import Request from scrapy_study.items import ImageItem #定义spider组件,继承自scrapy.Spider class Spider(scrapy.Spider): print 'enter spider' name = "spider_girl" allowed_domains = ["iyangzi.com"] start_urls = ["http://iyangzi.com/?p=21"] #指定需要爬取的起始url # 用来去重的集合,首先将起始网址添加进去 crawed_urls = {"http://iyangzi.com/?p=21"} #只需要重写该函数即可,框架会自动回调该函数 def parse(self, response): print 'start parse' soup = BeautifulSoup(response.text, 'html.parser', from_encoding='utf-8') all_img = soup.find('div', class_='post-content').find_all('img') for img in all_img: src = img['src'] item=ImageItem() #实例化item对象,该对象是我们在items.py中定义的 item['img_src']=src yield item #找出当前页面中所有的符合规则的url,使用正则表达式进行过滤 urls = soup.find_all('a', href=re.compile(r"http://iyangzi.com/\?p=\d+$")) for url in urls: next_url=url['href'] if next_url not in self.crawed_urls:#去除重复url self.crawed_urls.add(next_url) print next_url yield Request(next_url,self.parse) #返回待爬取的Request请求给引擎
代码注释很详细,相信大家都看得懂,主要就是在上一节的spider.py模块中添加了爬取全部页面的代码,即在parse函数中返回Request对象,在该对象中指定下一个带爬取的url和回调函数即可。可以看到和上一节代码不同的是我们使用的不是return语句,而是yield,关于该表达式,简单的说一下其作用就是返回一个表达式,但和return不同的是,包含yield的函数已经不在是一个函数,而是一个可迭代的生成器,因此返回后不会结束该代码,而是类似与操作系统中的中断的作用,yield返回之后,程序的代码中变量的值会在此保存下来,待执行下一次迭代(当包含yield表达式时,该函数就是一个可迭代的生成器)时会从该中断语句处开始执行。关于yield的更多细节及请大家自行百度了解。
另一个需要注意的是,我们同样需要进行url去重,即定义一个集合保存需要爬取的url,然后如果新出现的url已经在该crawed_urls集合中,那么就不需要添加进去,如果不在则需要添加进去,然后返回Request对象。具体细节大家可以仔细的看代码,注释很详细。
当然如果某些网址需要使用设置header,cookies才可以访问的话,我们就不能够使用上述的代码了,因为使用start_urls的方式实质上是框架自动帮助我们发送了Request请求,但是该请求不带headers,cookies等参数,因此我们需要自己处理初始的Reques请求,此时我们只需要重写start_requests(self)函数即可,代码如下:
#设置自己的cookies cookies = {} #设置自己的headers headers = { 'Connection': 'keep - alive', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36' } #重写该函数,在该函数中返回Request对象,可以设置cookies,headers参数 def start_requests(self): yield Request(self.start_urls[0],callback=self.parse, headers=self.headers)
首先设置cookies和headers,然后重写start_requests(self)函数,在该函数中返回Request对象时指定cookies或者headers参数。完整的spider模块代码如下:
# -*- coding: utf-8 -*- import re import scrapy from bs4 import BeautifulSoup from scrapy import Request from scrapy_study.items import ImageItem #定义spider组件,继承自scrapy.Spider class Spider(scrapy.Spider): print 'enter spider' name = "spider_girl" allowed_domains = ["iyangzi.com"] start_urls = ["http://iyangzi.com/?p=21"] #指定需要爬取的起始url # 用来去重的集合,首先将起始网址添加进去 crawed_urls = {"http://iyangzi.com/?p=21"} #设置自己的cookies cookies = {} #设置自己的headers headers = { 'Connection': 'keep - alive', 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36' } #重写该函数,在该函数中返回Request对象,可以设置cookies,headers参数 def start_requests(self): yield Request(self.start_urls[0],callback=self.parse, headers=self.headers) #只需要重写该函数即可,框架会自动回调该函数 def parse(self, response): print 'start parse' soup = BeautifulSoup(response.text, 'html.parser', from_encoding='utf-8') all_img = soup.find('div', class_='post-content').find_all('img') for img in all_img: src = img['src'] item=ImageItem() #实例化item对象,该对象是我们在items.py中定义的 item['img_src']=src yield item #找出当前页面中所有的符合规则的url,使用正则表达式进行过滤 urls = soup.find_all('a', href=re.compile(r"http://iyangzi.com/\?p=\d+$")) for url in urls: next_url=url['href'] if next_url not in self.crawed_urls:#去除重复url self.crawed_urls.add(next_url) print next_url yield Request(next_url,self.parse) #返回待爬取的Request请求给引擎
其余模块的代码不需要改动,然后我们运行程序,可以看到在磁盘的C:\Users\htq\Desktop\girl_目录下已经为我们自动保存好了全部页面的妹纸图哦,如图:
好了,爬取全部页面妹纸图的程序就写好了,细心的小伙伴可以发现下载下来的图片的顺序和我们之前不用框架而是自己写的程序下载下来的顺序不一致,可以明显的感觉到很多页面的图片是交替出现的,这是因为scrapy框架使用了异步多线程的方式,因此图片的下载和爬取不是按照一个页面下载完成再去下载另一个页面的图片,而是爬取页面和图片下载交替进行,因此当前正在下载该页面的第一张妹纸图,下一秒可能就爬取到了另一个url下载该页面的第一张妹纸图,因此可以明显感觉到使用scrapy框架的下载速度要快得多,这也是使用框架的好处之一,可以显著的提高程序运行效率。
更多关于爬虫的干货,请继续关注超级易懂爬虫系列!
注:本文首次发表于www.huqi.tk,谢绝转载,如需转载,请注明出处:www.huqi.tk
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 超级易懂爬虫系列之爬虫框架scrapy
- 超级易懂爬虫系列之爬虫简单的架构
- Node 爬虫入门教程,简单易懂
- 超级易懂爬虫系列之使用scrapy爬取动态网页
- 超级易懂爬虫系列之使用scrapy爬取动态网页
- SVM 原理详解,通俗易懂
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
代码里的世界观——通往架构师之路
余叶 / 人民邮电出版社 / 2018-11 / 59.00元
本书分为两大部分,第一部分讲述程序员在编写程序和组织代码时遇到的很多通用概念和共同问题,比如程序里的基本元素,如何面向对象,如何面向抽象编程,什么是耦合,如何进行单元测试等。第二部分讲述程序员在编写代码时都会遇到的思考和选择,比如程序员的两种工作模式,如何坚持技术成长,程序员的组织生产方法,程序员的职业生涯规划等。一起来看看 《代码里的世界观——通往架构师之路》 这本书的介绍吧!