自定义chrome.devtools.network的Chrome插件

本文要实现的内容

通过chrome提供的网络接口,得到访问某个网站后,所请求的所有链接,将符合要求的链接过滤保存到文件中

实现在chrome中按下F12,Network选项卡一样的功能

在这里插入图片描述

chrome扩展(即插件)简介

学习Chrome插件开发有什么意义

增强浏览器功能,轻松实现属于自己的“定制版”浏览器,等等。

Chrome插件提供了很多实用API供我们使用,包括但不限于:

  • 书签控制
  • 下载控制
  • 窗口控制
  • 标签控制
  • 网络请求控制,各类事件监听
  • 自定义原生菜单
  • 完善的通信机制
  • 等等

为什么是Chrome插件而不是Firefox插件

  • Chrome占有率更高,更多人用
  • 开发更简单
  • 应用场景更广泛,Firefox插件只能运行在Firefox上,而Chrome除了Chrome浏览器之外,还可以运行在所有webkit内核的国产浏览器,比如360极速浏览器、360安全浏览器、搜狗浏览器、QQ浏览器等等
  • 除此之外,Firefox浏览器也对Chrome插件的运行提供了一定的支持

了解chrome插件

什么是chrome插件扩展

偷个懒,直接摘抄过来

Extensions are small software programs that customize the browsing experience. They enable users to tailor Chrome functionality and behavior to individual needs or preferences. They are built on web technologies such as HTML, JavaScript, and CSS.

An extension must fulfill a single purpose that is narrowly defined and easy to understand. A single extension can include multiple components and a range of functionality, as long as everything contributes towards a common purpose.

A screenshot of an extension's icon in the browser bar User interfaces should be minimal and have intent. They can range from a simple icon, such as the Google Mail Checker extension shown on the right, to overriding an entire page.

Extension files are zipped into a single .crx package that the user downloads and installs. This means extensions do not depend on content from the web, unlike ordinary web apps.

怎样开始chrome插件开发

chrome插件开发其实简单的两个文件即可解决问题,最核心的不过是manifest.json,manifest.json在该网页中有详细说明:
https://developer.chrome.com/extensions/manifest

如果你需要一个系列的教程,带你开始做chrome插件,那么可以参考这里的:
https://developer.chrome.com/extensions/getstarted

测试开始使用chrome插件功能

打开chrome的开发者模式

浏览器中输入

chrome://extensions/

右边打开

在这里插入图片描述

写插件前的准备

插件的功能如下

  • 通过插件得到网页的元素,找到百度网页的输入框
  • 输入框中填入"test"
  • 自动提交搜索

新建文件夹chrome

在文件夹中新建两个文件,分别为index.js和manifest.json

index.js的内容如下

var elem=document.getElementById('kw'); // 找到百度搜索的输入框
elem.value = "test"; // 输入内容
var searchButton=document.getElementById('su'); // 找到百度搜索的按钮
searchButton.click(); // 按下
console.log("end...");

manifest.json的内容如下

{
    "manifest_version":2,
    "version":"1.0.0",
    "name":"myPlug",
    "description":"test插件",
    "browser_action":{},
    "permissions":["*://www.baidu.com/"],
    "background":{},
    "content_scripts":[{
            "matches":["*://www.baidu.com/*"],
            "js":["index.js"],
            "run_at":"document_end",
            "all_frames":true
        }]
}

在chrome中安装插件

在这里插入图片描述

现在chrome文件夹,即可完成安装

在这里插入图片描述

测试功能

浏览器中打开

https://www.baidu.com/

看到如下

在这里插入图片描述

开发插件完成功能

与上个例子的不同

要想使用chrome提供的chrome.devtools.network,需要使用Developer Tools in the Network panel

简单来说就是需要新建一个html(充当panel的作用),在html中再另外引入.js来使用devtools.network

得到网络请求控制

新的manifest.json

需要注意,不同的permissions

{
    "name":"devtools",
    "version":"1.0.0",
    "minimum_chrome_version":"18.0",
    "description": "show request url",
    "devtools_page": "devtools.html",
	"permissions":["webRequest","webRequestBlocking"],
    "background":{},
    "manifest_version":2
}

新建一个devtools.html

内容如下,只是简单的引入需要使用到的js文件

<!DOCTYPE html>
<html>
<head></head>
<body>
    <script type="text/javascript" src="js/devtools.js"></script>
</body>
</html>

devtools.js的内容

chrome.devtools.network.onRequestFinished.addListener(
  function(request) {
	  chrome.devtools.inspectedWindow.eval(
		  'console.log("request.url: " + unescape("' +
			  escape(request.request.url) + '"))');
	  console.log("zengraoli"); // 不能直接输出
});

在chrome中做测试

在这里插入图片描述

完成一个带面板的network功能

manifest.json内容如下

使用一个为devtools.html的html网页

{
    "name":"devtools",
    "version":"1.0.0",
    "minimum_chrome_version":"18.0",
    "description": "show request url",
    "devtools_page": "devtools.html",
	"permissions":["webRequest","webRequestBlocking"],
    "background":{},
    "manifest_version":2
}

devtools.html内容如下

作为一个中转html页面,把index.js引入进来

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>showUrl</title>
</head>
<body>
    <script src="index.js"></script>
</body>
</html>

index.js内容如下

利用chrome.devtools提供的接口,创建一个panel,所对应的页面为panel.html

const CD = chrome.devtools;

CD.panels.create(
    "showUrl",
    "panel.html", // 这个devtools拓展真正的操作页面
)

panel.html内容如下

注意其中用到了jq

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>what</title>
    <link rel="stylesheet" href="panel.css">
</head>
<body>
    <div class="show">
        <h1>请求信息</h1>
        <table class="list">
            <tr>
                <th>方法</th>
                <th>地址</th>
                <th>状态</th>
            </tr>
        </table>
    </div>
    <script src="jquery-3.4.1.min.js"></script>
    <script src="panel.js"></script>
</body>
</html>

panel.js内容如下

panel.js文件中其实是用到了jq去追加表格内容的

const CD = chrome.devtools;

//devtools中不认识console.log。使用自带的api inspectedWindow 来弄一个它认识的
const log = (...params) => CD.inspectedWindow.eval(`console.log(...${JSON.stringify(params)})`);

//服务器状态码对应文字 word 以及描述 desc
// status对应文案 网上找的,如果有不对的,希望指出。
const statusText={
    "200":{
        word:"成功",
        desc: "服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。"
    },
    "201":{
        word: "已创建",
        desc: "请求成功且服务器已创建了新的资源。"
    },
    "202":{
        word:"已接受",
        desc: "服务器已接受了请求,但尚未对其进行处理。"
    },
    "203":{
        word: "非授权信息",
        desc: "服务器已成功处理了请求,但返回了可能来自另一来源的信息。"
    },
    "204":{
        word:"无内容",
        desc: "服务器成功处理了请求,但未返回任何内容。"
    },
    "205":{
        word:"充值内容",
        desc: "服务器成功处理了请求,但未返回任何内容。与 204 响应不同,此响应要求请求者重置文档视图(例如清除表单内容以输入新内容)。 "
    },
    "206":{
        word:"部分内容",
        desc: "服务器成功处理了部分 GET 请求。"
    },
    "300":{
        word:"多种选择",
        desc:"服务器根据请求可执行多种操作。服务器可根据请求者 来选择一项操作,或提供操作列表供其选择。 "
    },
    "301": {
        word: "永久请求",
        desc: "请求的网页已被永久移动到新位置。服务器返回此响应时,会自动将请求者转到新位置。您应使用此代码通知搜索引擎蜘蛛网页或网站已被永久移动到新位置。"
    },
    "302": {
        word: "临时移动",
        desc: " 服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。会自动将请求者转到不同的位置。但由于搜索引擎会继续抓取原有位置并将其编入索引,因此您不应使用此代码来告诉搜索引擎页面或网站已被移动。 "
    },
    "303": {
        word: "查看其他位置",
        desc: "当请求者应对不同的位置进行单独的 GET 请求以检索响应时,服务器会返回此代码。对于除 HEAD 请求之外的所有请求,服务器会自动转到其他位置。 "
    },
    "304": {
        word: "未修改",
        desc: "自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。"
    },
    "305": {
        word: "使用代理",
        desc: "请求者只能使用代理访问请求的网页。如果服务器返回此响应,那么,服务器还会指明请求者应当使用的代理。"
    },
    "306": {
        word: "",
        desc: ""
    },
    "307": {
        word: "重定向",
        desc: "服务器目前正从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。会自动将请求者转到不同的位置。但由于搜索引擎会继续抓取原有位置并将其编入索引,因此您不应使用此代码来告诉搜索引擎某个页面或网站已被移动。"
    },
    "400": {
        word: "错误请求",
        desc: "服务器不理解请求的语法。"
    },
    "401": {
        word: "身份验证错误",
        desc: "此页要求授权。您可能不希望将此网页纳入索引。"
    },
    "402": {
        word: "",
        desc: ""
    },
    "403": {
        word: "禁止",
        desc: "服务器拒绝请求。"
    },
    "404": {
        word: "未找到",
        desc: "服务器找不到请求的网页。例如,对于服务器上不存在的网页经常会返回此代码。"
    },
    "405": {
        word: "方法禁用",
        desc: "禁用请求中指定的方法。"
    },
    "406": {
        word: "不接受",
        desc: "无法使用请求的内容特性响应请求的网页。 "
    },
    "407": {
        word: "需要代理授权",
        desc: "请求者必须授权使用代理。如果服务器返回此响应,还表示请求者应当使用代理。 "
    },
    "408": {
        word: "请求超时",
        desc: "服务器等候请求时发生超时。 "
    },
    "409": {
        word: "冲突",
        desc: "服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。服务器在响应与前一个请求相冲突的 PUT 请求时可能会返回此代码,以及两个请求的差异列表。 "
    },
    "410": {
        word: "已删除",
        desc: "请求的资源永久删除后,服务器返回此响应。该代码与 404(未找到)代码相似,但在资源以前存在而现在不存在的情况下,有时会用来替代 404 代码。如果资源已永久删除,您应当使用 301 指定资源的新位置。 "
    },
    "411": {
        word: "需要有效长度",
        desc: "服务器不接受不含有效内容长度标头字段的请求。"
    },
    "412": {
        word: "未满足前提条件",
        desc: "服务器未满足请求者在请求中设置的其中一个前提条件。"
    },
    "413": {
        word: "请求实体过大",
        desc: "服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。 "
    },
    "414": {
        word: "URI过长",
        desc: "请求的 URI(通常为网址)过长,服务器无法处理。 "
    },
    "415": {
        word: "不支持的媒体类型",
        desc: "请求的格式不受请求页面的支持。 "
    },
    "416": {
        word: "请求范围不符合要求",
        desc: "如果页面无法提供请求的范围,则服务器会返回此状态码。 "
    },
    "417": {
        word: "未满足期望",
        desc: "服务器未满足‘期望’请求标头字段的要求。"
    },
    "500": {
        word: "服务器内部错误",
        desc: "服务器遇到错误,无法完成请求。 "
    },
    "501": {
        word: "尚未实施",
        desc: "服务器不具备完成请求的功能。例如,当服务器无法识别请求方法时,服务器可能会返回此代码。"
    },
    "502": {
        word: "网关错误",
        desc: "服务器作为网关或代理,从上游服务器收到了无效的响应。 "
    },
    "503": {
        word: "服务器当前不可用",
        desc: "目前无法使用服务器(由于超载或进行停机维护)。通常,这只是一种暂时的状态。"
    },
    "504": {
        word: "网关超时",
        desc: "服务器作为网关或代理,未及时从上游服务器接收请求。 "
    },
    "505": {
        word: "HTTP版本不受支持",
        desc: "服务器不支持请求中所使用的 HTTP 协议版本"
    }
}

//注册回调函数,每一个http请求完成后,都会执行。
CD.network.onRequestFinished.addListener((...args)=>{
	 const [{
        request,
        response
    }] = args;
    log(request);

    //本事件 每一次请求都会触发,所以使用jq的append
    $(".list").append(`<tr class="${response.status !== 200 ? 'red' : ''}">
            <td class="method"><div>${request.method}</div></td>
            <td class="url"><div>${request.url}</div></td>
            <td class="status">
                <span>${response.status}</span>
            </td>
            <td class="statusText">
                <span class='word'>${statusText[response.status].word}</span>
                <span class='desc'>${statusText[response.status].desc}</span>
            </td>
        </tr>`);
});

$("body").on("mouseenter", ".statusText .word", function () {
    $(this).next().show();
});
$("body").on("mouseleave", ".statusText .word", function () {
    $(this).next().hide();
});

panel.css内容如下

可能这个作用不是太大

.list{
    margin: 10px;
}
.list li.red{
    color:red;
}
.list tr{
    width: 1100px;
    border: 1px solid blue;
    margin: 10px;
}
.method{
    width: 100px;
}
.url div{
    width: 800px;
    word-wrap:break-word;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
}
.status{
    width: 100px;
    text-align: center;
}
.statusText{
    position: relative;
    width: 100px;
    text-align: center;
}
.word{
    cursor: pointer;
}
.desc{
    display: none;
    position: absolute;
    z-index:99;
    right: 70px;
    top: 20px;
    padding: 5px 10px;
    min-width: 180px;
    text-align: center;
    border: 1px solid rgb(18, 121, 218);
    background-color: rgb(18, 121, 218);
    color:#fff;
    border-radius: 2px;
}

浏览器的测试如下

在这里插入图片描述

示例代码下载

https://download.csdn.net/download/zengraoli/12120289

参考链接

  • https://blog.csdn.net/github_35631540/article/details/89842146
  • https://blog.csdn.net/hezheqiang/article/details/79310713
  • https://www.cnblogs.com/rwxwsblog/p/4490530.html
  • http://open.chrome.360.cn/extension_dev/devtools.network.html
  • https://juejin.im/post/5c246ad2518825566d238d4d#heading-2
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
这段代码主要是使用 Selenium 和 DevTools 来获取网络请求的相关信息。下面是 Python 代码的转换: ```python from selenium.webdriver import Chrome from selenium.webdriver.chrome.service import Service from msedge.selenium_tools import Edge, EdgeOptions from selenium.webdriver.common.desired_capabilities import DesiredCapabilities # 创建 Chrome 浏览器实例 caps = DesiredCapabilities.CHROME.copy() caps['goog:loggingPrefs'] = {'performance': 'ALL'} service = Service('/path/to/chromedriver') driver = Chrome(service=service, desired_capabilities=caps) # 创建 Edge 浏览器实例 caps = DesiredCapabilities.EDGE.copy() caps['goog:loggingPrefs'] = {'performance': 'ALL'} options = EdgeOptions() options.use_chromium = True driver = Edge(options=options, desired_capabilities=caps) # 获取 DevToolsSession devTools = driver session = devTools.get_devtools_session() # 启用 Network,并监听 DevToolsEventReceived 事件 session.domains['Network'].enable_network() LIST_DevToolsSession = [] # 定义一个列表用于存储 DevToolsSession def on_event_received(sender, e): global LIST_DevToolsSession LIST_DevToolsSession.append({ 'EventName': e.EventName, 'body': e.EventData }) session.devtools_event_received += on_event_received # 获取 DevToolsSession_实体 _session = next((s for s in LIST_DevToolsSession if s['Session']['是验证']), None) if _session: 目标会话 = next((s for s in LIST_DevToolsSession if s['Session']['requestId'] == _session['Session']['requestId'] and s['EventName'] == 'ResponseReceivedExtraInfo'), None) if 目标会话: 后置令牌_未处理 = 目标会话['Session']['headers']['set-cookie'] # .Replace("\n", ";"); 后置令牌 = CookieHelper.GetCookieStrByHeader换行(后置令牌_未处理) if 后置令牌: driver.quit() ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值