python爬虫框架scrapy实战之爬取京东商城进阶篇


Posted in Python onApril 24, 2017

前言

之前的一篇文章已经讲过怎样获取链接,怎样获得参数了,详情请看python爬取京东商城普通篇,本文将详细介绍利用python爬虫框架scrapy如何爬取京东商城,下面话不多说了,来看看详细的介绍吧。

代码详解

1、首先应该构造请求,这里使用scrapy.Request,这个方法默认调用的是start_urls构造请求,如果要改变默认的请求,那么必须重载该方法,这个方法的返回值必须是一个可迭代的对象,一般是用yield返回。

代码如下:

def start_requests(self):
 for i in range(1,101):
 page=i*2-1 #这里是构造请求url的page,表示奇数
 url=self.start_url+str(page)
 yield scrapy.Request(url,meta={'search_page':page+1},callback=self.parse_url) #这里使用meta想回调函数传入数据,回调函数使用response.meta['search-page']接受数据

下面就是解析网页了,从上面看出这里的解析回调函数是parse_url,因此在此函数中解析网页。这里还是和上面说的一样,这个url得到的仅仅是前一半的信息,如果想要得到后一半的信息还有再次请求,这里还有注意的就是一个技巧:一般先解析出一个数据的数组,不急着取出第一个数,先要用if语句判断,因为如果得到的是[],那么直接取出[0]是会报错的,这只是一个避免报错的方法吧。

代码如下:

def parse_url(self,response):
 if response.status==200: #判断是否请求成功
 # print response.url
 pids = set() #这个集合用于过滤和保存得到的id,用于作为后面的ajax请求的url构成
 try:
 all_goods = response.xpath("//div[@id='J_goodsList']/ul/li") #首先得到所有衣服的整个框架,然后从中抽取每一个框架
 for goods in all_goods: #从中解析每一个
 # scrapy.shell.inspect_response(response,self) #这是一个调试的方法,这里会直接打开调试模式
 items = JdSpiderItem() #定义要抓取的数据
 img_url_src = goods.xpath("div/div[1]/a/img/@src").extract() # 如果不存在就是一个空数组[],因此不能在这里取[0]
 img_url_delay = goods.xpath(
  "div/div[1]/a/img/@data-lazy-img").extract() # 这个是没有加载出来的图片,这里不能写上数组取第一个[0]
 price = goods.xpath("div/div[3]/strong/i/text()").extract() #价格
 cloths_name = goods.xpath("div/div[4]/a/em/text()").extract()
 shop_id = goods.xpath("div/div[7]/@ data-shopid").extract()
 cloths_url = goods.xpath("div/div[1]/a/@href").extract()
 person_number = goods.xpath("div/div[5]/strong/a/text()").extract()
 pid = goods.xpath("@data-pid").extract()
 # product_id=goods.xpath("@data-sku").extract()
 if pid:
  pids.add(pid[0])
 if img_url_src: # 如果img_url_src存在
  print img_url_src[0]
  items['img_url'] = img_url_src[0]
 if img_url_delay: # 如果到了没有加载完成的图片,就取这个url
  print img_url_delay[0]
  items['img_url'] = img_url_delay[0] # 这里如果数组不是空的,就能写了
 if price:
  items['price'] = price[0]
 if cloths_name:
  items['cloths_name'] = cloths_name[0]
 if shop_id:
  items['shop_id'] = shop_id[0]
  shop_url = "https://mall.jd.com/index-" + str(shop_id[0]) + ".html"
  items['shop_url'] = shop_url
 if cloths_url:
  items['cloths_url'] = cloths_url[0]
 if person_number:
  items['person_number'] = person_number[0]
 # if product_id:
 # print "************************************csdjkvjfskvnk***********************"
 # print self.comments_url.format(str(product_id[0]),str(self.count))
 # yield scrapy.Request(url=self.comments_url.format(str(product_id[0]),str(self.count)),callback=self.comments)
 #yield scrapy.Request写在这里就是每解析一个键裤子就会调用回调函数一次
 yield items
 except Exception:
 print "********************************************ERROR**********************************************************************"
 yield scrapy.Request(url=self.search_url.format(str(response.meta['search_page']),",".join(pids)),callback=self.next_half_parse) #再次请求,这里是请求ajax加载的数据,必须放在这里,因为只有等到得到所有的pid才能构成这个请求,回调函数用于下面的解析

2、从上面代码的最后可以看出最后就是解析ajax加载的网页了,这里调用的next_half_parse函数,和解析前面一个网页一样,这里需要的注意的是,如果前面定义的数据没有搜索完毕是不能使用yield items的,必须将items通过meta传入下一个回调函数继续完善后才能yield items,这里就不需要了。

代码如下:

#分析异步加载的网页
 def next_half_parse(self,response):
 if response.status==200:
 print response.url
 items=JdSpiderItem()
 #scrapy.shell.inspect_response(response,self) #y用来调试的
 try:
 lis=response.xpath("//li[@class='gl-item']")
 for li in lis:
  cloths_url=li.xpath("div/div[1]/a/@href").extract()
  img_url_1=li.xpath("div/div[1]/a/img/@src").extract()
  img_url_2=li.xpath("div/div[1]/a/img/@data-lazy-img").extract()
  cloths_name=li.xpath("div/div[4]/a/em/text()").extract()
  price=li.xpath("div/div[3]/strong/i/text()").extract()
  shop_id=li.xpath("div/div[7]/@data-shopid").extract()
  person_number=li.xpath("div/div[5]/strong/a/text()").extract()
  if cloths_url:
  print cloths_url[0]
  items['cloths_url']=cloths_url[0]
  if img_url_1:
  print img_url_1[0]
  items['img_url']=img_url_1
  if img_url_2:
  print img_url_2[0]
  items['img_url']=img_url_2[0]
  if cloths_name:
  items['cloths_name']=cloths_name[0]
  if price:
  items['price']=price[0]
  if shop_id:
  items['shop_id']=shop_id[0]
  items['shop_url']="https://mall.jd.com/index-" + str(shop_id[0]) + ".html"
  if person_number:
  items['person_number']=person_number[0]
  yield items #又一次的生成,这里是完整的数据,因此可以yield items
 except Exception:
 print "**************************************************"

3、当然这里还用到了设置请求池,mysql存储,没有使用到ip代理,这个在我前面的博客中又讲到,这里就不再赘述了。

想看源代码的朋友请

小技巧

  • 人们会抱怨为什么自己的爬虫在中途断开就要重头开始爬,为什么不能从断开那里开始爬呢,这里提供一个方法:在配置文件settings.py中加入JOBDIR=file_name,这里的file_name是一个文件的名字
  • 设置下载延迟防止被ban:DOWNLOAD_DELAY = 2:设置每一次的间隔时间 RANDOMIZE_DOWNLOAD_DELAY = True:这个是随机设置延迟时间 在设置的时间的0.5-1.5倍之间,这样可以更有效的防止被ban,一般是配套使用的
  • ROBOTSTXT_OBEY = False :这里是表示不遵循robots.txt文件,默认是True表示遵循,这里将之改成False
  • CONCURRENT_REQUESTS :设置最大请求数,这里默认的时16,我们可以根据自己电脑的配置改的大一点来加快请求的速度

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者使用python能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
python实现k均值算法示例(k均值聚类算法)
Mar 16 Python
理解Python中的类与实例
Apr 27 Python
Python装饰器实现几类验证功能做法实例
May 18 Python
Python3利用Dlib实现摄像头实时人脸检测和平铺显示示例
Feb 21 Python
Python合并同一个文件夹下所有PDF文件的方法
Mar 11 Python
利用Python实现Shp格式向GeoJSON的转换方法
Jul 09 Python
将tensorflow.Variable中的某些元素取出组成一个新的矩阵示例
Jan 04 Python
浅谈Pycharm最有必要改的几个默认设置项
Feb 14 Python
Python实现常见的几种加密算法(MD5,SHA-1,HMAC,DES/AES,RSA和ECC)
May 09 Python
python eventlet绿化和patch原理
Nov 21 Python
Python实现批量自动整理文件
Mar 16 Python
基于Python编写简易版的天天跑酷游戏的示例代码
Mar 23 Python
python爬虫实战之爬取京东商城实例教程
Apr 24 #Python
python中urllib.unquote乱码的原因与解决方法
Apr 24 #Python
Python面向对象特殊成员
Apr 24 #Python
Python解惑之整数比较详解
Apr 24 #Python
Python解惑之True和False详解
Apr 24 #Python
Python新手入门最容易犯的错误总结
Apr 24 #Python
Python正则抓取新闻标题和链接的方法示例
Apr 24 #Python
You might like
php面向对象全攻略 (三)特殊的引用“$this”的使用
2009/09/30 PHP
PHP采集利器 Snoopy 试用心得
2011/07/03 PHP
PHP面向对象之旅:深入理解static变量与方法
2014/01/06 PHP
php代码审计比较有意思的例子
2014/05/07 PHP
PHP常用工具类大全附全部代码下载
2015/12/07 PHP
php实现倒计时效果
2015/12/19 PHP
PHP基于Redis消息队列实现发布微博的方法
2017/05/03 PHP
JS遮罩层效果 兼容ie firefox jQuery遮罩层
2010/07/26 Javascript
jQuery EasyUI API 中文文档 - TimeSpinner时间微调器
2011/10/23 Javascript
JavaScript判断对象是否为数组
2015/12/22 Javascript
jQuery实现图像旋转动画效果
2016/05/29 Javascript
JavaScript队列、优先队列与循环队列
2016/11/14 Javascript
JS中正则表达式要注意lastIndex属性
2017/08/08 Javascript
spirngmvc js传递复杂json参数到controller的实例
2018/03/29 Javascript
微信小程序 简易计算器实现代码实例
2019/09/02 Javascript
vue中@change兼容问题详解
2019/10/25 Javascript
微信小程序实现弹幕墙(祝福墙)
2020/11/18 Javascript
[38:41]2014 DOTA2国际邀请赛中国区预选赛 LGD VS CNB
2014/05/22 DOTA
[11:57]《一刀刀一天》第十七期:TI中国军团加油!
2014/05/26 DOTA
[57:59]完美世界DOTA2联赛循环赛 Ink Ice vs LBZS BO2第一场 11.05
2020/11/05 DOTA
在Python的Django框架中包装视图函数
2015/07/20 Python
Python标准库sched模块使用指南
2017/07/06 Python
Python输出由1,2,3,4组成的互不相同且无重复的三位数
2018/02/01 Python
TensorFlow利用saver保存和提取参数的实例
2018/07/26 Python
Python实现多态、协议和鸭子类型的代码详解
2019/05/05 Python
Python中的 sort 和 sorted的用法与区别
2019/08/10 Python
使用Python实现将多表分批次从数据库导出到Excel
2020/05/15 Python
详解python安装matplotlib库三种失败情况
2020/07/28 Python
利用css3径向渐变做一张优惠券的示例
2018/03/22 HTML / CSS
阿根廷网上配眼镜:SmartBuyGlasses阿根廷
2016/08/19 全球购物
英国著名的茶叶品牌:Whittard of Chelsea
2016/09/22 全球购物
Java文件和目录(IO)操作
2014/08/26 面试题
秘书岗位职责
2013/11/18 职场文书
两只小狮子教学反思
2014/02/05 职场文书
小学美术兴趣小组活动总结
2014/07/07 职场文书
2014年敬老院工作总结
2014/12/08 职场文书