先说一下什么是python的惰性计算
惰性计算(Lazy evaluation)是指仅仅在真正需要执行的时候才计算表达式的值。充分利用其特性可以带来很多便利。yield的功能类似于return,但是不同之处在于它返回的是生成器。
惰性计算的好处:
1.避免不必要的计算,带来性能的提升。
对于Python中的条件表达式 if x and y,在x为false的情况下y表达式的值将不再计算。而对于if x or y,当x的值为true的时候将直接返回,不再计算y的值。因此编程中可以利用该特性,在 and逻辑中,将小概率发生的条件放在前面或者在or逻辑中,将大概率发生的时间放在前面,有助于性能的提升。
2.节省空间,使得无线循环的数据结构成为可能。
Python中最经典的使用延迟计算的例子就是生成式表达器了,它尽在每次需要计算的时候才通过yield产生所需要的元素。
以下介绍用法
为什么说yield类似于return而与return大不相同呢,用我写的代码看一下yield在scrapy中的用法。
# 这是一个spider类
class XiaoChiSpider(scrapy.Spider):
name = 'xiaochi_spider'
start_urls = ['https://www.meishij.net/china-food/xiaochi/']
# 小吃的种类是很多种的,我在默认的parse解析方法中得到所有种类的地址,以此循环
# callback到prasecontent中,分别对具体的小吃种类进行爬取
def parse(self, response):
xiaochi_list = response.xpath(
"//div[@class='other_c listnav_con clearfix']//dl//dd//a//@href").extract()
# 种类循环
for xiaochi_url in xiaochi_list:
# 这里体现了yield的用法
# 可简单的把yield的作用理解为“抛出”,我把信息抛出,此时停止计算,等待prasecontent运算完成,继续执行yield的下一条代码,即遍历下一小吃种类
yield scrapy.Request(xiaochi_url, callback=self.prasecontent)
def prasecontent(self, response):
# 获取下一页的url
next_link = response.xpath("//div[@class='listtyle1_page']//a[@class='next']//@href").extract()
split_name = re.split('/', next_link[0])
cai_type = split_name[-2]+split_name[-3]
xiaochi_juti = response.xpath(
"//div[@class='main']//div[@class='listtyle1_list clearfix']//div[@class='listtyle1']//a")
for i_item in xiaochi_juti:
meishi_item = LiangCaiItem()
meishi_item['cai_name'] = i_item.xpath(".//div[@class='c1']//strong//text()").extract_first()
meishi_item['suoshu_type'] = i_item.xpath(
"//div[@class='other_c listnav_con clearfix']//dl//dd[@class='current']//text()").extract()[0]
try:
redu = i_item.xpath(".//div[@class='c1']//span[1]//text()").extract_first().split(' ')
meishi_item['cai_ReDu'] = redu[1]
except:
meishi_item['cai_ReDu'] = 'null'
try:
fenli = i_item.xpath(".//div[@class='c2']//li[@class='li2']//text()").extract_first().split(' / ')
meishi_item['cai_KouWei'] = fenli[1]
meishi_item['cai_ZuoFa'] = fenli[0]
except:
meishi_item['cai_KouWei'] = 'null'
meishi_item['cai_ZuoFa'] = 'null'
meishi_item['cai_HaoChu'] = i_item.xpath(".//strong[@class='gx']//text()").extract_first()
meishi_item['cai_picture_path'] = i_item.xpath(".//img//@src").extract_first()
meishi_item['cai_ZhiZuoRen'] = i_item.xpath(".//div[@class='c1']//em//text()").extract_first()
meishi_item['cai_BuZhou'] = i_item.xpath(".//@href").extract_first()
# 文件下载 保存的 调用
murl = meishi_item['cai_BuZhou']
html_file = DownloadMethod().download(murl)
# 创建相应文件
file_path = "C:/Users/ASUS/Desktop/Meishijie/"+cai_type+"/"
if not os.path.exists(file_path):
os.makedirs(file_path)
DownloadMethod().save(file_path, re.split('/', murl)[-1], html_file)
print("文件保存在:"+ file_path + re.split('/', murl)[-1])
print("下载完成-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
meishi_item['file_save_path'] = file_path + re.split('/', murl)[-1]
yield meishi_item
if next_link:
next_link = next_link[0]
yield scrapy.Request(next_link + "", callback=self.prasecontent) # prase后不加括号
如果yield改为return,那扔出一次信息之后,这段代码即停止执行且不再运行。
以上代码中还体现了,文件的下载与保存到指定路径(没有指定的路径时则新建)、scrapy爬虫的翻页等
关于scrapy框架的知识欢迎提问探讨。