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遍历类中所有成员的方法
Mar 18 Python
不要用强制方法杀掉python线程
Feb 26 Python
python flask实现分页效果
Jun 27 Python
Python标准模块--ContextManager上下文管理器的具体用法
Nov 27 Python
python 中的list和array的不同之处及转换问题
Mar 13 Python
python+opencv+caffe+摄像头做目标检测的实例代码
Aug 03 Python
浅谈python 读excel数值为浮点型的问题
Dec 25 Python
python pandas时序处理相关功能详解
Jul 03 Python
用python3 返回鼠标位置的实现方法(带界面)
Jul 05 Python
python time.sleep()是睡眠线程还是进程
Jul 09 Python
tensorflow 只恢复部分模型参数的实例
Jan 06 Python
Pycharm安装Qt Design快捷工具的详细教程
Nov 18 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的无限分类实现想法~
2007/01/02 PHP
php中的动态调用实例分析
2015/01/07 PHP
PHP实现加强版加密解密类实例
2015/07/29 PHP
一个非常实用的php文件上传类
2017/07/04 PHP
iframe 自适应高度[在IE6 IE7 FF下测试通过]
2009/04/13 Javascript
javascript的函数、创建对象、封装、属性和方法、继承
2011/03/10 Javascript
jquery实现输入框动态增减的实例代码
2013/07/14 Javascript
js中单引号与双引号冲突问题解决方法
2013/10/04 Javascript
减少访问DOM的次数提升javascript性能
2014/02/24 Javascript
JavaScript中三种异步上传文件方式
2016/03/06 Javascript
Bootstrap中的Panel和Table全面解析
2016/06/13 Javascript
9个让JavaScript调试更简单的Console命令
2016/11/14 Javascript
js操作浏览器的参数方法
2017/01/21 Javascript
第一次记录Bootstrap table学习笔记(1)
2017/05/18 Javascript
jQuery实现html双向绑定功能示例
2017/10/09 jQuery
微信小程序自定义弹窗实现详解(可通用)
2019/07/04 Javascript
js HTML DOM EventListener功能与用法实例分析
2020/04/27 Javascript
javascript实现支付宝滑块验证码效果
2020/07/24 Javascript
jQuery zTree如何改变指定节点文本样式
2020/10/16 jQuery
[48:26]VGJ.S vs infamous Supermajor 败者组 BO3 第二场 6.4
2018/06/05 DOTA
python中函数总结之装饰器闭包详解
2016/06/12 Python
Python爬虫获取整个站点中的所有外部链接代码示例
2017/12/26 Python
解决django后台管理界面添加中文内容乱码问题
2019/11/15 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
2020/03/10 Python
python 检测nginx服务邮件报警的脚本
2020/12/31 Python
主持人演讲稿范文
2013/12/28 职场文书
劳动实践课感言
2014/02/01 职场文书
七匹狼男装广告词
2014/03/21 职场文书
《每逢佳节倍思亲》教后反思
2014/04/19 职场文书
实习单位指导教师评语
2014/12/30 职场文书
关于颐和园的导游词
2015/01/30 职场文书
未中标通知书
2015/04/17 职场文书
电影复兴之路观后感
2015/06/02 职场文书
为自己工作观后感
2015/06/11 职场文书
感谢信的技巧及范例
2019/05/15 职场文书
用Python生成会跳舞的美女
2022/01/18 Python