返回介绍

11.4 项目实战:爬取京东商城中的书籍信息

发布于 2024-02-05 21:13:20 字数 5072 浏览 0 评论 0 收藏 0

11.4.1 项目需求

爬取京东商城中所有Python书籍的名字和价格信息。

11.4.2 页面分析

图11-4所示为在京东网站(http://www.jd.com)的书籍分类下搜索Python关键字得到的页面。

图11-4

结果有很多页,在每一个书籍列表页面中可以数出有60本书,但我们在scrapy shell中爬取该页面时遇到了问题,仅在页面中找到了30本书,少了30本,代码如下:

$ scrapy shell
...
>>> url = 'https://search.jd.com/Search?keyword=python&enc=utf-8&book=y&wq=python'
>>> fetch(url)
...
>>> len(response.css('ul.gl-warp > li'))
30

原来页面中的60本书不是同时加载的,开始只有30本书,当我们使用鼠标滚轮滚动到页面下方某位置时,后30本书才由JavaScript脚本加载,通过实验可以验证这个说法,实验流程如下:

(1)页面刚加载时,在Chrome开发者工具的console中用jQuery代码查看当前有多少本书,此时为30。

(2)之后滚动鼠标滚轮到某一位置时,可以看到JavaScript发送HTTP请求和服务器交互(XHR)。

(3)然后用jQuery代码查看当前有多少本书,已经变成了60,如图11-5所示。

图11-5

既然如此,爬取这个页面时,可以先执行一段JavaScript代码,将滚动条拖到页面下方某位置,触发加载后30本书的事件,在开发者工具的console中进行实验,用document.getElementsByXXX方法随意选中页面下方的某元素,比如“下一页”按钮所在的<div>元素,然后在该元素对象上调用scrollIntoView(true)完成拖曳动作,此时查看书籍数量,变成了60,这个解决方案是可行的。图11-6所示为实验过程。

爬取一个页面的问题解决了,再来研究如何从页面中找到下一页的url地址。

图11-6

如图11-7所示,下一页链接的href属性并不是一个url,而在其onclick属性中包含了一条JavaScript代码,单击“下一页”按钮时会调用函数SEARCH.page(n, true)。虽然可以用Splash执行函数来跳转到下一页,但还是很麻烦,经观察发现,每个页面url的差异仅在于page参数不同,第一页page=1,第2页page=3,第3页page=5……以2递增,并且页面中还包含商品总数信息。因此,我们可以推算出所有页面的url。

图11-7

11.4.3 编码实现

首先,在splash_examples项目目录下使用scrapy genspider命令创建Spider类:

scrapy genspider jd_book search.jd.com

经上述分析,在爬取每一个书籍列表页面时都需要执行一段JavaScript代码,以让全部书籍加载,因此选用execute端点完成该任务,实现JDBookSpider代码如下:

# -*- coding: utf-8 -*-
import scrapy
from scrapy import Request
from scrapy_splash import SplashRequest

lua_script = '''
function main(splash)
 splash:go(splash.args.url)
 splash:wait(2)
 splash:runjs("document.getElementsByClassName('page')[0].scrollIntoView(true)")
 splash:wait(2)
 return splash:html()
end
'''

class JDBookSpider(scrapy.Spider):
 name = "jd_book"
 allowed_domains = ["search.jd.com"]
 base_url = 'https://search.jd.com/Search?keyword=python&enc=utf-8&book=y&wq=python'

 def start_requests(self):
  # 请求第一页,无须js渲染
  yield Request(self.base_url, callback=self.parse_urls, dont_filter=True)

 def parse_urls(self, response):
  # 获取商品总数,计算出总页数
  total = int(response.css('span#J_resCount::text').extract_first())
  pageNum = total // 60 + (1 if total % 60 else 0)
  # 构造每页的url,向Splash的execute 端点发送请求
  foriin range(pageNum):
    url = '%s&page=%s' % (self.base_url, 2 * i + 1)
    yield SplashRequest(url,
      endpoint='execute',
      args={'lua_source': lua_script},
      cache_args=['lua_source'])

def parse(self, response):
 # 获取一个页面中每本书的名字和价格
 for sel in response.css('ul.gl-warp.clearfix > li.gl-item'):
  yield {
    'name': sel.css('div.p-name').xpath('string(.//em)').extract_first(),
    'price': sel.css('div.p-price i::text').extract_first(),
  }

解释上述代码如下:

start_requests方法

start_requests提交对第一个页面的请求,这个页面不需要渲染,因为我们只想从中获取页面总数,使用scrapy.Request提交请求,并指定parse_urls作为解析函数。

parse_urls方法

从第一个页面中提取商品总数,用其计算页面总数,之后按照前面分析出的页面url规律构造每一个页面的url。这些页面都是需要渲染的,使用SplashRequest提交请求,除了渲染页面以外,还需要执行一段JavaScript代码(为了加载后30本书),因此使用Splash的execute端点将endpoint参数置为'execute'。通过args参数的lua_source字段传递我们要执行的lua脚本,由于爬取每个页面时都要执行该脚本,因此可以使用cache_args参数将该脚本缓存到Splash服务器。

parse方法

一个页面中提取60本书的名字和价格信息,相关内容大家早已熟悉,不再赘述。

lua_script字符串

自定义的lua脚本,其中的逻辑很简单:

打开页面→等待渲染→执行js触发数据加载(后30本书)→等待渲染→返回html。

另外,京东服务器程序会对请求头部中的User-Agent字段进行检测,因此需要在配置文件settings.py中设置USER_AGENT,伪装成常规浏览器:

# 伪装成常规浏览器
USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)'

编码和配置的工作已经完成了,运行爬虫并观察结果:

$ scrapy crawl jd_book -o books.csv
...
$ cat -n books.scv
  1  name,price
  2  教孩子学编程 Python语言版,59.00
  3  Python机器学习 预测分析核心算法,46.90
  4  Python机器学习 预测分析核心算法 9787115433732 [美] Michael,52.44
  5  Python数据分析实战 9787115432209,39.50
  6  数据科学实战手册 R+Python 9787115426758,39.50
  7  Python编程 从入门到实践,89.00
  8  Python可以这样学,69.00
  9  Python游戏编程快速上手,47.20
 10  Python性能分析与优化,45.00
 ...
  2932  Python语言在Abaqus 中的应用(附CD-ROM光盘1 张),38.40
  2933  Python绝技 运用Python成为*级黑客 运用Python成为 级黑客 书籍,46.50
  2934  趣学Python编程,42.70
  2935  零基础学Python(图文版),65.50
  2936  Python程序设计入门到实战,65.50
  2937  计算机科学丛书:Python语言程序设计,74.60
  2938  面向ArcGIS的Python脚本编程,41.00
  2939  Python算法教程 书籍,40.60
  2940  Python基础教程+利用Python进行数据分析 Python学习套装 共两册,136.20
  2941  包邮 量化投资 以Python 为工具 Python语言处理数据Python金融 量化投,65.80

结果显示,我们成功爬取到了2940本书籍的信息。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文