17.老板让我手动控制网页渲染速度,说这能反爬虫?我信了。(代码片段)

梦想橡皮擦 梦想橡皮擦     2023-01-04     166

关键词:

手动数据延迟加载,真的可以反爬虫
爬虫训练场项目,加速更新中,专栏清单参考 pachong.vip
本次案例需要的代码量特别小,所以咱们再 Nginx 中也进行一下相关配置

文章目录

页面逻辑实现

这篇博客主要实现一个慢响应爬虫,即模拟网速缓慢时,该如何处理采集程序。

正式实现前,依旧是实现基础页面,本次案例前端使用 Bootstrap5 构建,案例采用 9 部香港经典电影作为数据储备。

快速搭建出视图函数和视图页面,清单如下。

  • app/slow/index.py:用户编写视图相关函数。
  • app/templates/slow/index.html:视图相关代码。

其中 index.html 文件用于实现电影列表,我们可以用可以使用 Bootstrap 的网格系统来创建电影列表。例如,你可以使用 .col-4 类创建一个 3 列的电影列表:

<div class="row">
  <div class="col-4">
    <div class="card">
      <img src="movie1.jpg" class="card-img-top" alt="Movie 1">
      <div class="card-body">
        <h5 class="card-title">Movie 1</h5>
        <p class="card-text">Movie 1 description</p>
      </div>
    </div>
  </div>
  <div class="col-4">
   ……
  </div>
  <div class="col-4">
    ……
  </div>
</div>

在上述代码的基础上,完善卡片信息,补齐电影资料。

<div class="card">
   <img src="url_for('static',filename='images/movie/1.jpg')"
         class="img-fluid" alt="Movie 1">
    <div class="card-body">
        <h5 class="card-title">无间道</h5>
        <p class="card-text">
            作为香港警探电影系列的巅峰之作,无间道由刘德华、梁朝伟、黄秋生等实力影帝主演,它作为刘德华十大经典电影之一,主要讲述了黑社会的卧底故事,情节反转再反转,非常值得重复观看。</p>
        <button type="button" movieid="1" class="show_movie btn btn-primary">
            详细
        </button>

    </div>
</div>

图片素材,可以去 GitCode 获取,除此之外,给 <img> 标签还增加了 .img-fluid 类,该类可以让图像自适应容器大小,并保持宽度为 100%。

注意上述代码我们使用了一个【详细按钮】,该按钮可以唤醒一个模态弹窗,对应的JS代码如下所示。

$('.show_movie').on('click',function()
     showModal();
);
function showModal() 

   $('#movieModal').modal('show');

其中 $('#movieModal') 调用的 DIV 对象内容如下所示。

<div class="modal fade" id="movieModal">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">

            <!-- 模态标题 -->
            <div class="modal-header">
                <h4 class="modal-title movie_title">加载中……</h4>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>

            <!-- 模态主体 -->
            <div class="modal-body text-center">
                <div class="spinner-border text-primary d-none"></div>
                <p class="movie_body">加载中……</p>
            </div>

            <!-- 模态页脚 -->
            <div class="modal-footer">
                <button type="button" class="btn btn-danger" data-bs-dismiss="modal">关闭</button>
            </div>

        </div>
    </div>
</div>

基础内容增加完毕,实现页面请求部分代码,我们采用 jQuery 的 $.get() 方法发送 HTTP get 请求获取数据,基本格式如下所示。

$.get(url, data, callback, dataType);

其参数说明如下所示。

  • url是请求的 URL;
  • data 是要发送到服务器的数据;
  • callback 是服务器响应后执行的回调函数;
  • dataType 是服务器响应的数据类型,可以是 “html”, “xml”, “json”, “jsonp” 等。

下面是一个示例,用 $.get方法从服务器获取 JSON 格式的数据:

$.get('/data.json', function(data) 
  console.log(data);
, 'json');

简写格式如下所示:

$.get('/data.json', function(data) 
  console.log(data);
);

这样,数据类型就默认为 "text",不需要手动指定。

data 参数是要发送到服务器的数据。它可以是以下几种类型之一:

  • 字符串:表示查询字符串,例如"name=xiangpica&age=20"
  • 对象:表示查询字符串的键/值对,例如 name: "xiangpica", age: 20
  • 函数:表示返回查询字符串的函数,例如 function() return "name=xiangpica&age=20";

data 是字符串或对象时,会将其转换为查询字符串并附加到 URL 的末尾。例如,对于以下代码:

$.get('/data',  name: "xiangpica", age: 20 , function(data) 
  console.log(data);
);

实际发送的请求如下所示。

GET /data?name=xiangpica&age=20

如果 data 是函数,则会执行函数并使用其返回值作为查询字符串。例如,对于以下代码:

$.get('/data', function()  return "name=xiangpica&age=20"; , function(data) 
  console.log(data);
);

实际发送的请求如下所示。

GET /data?name=xiangpica&age=20

当然,你也可以不使用 data 参数,直接发送空的 GET 请求。例如:


$.get('/data', function(data) 
  console.log(data);
);

接口逻辑实现

前端页面构建完毕,就需要将API部分补齐,本次修改的文件是 slow/index.py 文件,其代码如下所示。

slow = Blueprint('slow', __name__, url_prefix='/slow')

movies = [
    "name": "无间道",
    "release_time": "2002年12月12日",
    "company": "寰亚电影发行公司",
    "movie_type": "剧情、犯罪、警匪"
, 
    "name": "青蛇",
    "release_time": "1993年11月4日",
    "company": "香港思远影业公司",
    "movie_type": "奇幻"

, 
    "name": "喜剧之王",
    "release_time": "1999年02月13日",
    "company": "星辉海外有限公司",
    "movie_type": "剧情、喜剧、爱情"

, 
    "name": "重庆森林",
    "release_time": "1994年07月14日",
    "company": "泽东电影有限公司",
    "movie_type": "剧情、悬疑、爱情"

, 
    "name": "英雄本色",
    "release_time": "1986年8月2日",
    "company": "新艺城影业有限公司",
    "movie_type": "剧情、动作、犯罪、惊悚"

, 
    "name": "倩女幽魂",
    "release_time": "1987年7月18日",
    "company": "新艺城影业有限公司",
    "movie_type": "爱情、奇幻、武侠、古装"
, 
    "name": "花样年华",
    "release_time": "2000年9月29日",
    "company": "泽东电影公司",
    "movie_type": "剧情、文艺、爱情"
, 
    "name": "大话西游系列",
    "release_time": "1995年2月4日",
    "company": "彩星电影公司",
    "movie_type": "喜剧、爱情、动作、奇幻、冒险"
, 
    "name": "东成西就",
    "release_time": "1993年2月5日",
    "company": "泽东电影公司",
    "movie_type": "喜剧"
]


@slow.route('/list')
def list_slow():
    return render_template('slow/index.html')


@slow.route('/detail')
def detail():
    movie_id = int(request.args.get("movie_id", 1))
    movie = movies[movie_id - 1]
    return jsonify(movie)

其中涉及两个路由配置,list 是列表页面,detail 是详情页面,后面主要控制该页面响应速度。

整体代码完成之后的效果如下所示。


前端弹窗接口调用部分JS代码如下所示,核心逻辑是请求 API,然后拼接响应数据。

$(function()
    function showModal(movie_id) 

         var data =  
                movie_id: movie_id
         
        $.get('/slow/detail',data,function(res)

            $('.spinner-border').addClass('d-none');
            $('.movie_title').text(res.name);
            $('.movie_body').html('<p>上映时间: '+res.release_time+'</p><p>类型:  '+res.movie_type+'</p><p>出品公司: '+res.company+'</p>')
        )
        $('#movieModal').modal('show');
    
    $('.show_movie').on('click',function()
            var movie_id = $(this).attr('movieid');
            $('.movie_title').text('加载中……');
            $('.movie_body').text('加载中……');
            $('.spinner-border').removeClass('d-none');
            showModal(movie_id);

    );
);

延迟实现,time.sleep() 和 Nginx 配置

在延迟处理这一块,最简单的办法是调用 time 模块的 sleep() 函数,代码如下:

time.sleep(5) # 延迟 5 秒

第二种配置是采用 Nginx 控制请求次数,首先在服务器端的 Nginx 上找到配置文件 nginx.conf,然后在 httpserver 块中添加如下配置。

limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;

在这里,$binary_remote_addr 是 Nginx 变量,表示客户端的 IP 地址,zone=mylimit:10m 表示将限制存储在名为 mylimit 的区域中,并且每个区域可以存储 10MB 的数据,rate=1r/s 表示请求速率为每秒 1 个请求。

接下来回到 Nginx 的通用配置文件 location 块中,添加如下内容。

location /slow/detail

 proxy_pass http://127.0.0.1:8787;
 proxy_set_header Host $host;
 limit_req zone=mylimit burst=1 nodelay;

这里最重要的配置为 limit_req zone=mylimit burst=1 nodelay;,其中 limit_req 指令是 Nginx 中的一个请求限制功能,用于限制对某个区域的请求的速率。

limit_req 指令有多个参数可以设置,常用的参数有:

  • zone:表示限制请求速率的区域名称。需要使用 limit_req_zone 指令先定义区域;
  • burst:表示请求速率的最大值(每秒请求数)。如果请求速率超过了这个值,则会被拒绝;
  • nodelay:表示请求速率的最小值(每秒请求数)。如果请求速率低于了这个值,则会被延迟响应。

在回过头来看一下刚刚的配置,zone=mylimit 表示使用名为 mylimit 的区域来限制请求速率,burst=1 表示请求速率的最大值是每秒 1 个请求,nodelay 表示请求速率的最小值是每秒 1 个请求。

本案例到此结束,已更新到 爬虫训练场 欢迎大家访问学习。
项目同步到代码仓库 https://gitcode.net/hihell/spider_playground

📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 814 篇原创博客

从订购之日起,案例 5 年内保证更新

自从用了这个属性,老板都夸我网页加载的更快(代码片段)

前言某次浏览沸点的时候,无意间的打开控制台,偶遇了text-rendering。这个没有用过的新鲜属性,让我瞬间开心了起来,又可以水一篇文章了学会新的属性了。兼容性text-renderingMDN定义浏览器渲染引擎如何渲染字体... 查看详情

如何有效的优化网页的加载速度?优化网页速度的7种方法

...这些资源的加载速度,那么网页展示的速度也就上去了。让我来一一列举:1.优化图片资源的格式和大小一个网 查看详情

华为荣耀7i手动更改dns,提高网页加载速度

...度哦!亲身体验。有效的。以华为荣耀7i手机为例:通过手动设置DNS的方式解决。第一步  首先,进入手机系统界面,在桌面上找到【设置】,进入【WLAN设置】选项界面。  第二步  然后,在目前已扫描到 查看详情

用爬虫抓取网页得到的源代码和浏览器中看到的不一样运用了啥技术?

网页源代码和浏览器中看到的不一样是因为网站采用了动态网页技术(如AJAX、JavaScript等)来更新网页内容。这些技术可以在用户与网站进行交互时,通过异步加载数据、动态更新页面内容,实现更加流畅、快速的用户体验。而... 查看详情

python爬虫怎么获取动态的网页源码

...,导师也不催,自己也不急。但是,导师等我一个月都得让我来写意味着这东西得有多难吧。。。今天打开一看的确是这样。网站是基于Ajax写的,数据动态获取,所以无法通过下载源代码然后解析获得。从某不良少年写的抓取... 查看详情

了解爬虫(代码片段)

...站将数据返回给浏览器?浏览器将数据进行渲染?然后可以手动获取(ctrl+cctrl+V)"爬虫程序"获取数据:模拟浏览器往目标网站发送请求;请求库:reques 查看详情

初识爬虫

何为爬虫  网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。  我们平时的上网就是浏览器提交请求->下载网页代... 查看详情

class17-2动态渲染页面爬取—splash(代码片段)

...页面和浏览器中得到的结果完全一致。这个过程由什么来控制呢?重新返回首页,可以看到有段脚本,内容:functionmain(splash,args)assert(splash:go(args.url))assert(splash:wait(0.5))returnhtml=splash:html(),png=splash:png(),har=splash:har(),end这个脚本是用... 查看详情

学习爬虫前对网页进行认识

前言  首先我们提到爬虫,我们不得不说网页,因为我们使用python编写的爬虫实际上是针对于网页进行设计的,解析网页以及抓取这些数据是爬虫需要做的事情,日常中我们看到这些网页,可以看到很多图片,很多的标题以及... 查看详情

网络爬虫的盗之有道

...1小规模,数据量小,爬取速度不敏感;利用Request库爬取网页和玩转网页2中规模:数据规模较大,爬取速度敏感;可以利用scrapy库爬取网站或者爬取系列网站3大规模,搜索引擎爬取速度关键,主要是通过定制开发,而不是某一... 查看详情

网页浏览器速度太快,如何控制速度?

】网页浏览器速度太快,如何控制速度?【英文标题】:Webbrowsergoingtoofast,howtocontrolspeed?【发布时间】:2011-07-2016:39:42【问题描述】:我的应用需要点击页面上的按钮x次(用户定义)。该页面的工作方式如下:单击按钮后,页面... 查看详情

如何使 R 渲染图更快

...问题,即R渲染绘图所需的时间会占用计算所需的时间。让我通过一个人为的例子来证明这一点。在这个基本测试用例中,R需要大约17秒来渲染热图文件并将其保存为png(数据计算时间已被占用:行和列集群是预先计算的)我想 查看详情

反-反爬虫:用几行代码写出和人类一样的动态爬虫

...器。Phantomjs的特点由于“无头”——免去了渲染可视化的网页界面,她的速度要比一 查看详情

网页爬虫

...招拆招,只是遗憾的是仅仅要你想爬没啥爬不到的,比方控制下爬取频率,用无数个代理小量多次爬取,反爬虫仅仅能说是尽量添加一些爬取的门槛吧,至少把一些练手的小爬虫(比方如今这个小菜鸡爬虫)挡在外面。降低些负... 查看详情

控制台不必要的错误消息是不是会减慢网页速度?

】控制台不必要的错误消息是不是会减慢网页速度?【英文标题】:IsconsoleunnecessaryErrorMessageslowingthewebpage?控制台不必要的错误消息是否会减慢网页速度?【发布时间】:2021-05-2616:52:45【问题描述】:我正在使用Handsontable在我的... 查看详情

老板儿子来公司实习,还让我带着他学python?

...情是这样的最近公司来了一位00后实习生,关键还是老板的儿子。老板安排给了我,让我好好带带他可是这位少爷,天天上班不是刷抖音就是刷B站这……让我很难带他,关键啥也不懂于是我给他制定了一份最基础... 查看详情

python爬虫和测试的区别

...试、页面测试、压力测试、性能测试等,这些测试也还分手动,半自动和全自动,这些测试里面,网页页面的自动化测试确实也很多用selenium的,那种一般是测试自己的网页是不是有异常,展现的数据是不是有错误,所以抓取的... 查看详情

老板儿子来公司实习,还让我带着他学python?搞笑

...情是这样的最近公司来了一位00后实习生,关键还是老板的儿子。老板安排给了我,让我好好带带他可是这位少爷,天天上班不是刷抖音就是刷B站这……让我很难带他,关键啥也不懂于是我给他制定了一份最基础... 查看详情