Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【测试】python 模拟snmp-se

【测试】python 模拟snmp-se

作者头像
py3study
发布于 2020-01-10 02:44:15
发布于 2020-01-10 02:44:15
1.2K00
代码可运行
举报
文章被收录于专栏:python3python3
运行总次数:0
代码可运行

如下脚本,模拟windows和linux上的snmp-agent,返回数据给snmp请求者。

直接上代码吧:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# -*- coding: utf-8 -*-
import binascii, struct
import socket
import time
from threading import Thread

'''
windows OID
1.3.6.1.2.1.25.2.3.1.6.1 [ObjectIdentifier] //硬盘 
1.3.6.1.2.1.25.2.3.1.6.2 [ObjectIdentifier] //硬盘 
1.3.6.1.2.1.25.2.3.1.6.3 [ObjectIdentifier] //硬盘 
1.3.6.1.2.1.25.2.3.1.6.4 [ObjectIdentifier] //硬盘 
1.3.6.1.2.1.25.2.3.1.6.5 [ObjectIdentifier] //光盘 
1.3.6.1.2.1.25.2.3.1.6.6 [ObjectIdentifier] //光盘 
1.3.6.1.2.1.25.2.3.1.6.7 [ObjectIdentifier] //虚拟内存 
1.3.6.1.2.1.25.2.3.1.6.8 [ObjectIdentifier] //物理内存
OID号不固定,当只有一块硬盘,一个光驱时,物理内存占用OID1.2.52.1占用一般0,不是真实硬盘,不知道是什么意思,真正硬盘占用从2.2开始)
'''

#a 是一个真实的请求内容,def test_parse()函数可以将他解析出来,并打印出密码,请求类型,请求IDOID对象
a = '''0x30, 0x82, 0x01, 0x09, 0x02, 0x01, 0x01, 0x04, 
0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0xa0, 
0x81, 0xfb, 0x02, 0x04, 0x4a, 0xbb, 0x2b, 0xac, 
0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x30, 0x81, 
0xec, 0x30, 0x0d, 0x06, 0x09, 0x2b, 0x06, 0x01, 
0x02, 0x01, 0x19, 0x02, 0x02, 0x00, 0x05, 0x00, 
0x30, 0x0f, 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x02, 
0x01, 0x19, 0x03, 0x03, 0x01, 0x02, 0x01, 0x05, 
0x00, 0x30, 0x0f, 0x06, 0x0b, 0x2b, 0x06, 0x01, 
0x02, 0x01, 0x19, 0x02, 0x03, 0x01, 0x05, 0x01, 
0x05, 0x00, 0x30, 0x0f, 0x06, 0x0b, 0x2b, 0x06, 
0x01, 0x02, 0x01, 0x19, 0x02, 0x03, 0x01, 0x05, 
0x02, 0x05, 0x00, 0x30, 0x0f, 0x06, 0x0b, 0x2b, 
0x06, 0x01, 0x02, 0x01, 0x19, 0x02, 0x03, 0x01, 
0x05, 0x03, 0x05, 0x00, 0x30, 0x0f, 0x06, 0x0b, 
0x2b, 0x06, 0x01, 0x02, 0x01, 0x19, 0x02, 0x03, 
0x01, 0x05, 0x04, 0x05, 0x00, 0x30, 0x0f, 0x06, 
0x0b, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x19, 0x02, 
0x03, 0x01, 0x06, 0x01, 0x05, 0x00, 0x30, 0x0f, 
0x06, 0x0b, 0x2b, 0x06, 0x01, 0x02, 0x01, 0x19, 
0x02, 0x03, 0x01, 0x06, 0x02, 0x05, 0x00, 0x30, 
0x0f, 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x02, 0x01, 
0x19, 0x02, 0x03, 0x01, 0x06, 0x03, 0x05, 0x00, 
0x30, 0x0f, 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x02, 
0x01, 0x19, 0x02, 0x03, 0x01, 0x06, 0x04, 0x05, 
0x00, 0x30, 0x0f, 0x06, 0x0b, 0x2b, 0x06, 0x01, 
0x02, 0x01, 0x19, 0x02, 0x03, 0x01, 0x06, 0x05, 
0x05, 0x00, 0x30, 0x0f, 0x06, 0x0b, 0x2b, 0x06, 
0x01, 0x02, 0x01, 0x19, 0x02, 0x03, 0x01, 0x06, 
0x06, 0x05, 0x00, 0x30, 0x0f, 0x06, 0x0b, 0x2b, 
0x06, 0x01, 0x02, 0x01, 0x19, 0x02, 0x03, 0x01, 
0x06, 0x07, 0x05, 0x00, 0x30, 0x0f, 0x06, 0x0b, 
0x2b, 0x06, 0x01, 0x02, 0x01, 0x19, 0x02, 0x03, 
0x01, 0x06, 0x08, 0x05, 0x00'''

class snmpReqParse:
    struct_type = {0x02:'INTEGER_TYPE',
                   0x30:'SQUENCE_TYPE',
                   0x04:'OCTET_TYPE',
                   0X05:'NULL_TYPE', 
                   0x06:'OBJID_TYPE', 
                   0xa0:'GET_REQ_TYPE', 
                   0xa5:'GET_BULKREQ_TYPE', 
                   0Xa2:'RESPONSE_TYPE'}
    def __init__(self, request):
        self.request = request
        self.objidList = []
        self.requestID = None
        self.getReqType = 0xa0
        self.publicPasswd = ''
        self.parse()
    def parse(self):
        currentPos = self.parse_header1()
        if not currentPos:
            print "parse SNMP header failed!"
            return
        currentPos = self.parse_header2(currentPos)
        if not currentPos:
            print "parse SNMP header failed!"
            return
        self.parse_obj(currentPos)    
    def parse_obj(self, pos):
        #开始解析obj对象了    
        currentPos = pos
        stype = struct.unpack('B', self.request[currentPos:currentPos+1])[0]
        currentPos += 1
        currentPos = self.struct_parse(currentPos)[0] 
        while len(self.request[currentPos:]) != 0:
            stype = struct.unpack('B', self.request[currentPos:currentPos+1])[0]
            currentPos += 1
            currentPos = self.struct_parse(currentPos)[0]
            stype = struct.unpack('B', self.request[currentPos:currentPos+1])[0]
            if stype != 0x06:
                print "wrong type coding, must be 0x06"
                break
            currentPos += 1
            currentPos, stringLen = self.struct_parse(currentPos)
            objid = struct.unpack(stringLen*'B', self.request[currentPos:currentPos+stringLen])
            objid1stStr = str(divmod(objid[0], 40)[0]) + '.' + str(divmod(objid[0], 40)[1])
            #当obj中每一段中有值大于127时,则后面一个数应该和前面一个数拼起来,例如0x8F0X65,应该是0x8F*128+65
            templist = []
            temp1 = 0
            for i in objid[1:]:
                if not temp1:
                    if i<=127:
                        templist.append(str(i))
                    else:
                        temp1 = i
                else:
                    templist.append(str((temp1-128)*128+i))
                    temp1 = 0
            objidStr = objid1stStr + '.' + '.'.join(templist)
            self.objidList.append(objidStr)
            currentPos = currentPos+stringLen
            #跳过null type
            currentPos += 2
        #print self.objidList   
    def parse_header2(self, pos):
        #从团体属性密钥结束后,解析到OBject开始
        currentPos = pos
        stype = struct.unpack('B', self.request[currentPos:currentPos+1])[0]
        self.getReqType = stype
        currentPos += 1
        currentPos = self.struct_parse(currentPos)[0]
        stype = struct.unpack('B', self.request[currentPos:currentPos+1])[0]    
        if stype == 0x02:
            startPos = currentPos + 1
            currentPos, stringLen = self.struct_parse(startPos)
            self.requestID = self.request[currentPos:currentPos+stringLen]
            currentPos += stringLen
            #直接跳过error-statues和error-index
            currentPos += 6
            return currentPos
        else:
            print 'wrong type coding ,should be 0x02!'
            return
    def parse_header1(self):
        #start parse,从开始到得到团体属性密钥
        #currentPos为读取数据流的位置
        stype = struct.unpack('B', self.request[0:1])[0]
        if stype == 0x30:
            currentPos = self.struct_parse(1)[0]
            stype = struct.unpack('B', self.request[currentPos:currentPos+1])[0]
            if stype == 0x02:
                startPos = currentPos+1
                currentPos = self.struct_parse(startPos)[0]
                if currentPos - startPos == 1:
                    #不做判断了,直接跳到解析团体关键字
                    startPos = currentPos + 2
                    currentPos, stringLen = self.struct_parse(startPos)
                    self.publicPasswd = self.request[startPos+1:startPos+stringLen+1]
                    currentPos = startPos+stringLen+1 
                    return currentPos
                else:
                    print "wrong SNMP version ,must be v2c!"
            else:
                print "wrong type coding: %s,should be 0x02"%stype
        else:
            print "wrong type coding: %s, should be 0x30 "%stype
    def struct_parse(self, startpos):
        #结构解析,startpos的位置已经是长度字段了,解析出来,最后返回这个结构结尾的pos
        length = struct.unpack('B', self.request[startpos:startpos+1])[0]
        if length == 0x81:
            endpos = startpos + 2
            slen = struct.unpack('B', self.request[startpos+1:endpos])[0]
        elif length == 0x82:
            endpos = startpos + 3
            slen = struct.unpack('!H', self.request[startpos+1:endpos])[0]
        elif length <= 127:
            endpos = startpos + 1
            slen = length
        else:
            print "wrong length coding: "%length
            return
        if len(self.request[endpos:]) < slen:
            print "string is not enough long!"
            return
        return endpos, slen

class snmpResponse:
    OID = {'windows':['1.3.6.1.2.1.25.2.2.0',  #内存总大小(mem_count),integar类型
                  '1.3.6.1.2.1.25.3.3.1.2.1',  #CPU,integar类型
                  '1.3.6.1.2.1.25.2.3.1.5.1',  #值为0,integar类型
                  '1.3.6.1.2.1.25.2.3.1.5.2',  #硬盘总大小,*4096单位为字节数,integar类型
                  '1.3.6.1.2.1.25.2.3.1.5.3',  #光驱总大小,实际为光盘容量,没有光盘时为0,integar类型
                  '1.3.6.1.2.1.25.2.3.1.5.4',  #暂时不清楚是什么,默认我给它赋值0x009a5f,integar类型
                  '1.3.6.1.2.1.25.2.3.1.6.1',  #值为0,integar类型
                  '1.3.6.1.2.1.25.2.3.1.6.2',  #硬盘占用的大小,integar类型
                  '1.3.6.1.2.1.25.2.3.1.6.3',  #光驱大小,和5.3一致
                  '1.3.6.1.2.1.25.2.3.1.6.4',  #虚拟内存大小,一般不关注,integar类型
                  '1.3.6.1.2.1.25.2.3.1.6.5'], #物理内存使用大小(mem_use),integar类型
       #内存使用率计算方法:(mem_use*65535)/(mem_count*1024'linux':['1.3.6.1.4.1.2021.11.11.0',  #CPU剩余,如40
                '1.3.6.1.4.1.2021.4.5.0',  #内存总大小,integar类型
                '1.3.6.1.4.1.2021.4.6.0',  #内存剩余大小,integar类型
                '1.3.6.1.4.1.2021.9.1.9.1']} #硬盘使用百分比,如60, integar类型
    def __init__(self):
        self.getReqType = 0x00
        self.reqPublicPasswd = ''
        self.reqObjList = []
        self.OIDdic = {}
        self.getResType = 0xa2
        self.respondID = 0
        self.error_index = 0
        self.error_status = 0
        self.simDev = { 'publicPasswd':'public', 
                        'platform':'windows', 'CPULOAD':45,
                        'totalMem':1024000, 'usedMem':102400,  #mem单位为kB
                        'totalDisk':512000000, 'usedDisk':100000000}
    def check_request(self):
        if self.getReqType != 0xa0:
            print "this tool can only support get-request"
            return
        if self.reqObjList:
            if self.reqObjList[0] in self.OID['windows']:
                self.simDev['platform'] = 'windows'
                for i in range(0, len(self.reqObjList)):
                    if self.reqObjList[i] not in self.OID['windows']:
                        self.error_index = i + 1
                        self.error_status = 0x02
                        return
                useMemVal = (self.simDev['usedMem']*1024)/65535  
                self.OIDdic = {'1.3.6.1.2.1.25.2.2.0':self.simDev['totalMem'], #内存总大小(mem_count),integar类型
                               '1.3.6.1.2.1.25.3.3.1.2.1':self.simDev['CPULOAD'],  #CPU,integar类型
                              '1.3.6.1.2.1.25.2.3.1.5.1':0,  #值为0,integar类型
                              '1.3.6.1.2.1.25.2.3.1.5.2':self.simDev['totalDisk']/2048,  #硬盘总大小,*4096单位为字节数,integar类型
                              '1.3.6.1.2.1.25.2.3.1.5.3':0,  #光驱总大小,实际为光盘容量,没有光盘时为0,integar类型
                              '1.3.6.1.2.1.25.2.3.1.5.4':39519,  #暂时不清楚是什么,默认我给它赋值0x009a5f,integar类型
                              '1.3.6.1.2.1.25.2.3.1.6.1':0,  #值为0,integar类型
                              '1.3.6.1.2.1.25.2.3.1.6.2':self.simDev['usedDisk']/2048,  #硬盘占用的大小,integar类型
                              '1.3.6.1.2.1.25.2.3.1.6.3':0,  #光驱大小,和5.3一致
                              '1.3.6.1.2.1.25.2.3.1.6.4':10835,  #虚拟内存大小,一般不关注,integar类型
                              '1.3.6.1.2.1.25.2.3.1.6.5':useMemVal}
            elif self.reqObjList[0] in self.OID['linux']:
                self.simDev['platform'] = 'linux'
                for i in self.reqObjList:
                    if i not in self.OID['linux']:
                        print 'can not support the OID:', i
                        return
                freeCPU = 100 - self.simDev['CPULOAD']
                usedDisk = (self.simDev['usedDisk']*100)/self.simDev['totalDisk']
                freeMemVal = self.simDev['totalMem'] - self.simDev['usedMem']
                self.OIDdic = {'1.3.6.1.4.1.2021.11.11.0':freeCPU,  #CPU剩余
                               '1.3.6.1.4.1.2021.4.5.0':self.simDev['totalMem'],  #内存总大小,integar类型
                               '1.3.6.1.4.1.2021.4.6.0':freeMemVal,  #内存剩余大小,integar类型
                               '1.3.6.1.4.1.2021.9.1.9.1':usedDisk}   #硬盘使用百分比,如60, integar类型
            else:
                print "the objlist will not be supported!"
                return
        else:
            print "error: objlist is Null!" 
            return
    def build_objbuff(self):
        objbuff = ''    
        if self.error_index:
                for i in self.reqObjList:
                    objbuff += self.coding_obj_and_value(i)
        else:
            for i in self.reqObjList:
                objbuff += self.coding_obj_and_value(i, self.OIDdic[i])
        if not objbuff:
            return
        objbuff = '\x30' + self.coding_of_length(len(objbuff)) + objbuff
        return objbuff        
    def build_snmpbuff(self):
        self.check_request()
        objBuff = self.build_objbuff()
        if not objBuff:
            return
        snmpbuff = ''
        if self.simDev['publicPasswd'] != self.reqPublicPasswd:
            print "public keyword is wrong!"
            return
        else:
            snmpbuff = '\x02' + struct.pack('B', len(self.respondID)) + self.respondID \
                       + '\x02\x01' + struct.pack('B', self.error_status) \
                       + '\x02\x01' + struct.pack('B', self.error_index)
            snmpbuff += objBuff
            snmpbuff = '\xa2' + self.coding_of_length(len(snmpbuff)) + snmpbuff
            snmpbuff = '\x02\x01\x01\x04' + struct.pack('B', len(self.simDev['publicPasswd'])) + self.simDev['publicPasswd'] + snmpbuff
            snmpbuff = '\x30' + self.coding_of_length(len(snmpbuff)) + snmpbuff
            return snmpbuff
    def coding_obj_and_value(self, obj, val=None):
        temps = ''
        temps += self.coding_obj(obj)
        temps = struct.pack('2B', 0x06, len(temps)) + temps
        if val == None:
            temps += '\x05\x00'
        elif str(type(val)) == '<type \'str\'>':
            temps += '\x04' + struct.pack('B', len(val)) + val
        elif str(type(val)) in ['<type \'int\'>', '<type \'long\'>']:
            if val<=2**7:
                temps += '\x02\x01' + struct.pack('B', val)
            elif 2**7<val<=2**15:
                temps += '\x02\x02' + struct.pack('!H', val)
            elif 2**15<val<=2**23:
                temps += '\x02\x03' + struct.pack('!I', val)[1:]
            elif 2**23<val<=2**31:
                temps += '\x02\x04' + struct.pack('!I', val)  
            else:
                print "value is too big!"
                return
        temps = '\x30' + struct.pack('B', len(temps)) + temps
        return temps 
    def coding_of_length(self, slen):
        #SNMP中域长度的编码方式。此函数直接返回长度字段的编码结果
        if slen<=127:
            return struct.pack('B', slen)
        if 127<slen<256:
            return struct.pack('2B', 0x81, slen)
        if 256<=slen<256**2:
            return struct.pack('!BH', 0x82, slen)            
    def coding_obj(self, obj):
        #将1.3.6.XOID打包成字节流
        objlist = obj.split('.')
        objtemplist = []
        objfir1byte = int(objlist[0])*40 + int(objlist[1])
        objtemplist.append(struct.pack('B', objfir1byte))
        for i in objlist[2:]:
            if int(i)>127:
                a, b = divmod(int(i), 128)
                objtemplist.append(struct.pack('2B', a+128, b))
            else:
                objtemplist.append(struct.pack('B', int(i)))
        return ''.join(objtemplist)
    
    
def SNMP_server(serverIP = '', passWd = 'public', SNMPPORT = 161):
    usock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    usock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    usock.bind((serverIP, SNMPPORT))
    while 1:
        message, clientaddr = usock.recvfrom(8192)
        req = snmpReqParse(message)
        res = snmpResponse()
        res.reqPublicPasswd = req.publicPasswd
        res.simDev = read_config()[serverIP]
        res.getReqType = req.getReqType
        res.respondID = req.requestID
        res.reqObjList = req.objidList
        resbuff = res.build_snmpbuff()
        if resbuff:
            usock.sendto(resbuff, clientaddr)
            memUsage = res.simDev['usedMem']*100/res.simDev['totalMem']
            diskUsage = res.simDev['usedDisk']*100/res.simDev['totalDisk']
            if not res.error_index:
                print '########### %s ###########\n\
<%s>\n\
>>you request oid are %s\n\
>>server CPU load percentage is : %s\n\
>>server mem used percentage is : %s\n\
>>server disk used percentage is: %s'%(serverIP, time.ctime(), res.reqObjList,
                      res.simDev['CPULOAD'], memUsage, diskUsage)
            
def test_parse():
    global a
    b = a.replace(', 0x', r'\x')
    c = '\\' + b.replace(', \n0x', r'\x')[1:]
    d = c.replace(r'\x', '')
    request = binascii.a2b_hex(d)
    test = snmpReqParse(request)
    print test.simDev('publicPasswd')
    print hex(test.getReqType)
    print test.requestID
    for i in test.objidList:
        print i
def test_response():
    global a
    b = a.replace(', 0x', r'\x')
    c = '\\' + b.replace(', \n0x', r'\x')[1:]
    d = c.replace(r'\x', '')
    request = binascii.a2b_hex(d)
    test = snmpReqParse(request)
    res = snmpResponse('public')
    res.reqPublicPasswd = test.simDev('publicPasswd')
    res.getReqType = test.getReqType
    res.respondID = test.requestID
    res.reqObjList = test.objidList
    resbuff = res.build_snmpbuff()
    print repr(resbuff)
def read_config():
    import ConfigParser
    cf = ConfigParser.ConfigParser()
    cf.read('snmpServer.ini')
    simSers = {}
    for sec in cf.sections():
        simSers[sec] = {'publicPasswd':cf.get(sec, 'password'),
                       'CPULOAD': cf.getint(sec, 'cpuload'),
                       'totalMem':cf.getint(sec, 'totalMem'), 
                       'usedMem':cf.getint(sec, 'usedMem'),
                       'totalDisk':cf.getint(sec, 'totalDisk'), 
                       'usedDisk':cf.getint(sec, 'usedDisk')}
    return simSers
   
def main():
    sersDic = read_config()
    for s in sersDic.keys():
        print repr(s), 'is listening!'
        t = Thread(target=SNMP_server, args=(s, ))
        t.start()
        time.sleep(1)
       
if __name__=='__main__':
    #test_parse()
    #test_response()
    #serverIP = '172.16.1.102'
    #SNMP_server(serverIP)
    print 'start'
    main()
    raw_input('')

以上服务启动依赖配置文件,配置文件中指定模拟的linux或者windows服务器,可以填写多组,文件存为snmpServer.ini

[192.168.10.102] password = public cpuload = 11 totalMem = 1024000 usedMem = 102400 totalDisk = 512000000 usedDisk = 100000000 [172.16.1.102] password = public cpuload = 30 totalMem = 1024000 usedMem = 204800 totalDisk = 512000000 usedDisk = 300000000

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/08/28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
谷歌浏览器扩展开发的原理与实践(DIY存网文)
我正在参加CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴(文末下载)
悟空聊架构
2025/05/17
1330
谷歌浏览器扩展开发的原理与实践(DIY存网文)
通过浏览器扩展获取本机 MAC 地址
在 Web 技术主导的 B/S 架构项目中,获取终端设备硬件信息(如 MAC 地址)的需求经常会碰到。尽管 Electron/CEF 等混合应用框架可通过系统级 API 轻松实现,但纯浏览器环境下的硬件信息获取则不那么容易。因为现代浏览器基于沙箱机制和隐私保护策略,严格禁止网页直接访问底层硬件资源。
云水木石
2025/03/19
3640
通过浏览器扩展获取本机 MAC 地址
带你快速走进Chrome扩展开发的大门
Chrome 扩展程序通过可以向 Chrome 浏览器添加特性和功能来增强浏览体验,可以构建一些强大的生产力工具,也可以丰富网页的内容,还可以做一些信息的聚合等等。本篇文章将带你通过三个简单的案例带你快速走进Chrome扩展开发的大门。
前端小鑫同学
2023/04/22
8930
带你快速走进Chrome扩展开发的大门
Chrome扩展开发入门
近几年,随着 IE 浏览器的落幕,Chrome(包括使用Chrome内核的浏览器)其实质上已经垄断整个浏览器行业了,就连微软的 Edge 都用上了 Chrome 内核。 可以说,Chrome 的标准,事实上就可以看做是行业标准了。可以预见,Chrome 的发展前景将会非常广阔。
epoos
2022/09/19
4.2K0
Chrome扩展开发入门
使用 WXT 开发浏览器插件(上手使用篇)
WXT (https://wxt.dev/), Next-gen Web Extension Framework. 号称下一代浏览器开发框架. 可一套代码 (code base) 开发支持多个浏览器的插件.
Cloud-Cloudys
2024/03/16
8330
使用 WXT 开发浏览器插件(上手使用篇)
Chrome扩展开发入门体验
****前言**** Chrome浏览器扩展开发算是相当简单的,基本只要掌握HTML+CSS+Javascript,即可快速开发一个属于你的Chrome插件! ---- ****Chrome扩展基本目录结构**** manifest.json 这是一个配置文件,里面记录了扩展的使用范围、作者、版本、其余需要加载的文件等内容; icon.png 这个一看便知,就是扩展的图标~~~ popup.html 点击扩展图标,弹出的面板页面(如果在manifest.json中配置了default
AlicFeng
2018/06/08
1.2K0
从零到一:腾讯云 AI 代码助手 + DeepSeek 写一个浏览器插件
这个实现方案完全使用矢量图形绘制,不依赖任何图片素材,核心游戏逻辑与UI组件分离,便于维护和扩展。游戏控制逻辑完整包含开始/暂停/重置功能,并实现了经典贪吃蛇的所有核心机制。
全栈若城
2025/02/28
1680
从零到一:腾讯云 AI 代码助手 + DeepSeek 写一个浏览器插件
开发者必备!用纯 CSS 搞定网站黑暗模式
最近上线了一个用户管理后台,忙得焦头烂额。没想到上线后的用户反馈让我直冒冷汗:“网站晚上用着太刺眼了,能不能加个黑暗模式?”
前端达人
2025/01/09
1300
开发者必备!用纯 CSS 搞定网站黑暗模式
全流程 Chrome 扩展开发之按键提示
key-prompt 是一个基于 Extension.js 开发工具和其提供的 vue-typescript 模板开发的 Chrome 扩展程序,可以在任意网页的左下方位置显示你对当前页面的键盘操作,其实这是一个无聊的扩展程序,只当图一乐儿 😁
前端小鑫同学
2024/08/06
2030
全流程 Chrome 扩展开发之按键提示
AI编程:Coze + Cursor实现一个思维导图的浏览器插件
虽然AI编程知识简单对话就行,不过咱要逐步深入到项目开发中,所以还需要前面的需求分析、调研等等步骤,下面是完成一个需求的流程图:
卷福同学
2025/02/05
4360
chrome浏览器扩展v3版本配置项整理备忘
2、除了在插件内部contenscript background 和 popup之间传递消息以外,其他网站也可以给插件发送消息。方法如下 首先,需要增加配置 externally_connectable:{matches:[“https://*.xxx.com/”]}指定允许哪些网站可以给当前插件发送消息,相当于白名单,只有在白名单中的站点发送的消息,扩展才会监听
fastmock
2023/10/23
6430
手摸手教你,从0到1开发一个Chrome浏览器插件
开发 Chrome 浏览器插件(也称为扩展)是一段有趣且有成就感的过程。在本教程中,我将引导你从零开始,逐步创建一个简单的 Chrome 插件。无论你是编程新手还是有一定基础的用户,我们都将以简单易懂的方式介绍整个过程。
南山竹
2024/08/09
3.7K0
手摸手教你,从0到1开发一个Chrome浏览器插件
安装量终于破千了!聊聊浏览器扩展开发的相关问题与解决方案
我开发的浏览器扩展安装量终于过千了!在 Firefox AddOns 已经有2.1k+安装,在 Chrome WebStore 已经有2k+安装。实际上在Firefox的扩展市场里是周平均安装量,当天的实际安装量要高出平均值不少,而Chrome的扩展市场在超过1k安装量之后就不精确显示安装量了,实际安装量也会高于1k。
WindRunnerMax
2025/05/22
840
用ChatGPT(o3-mini-high)&amp; Claude-3.7-sonnet开发谷歌浏览器插件!实战+踩坑修复+源码对比
ChatGPT生成了一个新的removeHighlights方法,并在highlightText中先调用它。
前端达人
2025/04/13
1370
用ChatGPT(o3-mini-high)&amp; Claude-3.7-sonnet开发谷歌浏览器插件!实战+踩坑修复+源码对比
从油猴脚本管理器的角度审视Chrome扩展
在之前一段时间,我需要借助Chrome扩展来完成一个需求,当时还在使用油猴脚本与浏览器扩展之间调研了一波,而此时恰好我又有一些做的还可以的油猴脚本 TKScript (点个star吧 😁),相对会比较熟悉脚本管理器的能力,预估是不太能完成需求的,所以趁着这个机会,我又学习了一波浏览器扩展的能力。那么在后来需求的开发过程中,因为有些能力是类似于脚本管理器提供的基础环境,致使我越来越好奇脚本管理器是怎么实现的,而实际上脚本管理器实际上还是一个浏览器扩展,浏览器也并没有给脚本管理器开后门来实现相关能力,而让我疑惑的三个问题是:
WindRunnerMax
2024/05/14
4320
开发一款浏览器插件
可以从这个网站[1]下载个好看的图标,命名为default_icon字段对应的名称
fliter
2024/05/10
1810
开发一款浏览器插件
开发一个浏览器插件从未如此简单 ...
实际上我们平时说的浏览器插件指的就是浏览器扩展,它可以帮助我们实现非常多强大的能力。以我们最常接触到的 Chrome 扩展 (Chrome Extension) 为例,它可以帮助我们实现请求的抓取和劫持、各种事件监听、浏览器窗口控制、更改网页内容等等。
ConardLi
2023/01/09
1.8K0
开发一个浏览器插件从未如此简单 ...
手把手教你打造全宇宙最强 Firefox 浏览器
Firefox 和 Chrome 分别是当今世界最流行的浏览器之一,虽然这两款浏览器都有各自的优势,但随着时间的推移,Firefox 的受欢迎程度在逐渐下降,开始走下坡路。这无可厚非,并不是 Firefox 不行了,而是 Chrome 太强了,背靠 Google 顶级大厂,无缝整合 Google 服务,界面极度简洁,它就像一个十足精美的篮子,你往里面放的鸡蛋越多,它就越好用。
米开朗基杨
2022/05/25
2.3K0
手把手教你打造全宇宙最强 Firefox 浏览器
浏览器扩展开发系列教程(一)
以谷歌内核的浏览器扩展,包括 edge chrome ,还有我们常用的国产浏览器都能使用
唯一Chat
2022/11/22
5020
浏览器扩展开发系列教程(一)
浏览器插件开发-manifest文件解读「建议收藏」
"content_security_policy": "script-src 'self' https://*.xxx.com; object-src 'self'"
全栈程序员站长
2022/07/28
2.8K0
推荐阅读
相关推荐
谷歌浏览器扩展开发的原理与实践(DIY存网文)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验