Python Scrapy实战:京东商城数据爬取进阶教程

云舒
云舒
发布时间:2026-10-13| 5人浏览过
原创

本文深入讲解使用Python Scrapy框架爬取京东商城的进阶技巧。内容涵盖构造奇数页请求、解析首屏数据、处理Ajax异步加载的后半部分商品信息,以及通过Meta传递参数。同时提供断点续爬、下载延迟、随机延迟、忽略Robots协议及并发控制等settings.py配置技巧,帮助开发者高效获取商品详情并避免被封禁。

前言

在之前的文章中,我们已经介绍了如何获取链接和参数,具体细节可参考《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是一个文件的名字。
  • 设置下载延迟以防止被屏蔽:DOWNLOAD_DELAY = 2用于设置每次请求的间隔时间;RANDOMIZE_DOWNLOAD_DELAY = True用于随机设置延迟时间,在设定时间的0.5到1.5倍之间,这样可以更有效地防止被屏蔽,通常是配套使用的。
  • ROBOTSTXT_OBEY = False:这里表示不遵循robots.txt文件,默认值为True表示遵循,这里将其改为False。
  • CONCURRENT_REQUESTS:设置最大请求数,默认值为16,我们可以根据自己电脑的配置改大一些,以加快请求速度。

总结

以上就是本文的全部内容,希望本文的内容对大家学习或使用Python能带来一定的帮助。如果有疑问,大家可以留言交流,谢谢大家对本站的支持。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。