13-scrapy中selenium的应用
一. 引入
在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值。但是通过观察我们会发现,通过浏览器进行url请求发送则会加载出对应的动态加载出的数据。那么如果我们想要在scrapy也获取动态加载出的数据,则必须使用selenium创建浏览器对象,然后通过该浏览器对象进行请求发送,获取动态加载的数据值。
二. 今日详情
1.案例分析:
(1).需求: 爬取网易新闻的国内板块下的新闻数据
(2).需求分析: 当点击国内超链接进入国内对应的页面时, 会发现当前页面展示的新闻数据是被动态加载出来的, 如果直接通过程序对url进行请求, 是获取不到动态加载出的新闻数据的, 则就需要我们使用selenium实例化一个浏览器对象, 在该对象中进行url请求, 获取动态加载的新闻数据
2. selenium在scrapy中使用的原理分析:
当引擎将国内板块url对应的请求提交给下载器后,下载器进行网页数据的下载,然后将下载到的页面数据,封装到response中,提交给引擎,引擎将response在转交给Spiders。Spiders接受到的response对象中存储的页面数据里是没有动态加载的新闻数据的。要想获取动态加载的新闻数据,则需要在下载中间件中对下载器提交给引擎的response响应对象进行拦截,切对其内部存储的页面数据进行篡改,修改成携带了动态加载出的新闻数据,然后将被篡改的response对象最终交给Spiders进行解析操作。
3. selenium在scrapy中的使用流程:
- 重写爬虫文件的构造方法,在该方法中使用selenium实例化一个浏览器对象(因为浏览器对象只需要被实例化一次)
- 重写爬虫文件的closed(self,spider)方法,在其内部关闭浏览器对象。该方法是在爬虫结束时被调用
- 重写下载中间件的process_response方法,让该方法对响应对象进行拦截,并篡改response中存储的页面数据
- 在配置文件中开启下载中间件
4. 代码展示:
爬虫文件代码:
- # -*- coding: utf-8 -*-
- import scrapy
- from Wangyixinwen.items import WangyixinwenItem
- from selenium import webdriver
- class WangyiSpider(scrapy.Spider):
- name = 'wangyi'
- # allowed_domains = ['www.xxx.com']
- #自动发送请求的 去设置里将user-agent以及robots协议设置好
- start_urls = ['https://news.163.com/']
- """"
- 我们的第一次请求对象就是start_urls开始,我们还需要对UA伪装同时还有IP代理等,可以在下载中间件的process_request中设置UA伪装
- process_exception中设置代理ip(等到自己ip出问题了就用代理ip)。等到响应对象缺失就可以在process_response中拦截。
- """
- bro = webdriver.Chrome("./chromedriver.exe")
- urls = []
- def parse(self, response):
- #从响应对象中获取到全部目标
- target_list = response.xpath('//*[@id="js_festival_wrap"]/div[3]/div[2]/div[2]/div[2]/div/ul/li')
- #遍历目标得到具体的url
- for index in [3,6,7,8]:
- target = target_list[index]
- #得到目标的url 并且取出url
- target_url = target.xpath('./a/@href').extract_first()
- self.urls.append(target_url)
- #对目标url发起请求
- yield scrapy.Request(url=target_url,callback=self.parse_target)
- def parse_target(self,response):
- #将第二次请求的响应对象开始解析,分析由于还未编写代码就知道这次是含有动态加载数据,因此这次
- #分析可以用到selenium一起解析数据,下面解析出新闻标题以及具体的详情页的url(响应的数据缺失,因此我们需要去下载中间件设置)
- detail_list = response.xpath('/html/body/div[1]/div[3]/div[4]/div[1]/div/div/ul/li/div/div')
- for detail in detail_list:
- title = detail.xpath('./div/div[1]/h3/a/text()').extract_first()
- detail_url = detail.xpath('./div/div[1]/h3/a/@href').extract_first()
- #实例化item对象,封装数据
- item = WangyixinwenItem()
- item["title"] = title
- yield scrapy.Request(url=detail_url,callback=self.parse_detail,meta={"item":item})
- def parse_detail(self,response):
- item = response.meta['item']
- content = response.xpath('//*[@id="endText"]/p/text()').extract()
- #将内容转换为字符串对象
- content = "".join(content)
- item["content"] = content
- #提交数据
- yield item
- def close(self,spider):
- # 爬虫结束,浏览器也关闭
- print("爬虫结束!!!")
- self.bro.quit()
中间件文件拦截代码展示:
- # -*- coding: utf-8 -*-
- # Define here the models for your spider middleware
- #
- # See documentation in:
- # https://docs.scrapy.org/en/latest/topics/spider-middleware.html
- from scrapy import signals
- from scrapy.http import HtmlResponse
- import random
- from time import sleep
- class WangyixinwenDownloaderMiddleware(object):
- # Not all methods need to be defined. If a method is not defined,
- # scrapy acts as if the downloader middleware does not modify the
- # passed objects.
- def process_request(self, request, spider):
- return None
- def process_response(self, request, response, spider):
- #刚才响应体缺失,因此从这里我们应该重新返回新的响应体
- #这里要用到爬虫程序中的urls,判断url是否在里面,在urls里面的就会出现响应缺失,
- # 、因此需要返回新的响应体
- if request.url in spider.urls:
- #响应缺失是因为是动态加载数据,因此我们配合selenium使用
- #在这里实例化selenium的话会被实例化多次,然而selenium只需要实例化一次,
- #这个时候我们可以将selenium放在实例化一次的爬虫程序开始的时候,实例化完成引入
- sleep(2)
- bro = spider.bro.get(url=request.url)#浏览器中发送请求
- sleep(1)
- spider.bro.execute_script("window.scrollTo(0,document.body.scrollHeight)")
- sleep(1.5)
- spider.bro.execute_script("window.scrollTo(0,document.body.scrollHeight)")
- sleep(0.7)
- spider.bro.execute_script("window.scrollTo(0,document.body.scrollHeight)")
- sleep(1)
- spider.bro.execute_script("window.scrollTo(0,document.body.scrollHeight)")
- #发送到请求我们需要获取浏览器当前页面的源码数据 获取数据之前需要翻滚页面
- page_text = spider.bro.page_source
- #改动返回响应对象 scrapy提供了一个库url=spider.bro.current_url, body=page_text, encoding='utf-8', request=request
- new_response = HtmlResponse(url=request.url,body=page_text,encoding="utf-8",request=request)
- return new_response
- else:
- return response
- #提交完新的响应体之后,去设置将下载中间件打开
- def process_exception(self, request, exception, spider):
- pass
备注:仔细看代码注释,能够迅速唤醒记忆,更快开发。
13-scrapy中selenium的应用的更多相关文章
- 15.scrapy中selenium的应用
引入 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现 ...
- scrapy中selenium的应用
引入 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现 ...
- scrapy中 selenium(中间件) + 语言处理 +mysql
在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现,通过 ...
- 15,scrapy中selenium的应用
引入 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生如果直接用scrapy对其url发请求,是获取不到那部分动态加载出来的数据值,但是通过观察会发现,通过浏览器 ...
- 14 Scrapy中selenium的应用
在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现,通过 ...
- selenium在scrapy中的使用、UA池、IP池的构建
selenium在scrapy中的使用流程 重写爬虫文件的构造方法__init__,在该方法中使用selenium实例化一个浏览器对象(因为浏览器对象只需要被实例化一次). 重写爬虫文件的closed ...
- Scrapy中集成selenium
面对众多动态网站比如说淘宝等,一般情况下用selenium最好 那么如何集成selenium到scrapy中呢? 因为每一次request的请求都要经过中间件,所以写在中间件中最为合适 from se ...
- 在Scrapy中使用selenium
在scrapy中使用selenium 在scrapy中需要获取动态加载的数据的时候,可以在下载中间件中使用selenium 编码步骤: 在爬虫文件中导入webdrvier类 在爬虫文件的爬虫类的构造方 ...
- selenium在scrapy中的应用
引入 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现 ...
- 第三百五十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—将selenium操作谷歌浏览器集成到scrapy中
第三百五十一节,Python分布式爬虫打造搜索引擎Scrapy精讲—将selenium操作谷歌浏览器集成到scrapy中 1.爬虫文件 dispatcher.connect()信号分发器,第一个参数信 ...
随机推荐
- Creating a Physical Standby from Primary on Version 12c (Doc ID 1570958.1)
Creating a Physical Standby from Primary on Version 12c (Doc ID 1570958.1) APPLIES TO: Oracle Databa ...
- 浅谈C++ STL string容器
浅谈C++ STL string容器 本篇随笔简单讲解一下\(C++STL\)中\(string\)容器的使用方法及技巧. string容器的概念 其实\(string\)并不是\(STL\)的一种容 ...
- 性能分析-java程序篇之案例-工具和方法
1. 背景说明 线上服务响应时间超过40秒,登录服务器发现cpu将近100%了(如下图),针对此问题,本文说明排查过程.工具以定位具体的原因. 2. 分析排查过程 此类问题的排查,有两款神器可用,分别 ...
- Python 从入门到进阶之路(四)
之前的文章我们简单介绍了一下 Python 的几种变量类型,本篇文章我们来看一下 Python 中的函数. 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性, ...
- 【带着canvas去流浪(9)】粒子动画
目录 一. 粒子特效 二. 开发中遇到的问题 2.1 卡顿 2.2 轨迹 2.3 复位 2.4 防护层 2.5 二维向量类 三. 实现讲解 3.1 粒子类的update方法 3.2 粒子群的绘制 3. ...
- Redis 数据类型及应用场景
一. redis 特点 所有数据存储在内存中,高速读写 提供丰富多样的数据类型:string. hash. set. sorted set.bitmap.hyperloglog 提供了 AOF 和 R ...
- js获取时间,循环执行任务,延迟执行任务
一.获取时间 核心方法创建一个时间对象:new Date() 时间对象相关操作 时间对象.函数名 函数名 功能 getYear() 获取四位数的年份 getMonth() 获取2位数的月数, 这个是从 ...
- 本地SQL Server数据库提示网络问题无法连接
运行程序时发现本地SQLserver数据库无法连接,提示信息为:在与SQL Server 建立连接时出现与网络相关的或特定与实例的错误.未能找到或无法访问服务器.请验证实例名称是否正确并且SQL Se ...
- Winform中在使用VS+svn进行协同开发时添加引用时的相对路径和绝对路径的问题
场景 使用Visual Studio 开发Winform程序,使用SVN进行项目版本管理. 在添加引用时,会出现在A电脑中添加了绝对路径的引用,在B电脑中就会出现找不到 并且将此引用标识为?的状态. ...
- Ext.ux.UploadDialog上传大文件 HTTP 错误 413.1 - Request Entity Too Large Web 服务器拒绝为请求提供服务,因为该请求实体过大。Web 服务器无法为请求提供服务,因为它正尝试与客户证书进行协商,但请求实体过大。
问题描述 问题:HTTP 错误 404.13 - Not Found 请求筛选模块被配置为拒绝超过请求内容长度的请求. 原因:Web 服务器上的请求筛选被配置为拒绝该请求,因为内容长度超过配置的值(I ...