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和IPython中使用Docker
Apr 28 Python
在java中如何定义一个抽象属性示例详解
Aug 18 Python
目前最全的python的就业方向
Jun 05 Python
Python使用指定端口进行http请求的例子
Jul 25 Python
django删除表重建的实现方法
Aug 28 Python
使用Python脚本zabbix自定义key监控oracle连接状态
Aug 28 Python
Python性能分析工具Profile使用实例
Nov 19 Python
使用Python画出小人发射爱心的代码
Nov 23 Python
Python实现转换图片背景颜色代码
Apr 30 Python
Pandas实现一列数据分隔为两列
May 18 Python
python的help函数如何使用
Jun 11 Python
Python3爬虫关于识别点触点选验证码的实例讲解
Jul 30 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
JAVA/JSP学习系列之四
2006/10/09 PHP
php学习 函数 课件
2008/06/15 PHP
thinkphp微信开之安全模式消息加密解密不成功的解决办法
2015/12/02 PHP
JavaScript高级程序设计
2006/12/29 Javascript
javascript 哈希表(hashtable)的简单实现
2010/01/20 Javascript
JavaScript Accessor实现说明
2010/12/06 Javascript
jQuery EasyUI API 中文文档 - Menu菜单
2011/10/03 Javascript
jquery Mobile入门—多页面切换示例学习
2013/01/08 Javascript
javascript 闭包详解
2015/02/15 Javascript
js小数运算出现多位小数如何解决
2015/10/08 Javascript
JavaScript操作 url 中 search 部分方法函数
2016/06/15 Javascript
jQuery+正则+文本框只能输入数字的实现方法
2016/10/07 Javascript
JS封装的三级联动菜单(使用时只需要一行js代码)
2016/10/24 Javascript
jquery代码规范让代码越来越好看
2017/02/03 Javascript
探索webpack模块及webpack3新特性
2017/09/18 Javascript
Node.js 中使用 async 函数的方法
2017/11/20 Javascript
小程序实现多选框功能
2018/10/30 Javascript
[02:59]2014DOTA2西雅图国际邀请赛 圆满落幕中国夺冠
2014/07/23 DOTA
在Django框架中伪造捕捉到的URLconf值的方法
2015/07/18 Python
Python正则表达式如何进行字符串替换实例
2016/12/28 Python
python的文件操作方法汇总
2017/11/10 Python
Python进阶学习之特殊方法实例详析
2017/12/01 Python
学习Python3 Dlib19.7进行人脸面部识别
2018/01/24 Python
Python实现图片添加文字
2019/11/26 Python
执行Python程序时模块报错问题
2020/03/26 Python
python 安装impala包步骤
2020/03/28 Python
PyCharm2020.3.2安装超详细教程
2021/02/08 Python
信息技术专业个人自我评价
2013/12/11 职场文书
应用英语专业自荐信
2014/01/26 职场文书
家长建议怎么写
2014/05/15 职场文书
经营理念标语
2014/06/21 职场文书
淘宝好评语句大全
2014/12/31 职场文书
幼儿园门卫安全责任书
2015/05/08 职场文书
5分钟教你docker安装启动redis全教程(全新方式)
2021/05/29 Redis
5人制售《绝地求生》游戏外挂获利500多万元 被判刑
2022/03/31 其他游戏
SQL Server2019安装的详细步骤实战记录(亲测可用)
2022/06/10 SQL Server