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

备注:仔细看代码注释,能够迅速唤醒记忆,更快开发。

原文地址:https://www.cnblogs.com/lishuntao/p/11629852.html

时间: 2024-11-09 19:03:38

13-scrapy中selenium的应用的相关文章

爬虫学习 15.scrapy中selenium的应用

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

scrapy中selenium的应用

引子: 在通过scrapy框架进行某些网站数据爬取的时候,旺旺会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据,但是通过观察我们会发现,通过浏览器进行url请求发送则会加载出对应的动态加载出的数据.那么如果我们想要在scrapy也获取动态加载出的数据,则必须使用selenium穿件浏览器对象,然后通过该浏览器对象进行请求发送,获取动态加载的数据值. 1.案例分析: - 需求:爬取网易新闻的国内板块下的新闻数据 - 需求分析: 当点

scrapy中的selenium

引入 在通过scrapy框架进行某些网站数据爬取的时候,往往会碰到页面动态数据加载的情况发生,如果直接使用scrapy对其url发请求,是绝对获取不到那部分动态加载出来的数据值.但是通过观察我们会发现,通过浏览器进行url请求发送则会加载出对应的动态加载出的数据.那么如果我们想要在scrapy也获取动态加载出的数据,则必须使用selenium创建浏览器对象,然后通过该浏览器对象进行请求发送,获取动态加载的数据值. 1.案例分析: - 需求:爬取网易新闻的国内板块下的新闻数据 - 需求分析:当点击

爬虫07 /scrapy图片爬取、中间件、selenium在scrapy中的应用、CrawlSpider、分布式、增量式

目录 爬虫07 /scrapy图片爬取.中间件.selenium在scrapy中的应用.CrawlSpider.分布式.增量式 1. scrapy图片的爬取/基于管道类实现 2. 中间件的使用 3. selenium在scrapy中的应用 4. CrawlSpider 5. 分布式 5. 增量式 爬虫07 /scrapy图片爬取.中间件.selenium在scrapy中的应用.CrawlSpider.分布式.增量式 1. scrapy图片的爬取/基于管道类实现 爬取流程: 爬虫类中将解析到的图片

在Scrapy中使用Selenium

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

Scrapy中对xpath使用re

Scrapy中使用xpath时,根据xpath的语法不一定能得到想要的. 如下面的html源码: 1 <div class="db_contout"> <div class="db_cont"> <div class="details_nav"> <a href="http://movie.mtime.com/79055/addimage.html" class="db_ad

scrapy和selenium结合抓取动态网页

1.安装python (我用的是2.7版本的) 2.安装scrapy:   详情请参考 http://blog.csdn.net/wukaibo1986/article/details/8167590 (提示,能下载源码安装的就避免用pip install **) 安装过程中遇到python扩展问题”unable to find vcvarsall.bat“的解决办法: http://blog.csdn.net/ren911/article/details/6448696 3.安装seleniu

scrapy中的canonicalize_url【转】

转自:http://www.leyle.com/archives/canonicalize_url.html 思考一下:对url进行规范化处理是否是必须的?因为这一步处理涉及到编码转换,对于一个网页的新链发现来说是比较耗时的. 为什么需要格式化 url? 比如下面几个url: http://www.example.com/path/xxx?name=leyle&passwd=leyle http://www.example.com/path/xxx?passwd=leyle&name=le

JavaScript学习13 JavaScript中的继承

JavaScript学习13 JavaScript中的继承 继承第一种方式:对象冒充 <script type="text/javascript"> //继承第一种方式:对象冒充 function Parent(username) //父类对象 { this.username = username; //下面的代码最关键的部分就是将子对象的this传递给了父对象 this.sayHello = function() { alert(this.username); } } f