一、概述

在上一篇文章中,链接如下:https://www.cnblogs.com/xiao987334176/p/13656055.html

已经介绍了如何使用Splash抓取javaScript动态渲染页面

这里做一下项目实战,以爬取京东商城商品冰淇淋为例吧

环境说明

操作系统:centos 7.6

docker版本:19.03.12

ip地址:192.168.0.10

说明:使用docker安装Splash服务

操作系统:windows 10

python版本:3.7.9

ip地址:192.168.0.9

说明:使用Pycharm开发工具,用于本地开发。

关于Splash的使用,参考上一篇文章,这里就不做说明了。

二、分析页面

打开京东商城,输入关键字:冰淇淋,滑动滚动条,我们发现随着滚动条向下滑动,越来越多的商品信息被刷新了,这说明该页面部分是ajax加载

注意:每一条商品信息,都是在<div class="gl-i-wrap"></div>里面的。

我们打开scrapy shell 爬取该页面,如下图:

scrapy shell "https://search.jd.com/Search?keyword=%E5%86%B0%E6%B7%87%E6%B7%8B&enc=utf-8"

输出:

...
[s]   view(response)    View response in a browser
>>>

注意:url不要用单引号,否则会报错。

接下来,输入以下命令,使用css选择器

>>> response.css('div.gl-i-wrap')
[<Selector xpath="descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '
), ' gl-i-wrap ')]"
...

返回了很多Selector 对象。

统计商品信息个数

>>> len(response.css('div.gl-i-wrap'))
30

得到返回结果发现只有30个冰淇凌的信息,而我们再页面中明明看见了60个冰淇凌信息,这是为什么呢?

答:这也说明了刚开始页面只用30个冰淇淋信息,而我们滑动滑块时,执行了js代码,并向后台发送了ajax请求,浏览器拿到数据后再进一步渲染出另外了30个信息

我们可以点击network选项卡再次确认:

鉴于此,我们就想出了一种解决方案:即用js代码模拟用户滑动滑块到底的行为再结合execute端点提供的js代码执行服务即可(小伙伴们让我们开始实践吧)

 注意:<div id="footer-2017"></div>就是页面底部了,因此,只需要滑动到底部即可。

首先:模拟用户行为

在console,输入以下命令:

e = document.getElementById("footer-2017")
e.scrollIntoView(true)

效果如下,就直接滑动到底部了。

参数解释:

scrollIntoView是一个与页面(容器)滚动相关的API(官方解释),该API只有boolean类型的参数能得到良好的支持(firefox 36+都支持)

参数为true时调用该函数,页面(或容器)发生滚动,使element的顶部与视图(容器)顶部对齐;

使用scrapy.Request

上面我们使用Request发送请求,观察结果只有30条。为什么呢?因为页面时动态加载的所有我们只收到了30个冰淇淋的信息。

所以这里,使用scrapy.Request发送请求,并使用execute 端点解决这个问题。

打开上一篇文章中的爬虫项目dynamic_page,使用Pycharm打开,并点开Terminal

输入dir,确保当前目录是dynamic_page

(crawler) E:\python_script\爬虫\dynamic_page>dir驱动器 E 中的卷是 file卷的序列号是 1607-A400E:\python_script\爬虫\dynamic_page 的目录2020/09/12  10:37    <DIR>          .
2020/09/12  10:37    <DIR>          ..
2020/09/12  10:20               211 bin.py
2020/09/12  14:30                 0 dynamicpage_pipline.json
2020/09/12  10:36    <DIR>          dynamic_page
2020/09/12  10:33                 0 result.csv
2020/09/12  10:18               267 scrapy.cfg4 个文件            478 字节3 个目录 260,445,159,424 可用字节

接下来打开scrapy shell,输入命令:

scrapy shell 

输出:

...
[s]   view(response)    View response in a browser
>>>

最后粘贴以下代码:

from scrapy_splash import SplashRequest  #使用scrapy.splash.Request发送请求url = "https://search.jd.com/Search?keyword=%E5%86%B0%E6%B7%87%E6%B7%8B&enc=utf-8"
lua = '''
function main(splash)splash:go(splash.args.url)splash:wait(3)splash:runjs("document.getElementById('footer-2017').scrollIntoView(true)")splash:wait(3)return splash:html()
end
'''
fetch(SplashRequest(url,endpoint = 'execute',args= {'lua_source':lua})) #再次请求,我们可以看到现在已通过splash服务的8050端点渲染了js代码,并成果返回结果
len(response.css('div.gl-i-wrap'))

效果如下:

[s]   view(response)    View response in a browser
>>> from scrapy_splash import SplashRequest  #使用scrapy.splash.Request发送请求
>>> url = 'https://search.jd.com/Search?keyword=%E5%86%B0%E6%B7%87%E6%B7%8B&enc=utf-8'
>>> lua = '''
... function main(splash)
...     splash:go(splash.args.url)
...     splash:wait(3)
...     splash:runjs("document.getElementById('footer-2017').scrollIntoView(true)")
...     splash:wait(3)
...     return splash:html()
... end
... '''
>>> fetch(SplashRequest(url,endpoint = 'execute',args= {'lua_source':lua})) #再次请求,我们可以看到现
在已通过splash服务的8050端点渲染了js代码,并成果返回结果
2020-09-12 14:30:54 [scrapy.core.engine] INFO: Spider opened
2020-09-12 14:30:54 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET https://w
ww.jd.com/error.aspx> from <GET https://search.jd.com/robots.txt>
2020-09-12 14:30:55 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.jd.com/error.aspx> (ref
erer: None)
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 27 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 83 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 92 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 202 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 351 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 375 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 376 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 385 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 386 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 387 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 388 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 389 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 397 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 400 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 403 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 404 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 405 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 406 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 407 without any user agent to enforce it on.
2020-09-12 14:30:55 [protego] DEBUG: Rule at line 408 without any user agent to enforce it on.
2020-09-12 14:30:55 [scrapy.core.engine] DEBUG: Crawled (404) <GET http://192.168.0.10:8050/robots.txt
> (referer: None)
2020-09-12 14:31:10 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://search.jd.com/Search?keywor
d=%E5%86%B0%E6%B7%87%E6%B7%8B&enc=utf-8 via http://192.168.0.10:8050/execute> (referer: None)
>>> len(response.css('div.gl-i-wrap'))
60

注意:由于fetch不能直接在python代码中执行,所以只能在scrapy shell 模式中执行。

最后的任务就回归到了提取内容了阶段了,小伙伴让我们完成整个代码吧!---这里结合scrapy shell 进行测试

三、代码实现

新建项目

这里对目录就没有什么要求了,找个空目录就行。

打开Pycharm,并打开Terminal,执行以下命令

scrapy startproject ice_cream
cd ice_cream
scrapy genspider jd search.jd.com

在scrapy.cfg同级目录,创建bin.py,用于启动Scrapy项目,内容如下:

#在项目根目录下新建:bin.py
from scrapy.cmdline import execute
# 第三个参数是:爬虫程序名
execute(['scrapy', 'crawl', 'jd',"--nolog"])

创建好的项目树形目录如下:

./
├── bin.py
├── ice_cream
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       ├── __init__.py
│       └── jd.py
└── scrapy.cfg

修改settIngs.py

改写settIngs.py文件这里小伙伴们可参考github(https://github.com/scrapy-plugins/scrapy-splash)---上面有详细的说明

在最后添加如下内容:

# Splash服务器地址
SPLASH_URL = 'http://192.168.0.10:8050'
# 开启两个下载中间件,并调整HttpCompressionMiddlewares的次序
DOWNLOADER_MIDDLEWARES = {'scrapy_splash.SplashCookiesMiddleware': 723,'scrapy_splash.SplashMiddleware': 725,'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
}
# 设置去重过滤器
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
# 用来支持cache_args(可选)
SPIDER_MIDDLEWARES = {'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,
}
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
ITEM_PIPELINES = {'ice_cream.pipelines.IceCreamPipeline': 100,
}

注意:请根据实际情况,修改Splash服务器地址,其他的不需要改动。

修改文件jd.py

# -*- coding: utf-8 -*-
import scrapy
from scrapy_splash import SplashRequest
from ice_cream.items import IceCreamItem#自定义lua脚本
lua = '''
function main(splash)splash:go(splash.args.url)splash:wait(3)splash:runjs("document.getElementById('footer-2017').scrollIntoView(true)")splash:wait(3)return splash:html()end
'''class JdSpider(scrapy.Spider):name = 'jd'allowed_domains = ['search.jd.com']start_urls = ['https://search.jd.com/Search?keyword=%E5%86%B0%E6%B7%87%E6%B7%8B&enc=utf-8']base_url = 'https://search.jd.com/Search?keyword=%E5%86%B0%E6%B7%87%E6%B7%8B&enc=utf-8'# 自定义配置,注意:变量名必须是custom_settingscustom_settings = {'REQUEST_HEADERS': {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36',}}def parse(self, response):# 这里能获取100页page_num = int(response.css('span.fp-text i::text').extract_first())# 但是100页太多了,这里固定为2页page_num = 2# print("page_num", page_num)for i in range(page_num):url = '%s?page=%s' % (self.base_url, 2 * i + 1)  # 通过观察我们发现url页面间有规律# print("url", url)yield SplashRequest(url, headers=self.settings.get('REQUEST_HEADERS'), endpoint='execute',args={'lua_source': lua}, callback=self.parse_item)def parse_item(self, response):  # 页面解析函数# 创建item字段对象,用来存储信息item = IceCreamItem()for sel in response.css('div.gl-i-wrap'):name = sel.css('div.p-name em').extract_first()price = sel.css('div.p-price i::text').extract_first()# print("name", name)# print("price", price)item['name'] = nameitem['price'] = priceyield item# yield {#     'name': name,#     'price': price,# }

View Code

修改items.py

# -*- coding: utf-8 -*-# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapyclass IceCreamItem(scrapy.Item):# define the fields for your item here like:# name = scrapy.Field()# 与itcast.py定义的一一对应name = scrapy.Field()price = scrapy.Field()

View Code

修改pipelines.py

# -*- coding: utf-8 -*-# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
import jsonclass IceCreamPipeline(object):def __init__(self):#python3保存文件 必须需要'wb' 保存为json格式self.f = open("ice_cream_pipline.json",'wb')def process_item(self, item, spider):# 读取item中的数据 并换行处理content = json.dumps(dict(item), ensure_ascii=False) + ',\n'self.f.write(content.encode('utf=8'))return itemdef close_spider(self,spider):#关闭文件self.f.close()

View Code

执行bin.py,等待1分钟,就会生成文件ice_cream_pipline.json

打开json文件,内容如下:

{"name": "<em><span class=\"p-tag\" style=\"background-color:#c81623\">京东超市</span>\t\n明治(meiji)草莓白巧克力雪糕 245g(6支)彩盒 <font class=\"skcolor_ljg\">冰淇淋</font></em>", "price": "46.80"},
{"name": "<em><span class=\"p-tag\" style=\"background-color:#c81623\">京东超市</span>\t\n伊利 巧乐兹香草巧克力口味脆皮甜筒雪糕<font class=\"skcolor_ljg\">冰淇淋</font>冰激凌冷饮 73g*6/盒</em>", "price": "32.80"},
...

本文参考链接:

https://www.cnblogs.com/518894-lu/p/9067208.html

Splash抓取jd相关推荐

  1. java爬虫 京东_教您使用java爬虫gecco抓取JD全部商品信息(一)

    #教您使用java爬虫gecco抓取JD全部商品信息(一) ##gecco爬虫 如果对gecco还没有了解可以参看一下gecco的github首页.gecco爬虫十分的简单易用,JD全部商品信息的抓取 ...

  2. 教您使用java爬虫gecco抓取JD全部商品信息

    转自:http://www.geccocrawler.com/demo-jd/ gecco爬虫 如果对gecco还没有了解可以参看一下gecco的github首页.gecco爬虫十分的简单易用,JD全 ...

  3. java爬虫异步取数据_教您使用java爬虫gecco抓取JD全部商品信息(三)

    ##详情页抓取 商品的基本信息抓取完成后,就要针对每个商品的详情页进行抓取,可以看到详情页的地址格式一般如下:http://item.jd.com/1861098.html.我们建立商品详情页的Bea ...

  4. 教您使用java爬虫gecco抓取JD全部商品信息(一)

    摘要: 如果对gecco还没有了解可以参看一下gecco的github首页,https://github.com/xtuhcy/gecco.gecco爬虫十分的简单易用,JD全部商品信息的抓取9个类就 ...

  5. Scrapy爬虫框架(实战篇)【Scrapy框架对接Splash抓取javaScript动态渲染页面】

    (1).前言 动态页面:HTML文档中的部分是由客户端运行JS脚本生成的,即服务器生成部分HTML文档内容,其余的再由客户端生成 静态页面:整个HTML文档是在服务器端生成的,即服务器生成好了,再发送 ...

  6. Splash抓取javaScript动态渲染页面

    一.概述 Splash是一个javascript渲染服务.它是一个带有HTTP API的轻量级Web浏览器,使用Twisted和QT5在Python 3中实现.QT反应器用于使服务完全异步,允许通过Q ...

  7. python爬虫 爬取JD商城快消品的保质期

    从网上找的程序,稍加修改,实现在JD商城上爬取商品保质期的功能. 具体步骤如下: 一.准备工作 1)PC下载谷歌浏览器: 2)PC下载配置Selenium工具 具体可以参考 Python 爬虫实战 - ...

  8. Python3网络爬虫实战-38、动态渲染页面抓取:Splash的使用

    Splash 是一个 JavaScript 渲染服务,是一个带有 HTTP API 的轻量级浏览器,同时它对接了 Python 中的 Twisted和 QT 库,利用它我们同样可以实现动态渲染页面的抓 ...

  9. Python爬虫编程思想(114):项目实战--使用Splash Lua抓取京东搜索结果

    本文会利用Splash Lua脚本在京东商城上搜索商品,然后抓取搜索出的商品名称,以及将每一页搜索结果的截图保存为PNG格式的文件. 本例的核心是使用select_all方法通过CSS选择器得到搜索页 ...

最新文章

  1. onenote复制出来是图片_你真的了解 OneNote 吗?
  2. Java黑皮书课后题第10章:**10.7(游戏:ATM机)使用编程练习题9.7中创建的Account类来模拟一台ATM级
  3. Redis中的Cluster总结
  4. javascript --- 再识闭包
  5. c语言冒泡结构入门程序,C语言入门:冒泡排序
  6. 6阶群的非平凡子群_离散数学复习笔记
  7. [转载] 七龙珠第一部——第009话 兔子头儿的绝招
  8. 2017c语言 形成性考核,[2017年电大]《c语言程序设计》形成性考核作业()解答.doc...
  9. Docker-Docker-file构建Redis5.0.3镜像
  10. 电脑连接上无线网却没有网,手机却能上网怎么解决
  11. cefsharp 添加html,winform+cefSharp实现窗体加载浏览器
  12. 禁用win10触摸屏手势_笔记本WIN10系统启用或关闭触控板的多指(多点)触控功能步骤...
  13. php语言简述_PHP语言的简介
  14. 如何提高团队管理能力4
  15. signature=d392c0d1876b3909bd8f7e1f3c0bef22,【技术分享】NSA武器库:CVE-2017-9073 EsteemAudit分析...
  16. 如何制作一面智能镜子
  17. createrepo:创建本地源
  18. Deskpool云教室(云课堂)系列化配置
  19. 如何在Python中用集合实现随机的1~100的20个数字
  20. Xshell6下载及安装

热门文章

  1. 【数据可视化】bar函数绘制简单柱状图
  2. Write 字符输出流
  3. 【雷达通信】雷达探测项目仿真附Matlab代码
  4. 柠檬班性能测试day3_性能测试基础知识(0521)
  5. 利用脑电和功能磁共振成像(fMRI)捕捉自我生成、任务启动的思维的时空动态
  6. 软件性能测试报告收费,软件性能测试报告模板
  7. 根据收入计算纳税和税后所得
  8. 学生社团管理系统c语言代码,毕业设计—校园社团活动助手小程序
  9. python解决租房问题_高德API+Python解决租房问题
  10. 安全生产预测预警系统解决方案