python网络爬虫 Scrapy中selenium用法详解


Posted in Python onSeptember 28, 2019

引入

在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值。但是通过观察我们会发现,通过浏览器进行url请求发送则会加载出对应的动态加载出的数据。那么如果我们想要在scrapy也获取动态加载出的数据,则必须使用selenium创建浏览器对象,然后通过该浏览器对象进行请求发送,获取动态加载的数据值。

1.案例分析:

- 需求:爬取网易新闻的国内、国际、军事、无人机板块下的新闻数据

- 需求分析:当点击国内超链进入国内对应的页面时,会发现当前页面展示的新闻数据是被动态加载出来的,如果直接通过程序对url进行请求,是获取不到动态加载出的新闻数据的。则需要我们使用selenium实例化一个浏览器对象,在该对象中进行url的请求,获取动态加载的新闻数据。

2.selenium在scrapy中使用的原理分析:

python网络爬虫 Scrapy中selenium用法详解

当引擎将国内板块url对应的请求提交给下载器后,下载器进行网页数据的下载,然后将下载到的页面数据,封装到response中,提交给引擎,引擎将response再转交给Spiders。Spiders接受到的response对象中存储的页面数据里是没有动态加载的新闻数据的。要想获取动态加载的新闻数据,则需要在下载中间件中对下载器提交给引擎的response响应对象进行拦截,切对其内部存储的页面数据进行篡改,修改成携带了动态加载出的新闻数据,然后将被篡改的response对象最终交给Spiders进行解析操作。

3.selenium在scrapy中的使用流程:

  • 重写爬虫文件的构造方法,在该方法中使用selenium实例化一个浏览器对象(因为浏览器对象只需要被实例化一次)
  • 重写爬虫文件的closed(self,spider)方法,在其内部关闭浏览器对象。该方法是在爬虫结束时被调用
  • 重写下载中间件的process_response方法,让该方法对响应对象进行拦截,并篡改response中存储的页面数据
  • 在配置文件中开启下载中间件

4.实例:

# 1.spider文件

import scrapy
from wangyiPro.items import WangyiproItem
from selenium import webdriver

class WangyiSpider(scrapy.Spider):
  name = 'wangyi'
  # allowed_domains = ['www.xxx.con']
  start_urls = ['https://news.163.com/']
  # 浏览器实例化的操作只会被执行一次
  bro = webdriver.Chrome(executable_path='chromedriver.exe')

  urls = []# 最终存放的就是5个板块对应的url

  def parse(self, response):
    li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')
    for index in [3,4,6,7,8]:
      li = li_list[index]
      new_url = li.xpath('./a/@herf').extract_first()
      self.urls.append(new_url)

      # 对5大板块对应的url进行请求发送
      yield scrapy.Request(url=new_url,callback=self.parse_news)

  # 用来解析每一个板块对应的新闻数据【只能解析到新闻的标题】
  def parse_news(self,response):
    div_list = response.xpath('//div[@class="ndi_main"]/div')
    for div in div_list:
      title = div.xpath('./div/div[1]/h3/a/text()').extract_first()
      news_detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first()
      # 实例化item对象,将解析到的标题和内容存储到item对象中
      item = WangyiproItem()
      item['title'] = title
      # 对详情页的url进行手动请求发送获得新闻内容
      yield scrapy.Request(url=news_detail_url,callback=self.parse_detail,meta={'item':item})

  def parse_detail(self,response):
    item = response.meta['item']
    # 通过response解析出新闻内容
    content = response.xpath('//div[@id="endText"]//text()').extract()
    content = ''.join(content)

    item['content'] = content
    yield item

  def close(self,spider):
    # 当爬虫结束之后,调用关闭浏览器方法
    print('爬虫整体结束~~~~~~~~~~~~~~~~~~~')
    self.bro.quit()
----------------------------------------------------------------------------------------
# 2.items文件

import scrapy

class WangyiproItem(scrapy.Item):
  # define the fields for your item here like:
  # name = scrapy.Field()
  title = scrapy.Field()
  content = scrapy.Field()
----------------------------------------------------------------------------------------
# 3.middlewares文件

from scrapy import signals
from scrapy.http import HtmlResponse
from time import sleep

class WangyiproDownloaderMiddleware(object):

  def process_request(self, request, spider):
    return None

  def process_response(self, request, response, spider):
    # 判断哪些响应对象是5个板块的,如果在就对响应对象进行处理
    if response.url in spider.urls:
      # 获取在爬虫类中定义好的浏览器
      bro = spider.bro
      bro.get(response.url)

      bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
      sleep(1)
      bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
      sleep(1)
      bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
      sleep(1)
      bro.execute_script('window.scrollTo(0,document.body.scrollHeight)')
      sleep(1)

      # 获取携带了新闻数据的页面源码数据
      page_text = bro.page_source
      # 实例化一个新的响应对象
      new_response = HtmlResponse(url=response.url,body=page_text,encoding='utf-8',request=request)
      return new_response
    else:
      return response

  def process_exception(self, request, exception, spider):
    pass
----------------------------------------------------------------------------------------
# 4.pipelines文件

class WangyiproPipeline(object):
  def process_item(self, item, spider):
    print(item)
    return item
----------------------------------------------------------------------------------------
# 5.setting文件
BOT_NAME = 'wangyiPro'

SPIDER_MODULES = ['wangyiPro.spiders']
NEWSPIDER_MODULE = 'wangyiPro.spiders'

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

ROBOTSTXT_OBEY = False

DOWNLOADER_MIDDLEWARES = {
  'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,
}

ITEM_PIPELINES = {
  'wangyiPro.pipelines.WangyiproPipeline': 300,
}

LOG_LEVEL = 'ERROR'

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用正则表达式检测密码强度源码分享
Jun 11 Python
python获取当前计算机cpu数量的方法
Apr 18 Python
python使用socket向客户端发送数据的方法
Apr 29 Python
python字符串,数值计算
Oct 05 Python
python3使用requests模块爬取页面内容的实战演练
Sep 25 Python
使用pandas将numpy中的数组数据保存到csv文件的方法
Jun 14 Python
python实现内存监控系统
Mar 07 Python
centos 安装Python3 及对应的pip教程详解
Jun 28 Python
基于Python解密仿射密码
Oct 21 Python
Tensorflow之MNIST CNN实现并保存、加载模型
Jun 17 Python
Python中文分词库jieba(结巴分词)详细使用介绍
Apr 07 Python
总结三种用 Python 作为小程序后端的方式
May 02 Python
在vscode中配置python环境过程解析
Sep 28 #Python
python爬虫 线程池创建并获取文件代码实例
Sep 28 #Python
python 单线程和异步协程工作方式解析
Sep 28 #Python
python爬虫 正则表达式解析
Sep 28 #Python
python爬虫 Pyppeteer使用方法解析
Sep 28 #Python
python安装scipy的步骤解析
Sep 28 #Python
python网络爬虫 CrawlSpider使用详解
Sep 27 #Python
You might like
基于数据库的在线人数,日访问量等统计
2006/10/09 PHP
Smarty foreach控制循环次数的一些方法
2015/07/01 PHP
PHP微信刮刮卡 附微信接口
2016/07/22 PHP
浅谈PHP进程管理
2019/03/08 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
2019/12/12 PHP
Javascript(AJAX)解析XML的代码(兼容FIREFOX/IE)
2010/07/11 Javascript
在jQuery 1.5中使用deferred对象的代码(翻译)
2011/03/10 Javascript
jquery中的 $("#jb51")与document.getElementById("jb51") 的区别
2011/07/26 Javascript
JavaScript中统计Textarea字数并提示还能输入的字符
2014/06/10 Javascript
JavaScript获取网页表单action属性的方法
2015/04/02 Javascript
jQuery Ajax传值到Servlet出现乱码问题的解决方法
2016/10/09 Javascript
JavaScript中String对象的方法介绍
2017/01/04 Javascript
详解Javascript中DOM的范围
2017/02/13 Javascript
Bootstrap Multiselect 常用组件实现代码
2017/07/09 Javascript
underscore之function_动力节点Java学院整理
2017/07/11 Javascript
Element-UI Table组件上添加列拖拽效果实现方法
2018/04/14 Javascript
vue router 跳转后回到顶部的实例
2018/08/31 Javascript
微信小程序实现电影App导航和轮播
2020/11/30 Javascript
[26:21]浴火之凤-TI4世界冠军Newbee战队纪录片
2014/08/07 DOTA
python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE方法
2017/05/24 Python
python批量下载抖音视频
2019/06/17 Python
Django上线部署之IIS的配置方法
2019/08/22 Python
Python将QQ聊天记录生成词云的示例代码
2021/02/10 Python
日本即尚网:JSHOPPERS.com(支持中文)
2019/12/03 全球购物
澳大利亚领先的在线礼品网站:Gifts Australia
2020/08/15 全球购物
数据库设计的包括哪两种,请分别进行说明
2016/07/15 面试题
简述索引存取方法的作用和建立索引的原则
2013/03/26 面试题
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
2012/11/24 面试题
北京捷通华声语音技术有限公司Java软件工程师笔试题
2012/04/10 面试题
拓展培训心得体会
2014/01/04 职场文书
沙滩主题婚礼活动策划方案
2014/09/15 职场文书
公务员上班玩游戏检讨书
2014/09/17 职场文书
社区党务工作总结2015
2015/05/19 职场文书
《藏戏》教学反思
2016/02/23 职场文书
Java实现二分搜索树的示例代码
2022/03/17 Java/Android
「海贼王」112.9万粉丝纪念图标公布
2022/03/21 日漫