01-探寻 JavaScript 反爬虫的根本原因

答疑·限时优惠

如果,你想让我看见你的疑问并且百分之百的回答。可以加入我的知识星球。
AI悦创·进化岛
AI悦创·进化岛

你好,我是悦创。

本系列教程开始之前呢,我要先跟你探讨一下:反爬虫是什么

首先,反爬虫这件事在目前来讲,并没有明确的定义。(整个业内都没有一个明确的定义)那由于各方角色不同,或者用的编程语言或者工具不同,所以对于反爬虫的看法也各持己见。

那么,在咱们这个系列课程中呢,我需要大家保持一个相同的观点:

我们约定,限制爬虫程序访问服务器资源和获取数据行为的称为 反爬虫。

限制手段包括但不限于:请求限制、拒绝响应、客户端身份验证、文本混淆和使用动态渲染技术。

这些限制根据出发点可以分为:主动型反爬虫和被动型反爬虫。

Ps:

主动型反爬虫指的是,有意而为之,特意为我们(爬虫工程师)准备的一些限制手段。

例如说:IP 限制、Cookies 校验、登录页面的验证码或者是注册页面的验证码等等

被动型反爬虫指的是,当用户操作某样功能引起是的一个功能机制。

例如说:下拉加载、悬停(预览)、以及一些网页数据的计算等等,这些是以提升用户体验为主要目的,但是它们也造成了——爬虫对这些数据的获取的一个限制效果。

这节课主要分为 4 个知识点。

目录

  1. (反爬虫)Web 网页的基本构成
  2. 浏览器的组件和作用
  3. HTML DOM与网页渲染过程
  4. 编程语言或工具与浏览器的差异
1. Web 网页的基本构成

这是浏览器打开网页后的一个截图,从截图当中我们可以看到有:导航栏、logo、搜索框、备案号相关信息等等,那么组成这个页面的主要元素就是 文字和图片 。当然,页面的元素远远不止这些,像优酷、网易或者爱奇艺、搜狗等等,网站当中还有音频和视频。

接下来我们一起来看一下一个网页的基本构成

(图片来源-网络)

从左到右分别是:HTML、JavaScript、CSS、媒体资源、Other(和其他的一些东西)

  • HTML:HTML 是超文本标记语言,在文档当中它被 html 标签对包裹的文本(\-\)就是 HTML 文档或者是 HTML 的代码。
  • JavaScript:JavaScript 是一种解释型语言,在文档当中被 script 标签对(),包裹的文本就是 JavaScript 的代码。
  • CSS:CSS是层叠样式表,在文档中被 style 标签包裹着的就是 CSS 样式的代码
    > 那么之后的:图片视频音频和字体,这些都属于媒体或者多媒体资源。(例如:表示图片的标签通常是 img 标签,然后其中的 src 指向的就是 具体资源路径

操作:打开浏览器观察资源加载

按以下步骤来:

  1. 打开浏览器
  2. 访问:https://www.baidu.com/
  3. 打开浏览器的开发者工具(F12)
  4. 切换到 NetWork 面板

  1. 接下来刷新一些网页或者输入:Python 搜索

现在,我们来看看到底加载哪些内容。

这时候我们会发现,当我们访问百度这个网站的时候,加载的资源有:文档、css文件、图片(png、jpg)、js等

2. 浏览器的组件和作用

我们常用的浏览器共有五个组件和三个解释器,这五个组件分别是:用户界面、浏览器引擎、渲染引擎、数据存储、网络,三个解释器分别是:HTML 解释器、JavaScript 解释器、CSS 解释器

那么浏览器之所以能够理解 HTML、CSS、JavaScript 代码,并且按照一定的规则排版,就是这个三个解释器的功劳。

组件这边,用户界面组件的主要作用是显示操作界面,浏览器引擎的主要作用就是:负责将用户的操作传递给对应的渲染引擎,渲染引擎的主要作用是调用,这三个解释器去解释对应的文档中的代码。然后根据解释器的结果重新排版页面。数据存储组件它的作用是:在本地存储一些体积较小的数据,如 Cookies、Storage对象等。网络组件:它会自动加载 HTML 文档中所需要的其他资源。

刚才带大家了解了浏览器的五大组件和三大解释器,我们可以在脑海中填补浏览器的结构图。 也就是说平常使用的浏览器,实际上是由一堆组件构成的一个工具。

那么其中各个组件各司其职,例如:渲染组件、渲染引擎 它会调用三个解释器去解释并理解代码当中的一些意图。

3. HTML DOM 与网页渲染过程

HTML DOM 是文档对象模型,它是中立于平台和语言之间的一个接口。它允许程序动态的更新文档内容,文档结构和样式。换一句话来说:程序可以通过 DOM 来改变页面显示的内容,HTML 文档中的每一个标签对,都是一个 DOM 节点(例如:title 标签,对应一个 DOM节点,那么 year 标签对应的也是一个 DOM 节点)看一下上面右边的那张图,我们平时看到的一层一层、层层嵌套的 HTML 标签,实际上就是一个父子关系的一个 DOM 节点。JavaScript 代码和 CSS 样式,可以改变页面当中文字或图片的位置、颜色或者内容,但要注意的是:它们改变的只是页面显示的内容,并不是能够真正的去改变 HTML 文档本身。它们只是改变了浏览器中的 DOM,这个观点非常重要。(大家一定要理解)

操作:打开浏览器编辑 HTML

这里我们打开浏览器来做一个小实验,这里我们借助 W3school 的在线编辑器来运行 HTML 代码。

<html>

<!-- <style>
.last{
    color:red;
}
</style>
 -->
<body>
    <p id="first">这是段落。</p>
    <p>这是段落。</p>
    <p>这是段落。</p>
    <p class="last">段落元素由 p 标签定义</p>
</body>
<!--
<script>
    first = document.getElementById("first");
    first.innerHTML = "我说这是什么就是什么";
</script>
-->
</html>

我们可以看一下上面的代码,这些代码都包裹在 html 标签对当中。那么 body 标签当中包裹着的就是 HTML 的代码,<style></style> 标签对包裹着的是 CSS 样式<script></script> 标签对包裹的是 JavaScript 代码 在 HTML 中这个是注释符:<!----> 被注释符注释掉的,不会在代码中起作用。

我们先运行以下代码:

<html>
<body>
<p id="first">这是段落。</p>
<p>这是段落。</p>
<p>这是段落。</p>
<p class="last">段落元素由 p 标签定义</p>
</body>

</html>

我们来看看运行结果:

我们可以看到,右侧的内容显示区域,显示了 HTML 文档当中定义的内容。

我接下来来运行以下代码:

<html>
<style>
.last{
    color:red;
}
</style>

<body>
    <p id="first">这是段落。</p>
    <p>这是段落。</p>
    <p>这是段落。</p>
    <p class="last">段落元素由 p 标签定义</p>
</body>
</html>

我们这时候可以看到最后的那一段文字的颜色,已经被改变了。

同样我们加上 JavaScript 代码看看:

<html>

<style>
.last{
    color:red;
}
</style>

<body>
    <p id="first">这是段落。</p>
    <p>这是段落。</p>
    <p>这是段落。</p>
    <p class="last">段落元素由 p 标签定义</p>
</body>

<script>
    first = document.getElementById("first");
    first.innerHTML = "我说这是什么就是什么";
</script>

</html>

我们发现右侧内容区域的第一行内容已经被改变,那么问题来了:为什么内容区域的文字和颜色都发生了变化,但代码中的 body 标签包裹着的这些文字或者这些文本,都没有发生任何的变化呢?

左侧的代码仍然是:这是段落。而显示给我们看的就是:我说这是什么就是什么。这时候想一下,思考一下:为什么会是这个样子的呢?

其实,这正是之前所说的:它们其实就是 JavaScript 于 CSS 的改变的,也就是说浏览器当中的 DOM 节点是由 CSS 和 JavaScript 的改变,最终改变的不是 HTML 代码,或者它的文档中的内容,改变的其实是浏览器中 DOM 排版,要注意的是:这个变化是发生在 浏览器的显示层面 实际上 HTML 的根本没有发生任何的变化。

上面我说到了页面的渲染过程,能够说明刚才我们做的实验得到的结果。

上图的步骤可以让你更加的清晰。

从开始,用户输入了一个网址(这是在用户界面组件当中进行的一个操作),那么当用户回车之后便进入了浏览器引擎的工作流程当中,接着就会根据 HTML 文档当中的内容去加载对应的资源(例如:图片、视频、音频、文字等等),这时候其实渲染引擎和三大解释器已经开始工作了,要不然浏览器也不知道到底需要去加载什么样的资源,那么资源的加载和代码的解释是同步进行的。最后渲染引擎按照三大解释器的解释结果来操作 DOM,也就是重新把页面内容进行排版,把排版得到的结果呈现给用户(也就是我们看到的网页内容)以上就是浏览器的一个工作流程。

4. 编程语言或工具与浏览器的差异

操作:用浏览器打开指定网址

这里我们需要打开浏览器,然后访问一个网站(例如:GitChat

可以看到浏览器访问之后可以,我们得到的是一个错落有致,排版精美的一个页面。那么我们试一试用代码或者用工具来请求一下同样的网址,看看会得到什么样的结果,打开 IDE 也就是 Pycharm。

这里我们使用 requests 库GitChat发出网络请求。并且打印请求得到的内容。

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author:AI悦创 @DateTime :2020/1/12 13:53 @Function :功能  Development_tool :PyCharm
# code is far away from bugs with the god animal protecting
#    I love animals. They taste delicious.
import requests

url = 'https://gitbook.cn/'

html = requests.get(url).text
print(html)

# -------------输出-------------
"C:\Program Files\Python37\python.exe" "D:/daima/pycharm_daima/JavaScript 逆向课程/01-探寻 JavaScript 反爬虫的根本原因/test_1.py"
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, user-scalable=no"><title>GitChat</title><meta name="description" content="GitChat 是一款基于微信平台的知识分享产品。通过这款产品我们希望改变IT知识的学习方式。"><meta name="robots" content="index,follow"><meta name="keywords" content="GitChat,机器学习,大数据,程序员,用户体验,软件开发,知识付费,技术分享"><meta name="baidu-site-verification" content="BRkuL6TTfM"><link href="/dist/site/gitbook/bundle1.css" rel="stylesheet"><script src="/dist/site/gitbook/js1.js"></script><script src="/dist/js/jquery.lazyload.min.js"></script><link href="/css/gitbook/common/common.css" rel="stylesheet"><script src="/dist/gitbook/js/common.js"></script><link rel="icon" type="image/png" href="https://images.gitbook.cn/FrfR1mB39xM-U6iSAmDCpxWVxvoa" sizes="16x16"><link rel="icon" type="image/png" href="https://images.gitbook.cn/FrfR1mB39xM-U6iSAmDCpxWVxvoa" sizes="32x32"></head><link href="/dist/site/gitchat/bundle2.css" rel="stylesheet"><link rel="stylesheet" href="/dist/gitchat/css/mazi.css"><link rel="stylesheet" href="/dist/css/bootstrap.min.css"><link rel="stylesheet" href="/dist/gitbook/css/indexGitChat.css"><script src="/dist/js/ScrollMagic.min.js"></script><body><link rel="stylesheet" href="/dist/gitbook/css/mMaziJade.css"><div class="container_view"><link rel="stylesheet" href="/css/gitbook/topV6.css"><link rel="stylesheet" href="/dist/gitbook/css/topV6.css"><div id="header" class="headroom hidden-md hidden-lg hidden-sm top_box"><div style="float: left;-webkit-animation-name:none;animation-name:none;" class="container hidden-md hidden-lg hidden-sm"><ul id="gn-menu" class="gn-menu-main"><li class="gn-trigger"><a class="gn-icon gn-icon-menu"><span>Menu</span></a><nav class="gn-menu-wrapper"><div class="gn-scroller"><ul style="border-bottom:0" class="gn-menu"><li><a href="/" class="icon lnr-home">首 页</a></li><li><a href="/gitchat/columns" class="icon lnr-rocket">专 栏</a></li><li><a href="/gitchat/series/list" class="icon lnr-diamond">专 题</a></li><li><a href="/gitchat/geekbooks" class="icon lnr-book">电子书</a></li><li><a href="/books/5b398139328f856827673b50/index.html" class="icon lnr-earth">关于我们</a></li><li><a class="icon lnr-text-align-justify">活动分类</a><div class="activity_type clearfix"><a href="/gitchat/categories/58e84f875295227534aad506/1">前端</a><a href="/gitchat/categories/58e84f53ec8e9e7b34457809/2">人工智能</a><a href="/gitchat/categories/58e84f6bad952d6b3428af9a/3">架构</a><a href="/gitchat/categories/5953698a3d38293ecceacb89/4">区块链</a><a href="/gitchat/categories/58e84f1584c651693437f27c/5">职场</a><a href="/gitchat/categories/59c491948fee063dc3c447ab/6">编程语言</a><a href="/gitchat/categories/58e84f31ad952d6b3428af99/7">技术管理</a><a href="/gitchat/categories/58e84f7bec8e9e7b3445780d/8">大数据</a><a href="/gitchat/categories/591171a3e692d5280d8157b6/9">移动开发</a><a href="/gitchat/categories/58e84f2284c651693437f27d/10">产品与运营</a><a href="/gitchat/categories/58e84f425295227534aad502/11">测试</a><a href="/gitchat/categories/591f073981be962a981acf18/12">安全</a><a href="/gitchat/categories/5901bd477b61a76bc4016423/13">运维</a></div><div style="margin:0 auto;width:90%;margin-top: 180px;"></div></li></ul></div></nav></li>>严选</span></div><div class="chat_list"><a href="/gitchat/activity/5e17e817c01d3c1ce1be3e2f" target="_blank" class="chat_item">
内容太多省略!
内容太多省略!
内容太多省略!
内容太多省略!
内容太多省略!
内容太多省略!
内容太多省略!
内容太多省略!

})
function changeHomeColumn(num) {
    $('#syncColumn').addClass("syncColumn");
    $.ajax({
        url: "/gitchat/homepage/change/column/" + num,
        type: "GET",
        contentType: "application/json; charset=utf-8",
        success: function (data, status) {
            if (status == 'success' && data.code == 0) {
                $('#homeColumns').html('');
                $('#homeColumns').append(data.data);
                $('#changeColumns').attr('onclick', 'changeHomeColumn(' + data.next + '); return false;')
                $('#syncColumn').removeClass("syncColumn");
            }
        }
    });
}</script></html>

Process finished with exit code 0

我们得到的就是 HTML 代码,没有经过渲染。

接下来我们借助工具来操作一下,工具:PostMan

这样在下面就会得到我们的响应正文,可以看到和 Python 代码的结果是完全一样的,并没有排版过,也没有请求到任何图片之类的资源。所以,我们请求得到的只是 HTML代码。实际上就是 GitChat的源代码,我们可以在谷歌浏览器访问网页之后,右键选择显示网页源代码看到得到的页面也是和我们前面得到的代码时一样的。

刚刚我们用了几种不同的方式来访问了我们的 GitChat我们用一张图来解析:

由图可知,我们浏览器可以得到其他所需要的内容,而工具得到的只是 HTML。

这其实也就是:浏览器与其他工具的差异。准确来说,是因为其他工具当中没有 JavaScript 解释器,这里要注意 CSS 和 JavaScript 的情况时一样的也就是说可以利用其他工具当中没有 CSS 解释器和渲染引擎的特点来实现反爬虫。实际工作中由非常多这样的应用,例如我们常常听到的字体反爬虫、文本偏移反爬虫和文本混淆反爬虫手段等等。

AI悦创·创造不同!
AI悦创 » 01-探寻 JavaScript 反爬虫的根本原因

Leave a Reply