15分钟手摸手教你写个可以操控Chrome的插件

故事背景

事情是这样的呢

创新互联网站建设提供从项目策划、软件开发,软件安全维护、网站优化(SEO)、网站分析、效果评估等整套的建站服务,主营业务为成都网站制作、成都网站建设、外贸营销网站建设成都app软件开发公司以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。创新互联深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

友人 A: 能不能帮我整一个 chrome 插件?

我: 啥插件?

友人 A: 通过后端服务或者 python 脚本通信 chrome 插件能够操作浏览器

我: 你小子是想爬数据吧?直接用现成的 python 框架或者 谷歌的 puppeteer 就能操控浏览器吧

友人 A: 你说的路子我早就试过了,对于反爬检测高的网站一下就能检测你的无头浏览器的相应特征,所以就用平时用的浏览器就能以真乱真

我: 老是整这些花里胡哨的,有啥用呀

友人 A: 10 斤小龙虾!

我:成交!!!

整体的思路

根据朋友以上的要求,我们可以简单的得出一下的通信流程:

具体有疑问没关系,我们只要知道大体的流程是这样通信的即可

github 地址 每个 commit 对应相应的步骤

第一步 创建一个 chrome 插件

我们首先来创建一个啥功能都没有的 chrome 插件

目录如下所示

manifest.json

 
 
 
 
  1. // manifest.json 
  2.     "manifest_version": 2, // 配置文件的版本 
  3.     "name": "SocketEXController", // 插件的名称 
  4.     "version": "1.0.0", // 插件的版本 
  5.     "description": "Chrome SocketEXController",// 插件描述 
  6.     "author": "wjryours", // 作者 
  7.     "icons": { 
  8.         "48": "icon.png",// 对应尺寸的图标路径 我这边全部用一个了 
  9.         "128": "icon.png" 
  10.     }, 
  11.     "browser_action": { 
  12.         "default_icon": "icon.png", // 图标 
  13.         "default_popup": "popup.html" // 点击右上角的图标的 popup 浮层 html 文件 
  14.     }, 
  15.     "background": { 
  16.         // 会一直常驻的后台 JS 或后台页面 
  17.         // 2 种指定方式,如果指定 JS,那么会自动生成一个背景页 
  18.         "page": "background.html" 
  19.     }, 
  20.     "content_scripts": [ 
  21.         { 
  22.             // 允许哪些域名下加载 注入的 JS 
  23.             // "matches": ["http://*/*", "https://*/*"], 
  24.             // "" 表示匹配所有地址 
  25.             "matches": [ 
  26.                 "
  27.             ], 
  28.             "js": [ 
  29.                 "content-script.js" 
  30.             ], 
  31.             "run_at": "document_start" 
  32.         } 
  33.     ], 
  34.     "permissions": [ 
  35.         "contextMenus", // 右键菜单 
  36.         "tabs", // 标签 
  37.         "notifications", // 通知 
  38.         "webRequest", // web 请求 
  39.         "webRequestBlocking", // 阻塞式 web 请求 
  40.         "storage", // 插件本地存储 
  41.         "http://*/*", // 可以通过 executeScript 或者 insertCSS 访问的网站 
  42.         "https://*/*" // 可以通过 executeScript 或者 insertCSS 访问的网站 
  43.     ], 

js

 
 
 
 
  1. // background.js 
  2. console.log('background.js') 
 
 
 
 
  1. // popup.js 
  2. console.log('popup.js') 
 
 
 
 
  1. // content-script.js 
  2. console.log('content-script.js loaded') 

html

 
 
 
 
  1.  
  2.  
  3.  
  4.  
  5.      
  6.      
  7.      
  8.     SocketController Popup 
  9.      
  10.      
  11.  
  12.  
  13.     popup 
  14.  
  15.  
 
 
 
 
  1.  
  2.  
  3.  
  4.  
  5.  
  6.      
  7.      
  8.      
  9.     SocketController 
  10.  
  11.  
  12.  
  13.      
  14.         bg-container 
  15.     
 
  •  
  •  
  •  
  • 然后在 chrome 的扩展程序页加载我们的文件目录 即可

    然后我们启用插件 随手打开一个页面就发现我们的插件已经生效了

    第二步 在本地创建 websocket 的服务

    正如上面的通信流程所示,我们还需要在本地创建一个可用的 websocket 来发送信息给 chrome 插件

    为了方便起见,我这边就用 node 的 express 以及 socket.io 这个库来启用

    目录结构和代码都很简单

     
     
     
     
    1. // index.js  用来创建 node 服务 
    2. const express = require('express') 
    3. const app = express() 
    4. const http = require('http') 
    5. const server = http.createServer(app) 
    6. const { Server } = require("socket.io") 
    7. const io = new Server(server) 
    8.  
    9. app.get('/', (req, res) => { 
    10.     res.sendFile(__dirname + '/index.html') 
    11. }) 
    12.  
    13. io.on('connection', (socket) => { 
    14.     console.log('a user connected') 
    15.     socket.on('disconnect', () => { 
    16.         console.log('user disconnected'); 
    17.     }); 
    18.     socket.on('webviewEvent', (msg) => { 
    19.         console.log('webviewEvent: ' + msg); 
    20.         io.emit('webviewEvent', msg); 
    21.         // socket.broadcast.emit('chat message', msg); 
    22.     }); 
    23.     socket.on('webviewEventCallback', (msg) => { 
    24.         console.log('webviewEventCallback: ' + msg); 
    25.         io.emit('webviewEventCallback', msg); 
    26.     }); 
    27. }) 
    28.  
    29.  
    30. server.listen(9527, () => { 
    31.     console.log('listening on 9527') 
    32. }) 
     
     
     
     
    1.   
    2.  
    3.  
    4.  
    5.  
    6.  
    7.   Socket.IO Page 
    8.