├── README.md ├── img ├── .DS_Store ├── help.png ├── ipInfoSearch1.png ├── ipInfoSearch2.png ├── runThread1.png └── runThread2.png ├── ipInfoSearch.py ├── module ├── __init__.py ├── font.py ├── getDomain.bak.py ├── getDomain.py ├── getICP.bak.py ├── getICP.py └── getRank.py ├── requirements.txt └── runThread.py /README.md: -------------------------------------------------------------------------------- 1 | # ipInfoSearch 2 | ip域名反查、权重查询以及ICP备案查询。便于提交SRC时资产过滤。 3 | 4 | ## 配置需要python三方包 5 | pip install -r requirements.txt 6 | 7 | ## 基本用法: 8 | python ipInfoSearch.py -h 9 | 10 | ![image](/img/help.png) 11 | 12 | python ipInfoSearch.py -f fileName.txt -icp -o outFileName 13 | 14 | ![image](/img/ipInfoSearch1.png) 15 | 16 | ![image](/img/ipInfoSearch2.png) 17 | 18 | ## 报错处理: 19 | 20 | - 若报错:RuntimeError: maximum recursion depth exceeded 21 | 22 | - 是因为性能低导致的递归问题,请在ipInfoSearch.py头部添加 23 | 24 | ``` 25 | import sys 26 | sys.setrecursionlimit(10000) 27 | ``` 28 | 29 | ## 多线程用法: 30 | python runThread.py -c "python ipInfoSearch.py -t {{data}} -icp -o outFileName -hidden" -f fileName.txt 31 | 32 | 注释:**只需修改outFileName 以及 fileName** 33 | 34 | 注释:**-hidden 为ipInfoSearch.py参数,多线程不打印干扰信息** 35 | 36 | 原理:遍历fileName填充{{data}}执行命令 37 | 38 | ![image](/img/runThread1.png) 39 | 40 | ![image](/img/runThread2.png) 41 | -------------------------------------------------------------------------------- /img/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Potato-py/ipInfoSearch/da4a651fd49a156f1f9749f3c9155a5ef470eaf9/img/.DS_Store -------------------------------------------------------------------------------- /img/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Potato-py/ipInfoSearch/da4a651fd49a156f1f9749f3c9155a5ef470eaf9/img/help.png -------------------------------------------------------------------------------- /img/ipInfoSearch1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Potato-py/ipInfoSearch/da4a651fd49a156f1f9749f3c9155a5ef470eaf9/img/ipInfoSearch1.png -------------------------------------------------------------------------------- /img/ipInfoSearch2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Potato-py/ipInfoSearch/da4a651fd49a156f1f9749f3c9155a5ef470eaf9/img/ipInfoSearch2.png -------------------------------------------------------------------------------- /img/runThread1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Potato-py/ipInfoSearch/da4a651fd49a156f1f9749f3c9155a5ef470eaf9/img/runThread1.png -------------------------------------------------------------------------------- /img/runThread2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Potato-py/ipInfoSearch/da4a651fd49a156f1f9749f3c9155a5ef470eaf9/img/runThread2.png -------------------------------------------------------------------------------- /ipInfoSearch.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # author Potato 3 | # date 2022-09-26 09:57:02 4 | 5 | import os 6 | import sys 7 | import re 8 | import string 9 | import requests 10 | requests.packages.urllib3.disable_warnings() 11 | import csv 12 | import time 13 | import argparse 14 | import tldextract 15 | 16 | from module.font import * 17 | from module.getDomain import getDomain 18 | from module.getRank import getRank 19 | from module.getICP import getICP 20 | 21 | def printTime(): 22 | return f"[{blue(time.strftime('%H:%M:%S', time.localtime()))}] - " 23 | 24 | def parseArgs(): 25 | parser = argparse.ArgumentParser() 26 | parser.add_argument("-t", dest="target", required=False, type=str, help="目标IP/域名") 27 | parser.add_argument("-f", dest="file", required=False, type=str, default="", help=f"包含目标IP/域名的文件") 28 | parser.add_argument("-r", dest="rank", required=False, type=int, default=0, help="展示权重不小于R的数据 (默认0)") 29 | parser.add_argument("-rt", dest="rankTarget", required=False, type=int, default=0, help="展示权重[0所有][1百度][2移动][3三六零][4搜狗][5谷歌] (默认0所有)") 30 | parser.add_argument('-showE', dest="showDominError", required=False, action="store_true", default=False, help="展示反查域名网络错误信息 (默认关闭)") 31 | parser.add_argument('-icp', dest="icp", required=False, action="store_true", default=False, help="查询ICP备案信息 (默认关闭)") 32 | parser.add_argument("-o", dest="output", required=False, type=str, default=f"{fistDate}", help=f"输出文件 (默认输出 ./Result/{fistDate}.csv)") 33 | parser.add_argument('-hidden', dest="hidden", required=False, action="store_true", default=False, help="用于多线程隐藏入参打印及任务时间打印 (默认关闭)") 34 | argsObj = parser.parse_args() 35 | if not argsObj.target and not argsObj.file: 36 | print(red('\n[x] 用法:python ipInfoSearch.py [-t 目标IP/域名] [-f 含多个目标的文件] [-r 权重最小值] [-icp 备案查询] [-o 输出文件]\n\n[-] 举例:python ipInfoSearch.py -t 127.0.0.1 -r 1 -icp ')) 37 | sys.exit() 38 | if argsObj.file: 39 | if not os.path.isfile(argsObj.file): 40 | print(printTime()+f"\033[31m[Error] 加载文件[{argsObj.file}]失败\033[0m") 41 | sys.exit() 42 | if not argsObj.hidden: 43 | print(printTime()+bold(f"[Info] -t : {argsObj.target}")) 44 | print(printTime()+bold(f"[Info] -f : {argsObj.file}")) 45 | print(printTime()+bold(f"[Info] -r : {argsObj.rank}")) 46 | print(printTime()+bold(f"[Info] -rt : {argsObj.rankTarget}")) 47 | print(printTime()+bold(f"[Info] -showE: {argsObj.showDominError}")) 48 | print(printTime()+bold(f"[Info] -icp : {argsObj.icp}")) 49 | print(printTime()+bold(f"[Info] -o : ./Result/{argsObj.output}.csv")) 50 | return argsObj 51 | 52 | # 解析输入目标数据 53 | def parseData(data): 54 | domainObj = tldextract.extract(data) 55 | #domainObj:subdomain='www', domain='baidu', suffix='com' 56 | #判断是否为域名 57 | if not domainObj.suffix: 58 | #判断是否为IP 59 | if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",domainObj.domain): 60 | return f"{domainObj.domain}" 61 | else:#既不是域名也不是ip 62 | return "" 63 | else: 64 | return f"{domainObj.domain}.{domainObj.suffix}" 65 | 66 | # 加载目标IP/域名 67 | def loadTarget(file, target): 68 | targetList = [] 69 | if file: 70 | f = open(file, encoding="utf8") 71 | for line in f.readlines(): 72 | targetData = parseData(line.strip()) 73 | if targetData and targetData not in targetList: 74 | targetList.append(targetData) 75 | f.close() 76 | 77 | if target: 78 | targetData = parseData(target.strip()) 79 | if targetData and targetData not in targetList: 80 | targetList.append(targetData) 81 | 82 | return targetList 83 | 84 | def rtDel(list): 85 | if args.rankTarget==1: 86 | del list[3],list[3],list[3],list[3] 87 | elif args.rankTarget==2: 88 | del list[2],list[3],list[3],list[3] 89 | elif args.rankTarget==3: 90 | del list[2],list[2],list[3],list[3] 91 | elif args.rankTarget==4: 92 | del list[2],list[2],list[2],list[3] 93 | elif args.rankTarget==5: 94 | del list[2],list[2],list[2],list[2] 95 | return list 96 | 97 | def getIpInfo(target): 98 | 99 | if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", target): 100 | #如果目标是IP格式,获取域名 101 | domainList = getDomain(target) 102 | else: 103 | #目标为域名格式,直接赋值 104 | domainList = [target] 105 | 106 | #获取权重,任意一项满足即可 107 | for domain in domainList: 108 | #反查域名存在问题的单独处理 109 | if domain == "NtError": 110 | if args.showDominError: 111 | result = [target, domain,'-','-','-','-','-','-','-','-'] 112 | tableDataList=[ 113 | [result[0], 17], 114 | [result[1], 20], 115 | [result[2], 10], 116 | [result[3], 10], 117 | [result[4], 10], 118 | [result[5], 10], 119 | [result[6], 10], 120 | [result[7], 37], 121 | [result[8], 10], 122 | [result[9], 22] 123 | ] 124 | if not args.icp: 125 | del tableDataList[-1],tableDataList[-1],tableDataList[-1] 126 | printT(rtDel(tableDataList)) 127 | csvWriter.writerow(result) 128 | 129 | if domain != list(domainList)[-1] or target != targetList[-1] or args.hidden: 130 | printT(rtDel([17,20,10,10,10,10,10,37,10,22]),"middle") if args.icp else printT(rtDel([17,20,10,10,10,10,10]),"middle") 131 | else: 132 | printT(rtDel([17,20,10,10,10,10,10,37,10,22]),"bottom") if args.icp else printT(rtDel([17,20,10,10,10,10,10]),"middle") 133 | 134 | break 135 | 136 | rankDict = getRank(domain) 137 | for rankKey in rankDict: 138 | if (isinstance(rankDict[rankKey],str) and "Error" in rankDict[rankKey]) or (isinstance(rankDict[rankKey],int) and rankDict[rankKey] >= args.rank): #大于等于制定rank值 或 网络请求失败 139 | if args.icp: 140 | icpResult = getICP(domain) 141 | result = [target, domain, rankDict["baiduRank"], rankDict["yidongRank"], rankDict["360Rank"], rankDict["sougouRank"],rankDict["googleRank"],icpResult["unitName"], icpResult["unitType"], icpResult["unitICP"] ] 142 | tableDataList=[ 143 | [result[0], 17], 144 | [result[1], 20], 145 | [result[2], 10], 146 | [result[3], 10], 147 | [result[4], 10], 148 | [result[5], 10], 149 | [result[6], 10], 150 | [result[7], 37], 151 | [result[8], 10], 152 | [result[9], 22] 153 | ] 154 | printT(rtDel(tableDataList)) 155 | csvWriter.writerow(result) 156 | if domain != list(domainList)[-1] or target != targetList[-1] or args.hidden: 157 | printT(rtDel([17,20,10,10,10,10,10,37,10,22]),"middle") 158 | else: 159 | printT(rtDel([17,20,10,10,10,10,10,37,10,22]),"bottom") 160 | else: 161 | result = [target, domain, rankDict["baiduRank"], rankDict["yidongRank"], rankDict["360Rank"], rankDict["sougouRank"],rankDict["googleRank"] ] 162 | tableDataList=[ 163 | [result[0], 17], 164 | [result[1], 20], 165 | [result[2], 10], 166 | [result[3], 10], 167 | [result[4], 10], 168 | [result[5], 10], 169 | [result[6], 10] 170 | ] 171 | printT(rtDel(tableDataList)) 172 | csvWriter.writerow(result) 173 | if domain != list(domainList)[-1] or target != targetList[-1] or args.hidden: 174 | printT(rtDel([17,20,10,10,10,10,10]),"middle") 175 | else: 176 | printT(rtDel([17,20,10,10,10,10,10]),"bottom") 177 | break 178 | 179 | def getTitle(mode=""): 180 | if args.icp: 181 | if not args.hidden: 182 | printT(rtDel([17,20,10,10,10,10,10,37,10,22]),"top") 183 | tableDataList=[ 184 | ["ip/domain",17], 185 | ["反查域名",20], 186 | ["百度权重",10], 187 | ["移动权重",10], 188 | ["360权重",10], 189 | ["搜狗权重",10], 190 | ["谷歌权重",10], 191 | ["单位名称",37], 192 | ["单位性质",10], 193 | ["备案编号",22] 194 | ] 195 | printT(rtDel(tableDataList),fontStyle="bold") 196 | printT(rtDel([17,20,10,10,10,10,10,37,10,22]),"middle") 197 | csvWriter.writerow(["ip/domain", "反查域名", "百度权重", "移动权重", "360权重", "搜狗权重", "谷歌权重", "单位名称", "单位性质", "备案编号"]) if mode!="OnlyPrint" else 0 198 | else: 199 | if not args.hidden: 200 | printT(rtDel([17,20,10,10,10,10,10]),"top") 201 | tableDataList=[ 202 | ["ip/domain",17], 203 | ["反查域名",20], 204 | ["百度权重",10], 205 | ["移动权重",10], 206 | ["360权重",10], 207 | ["搜狗权重",10], 208 | ["谷歌权重",10] 209 | ] 210 | printT(rtDel(tableDataList),fontStyle="bold") 211 | printT(rtDel([17,20,10,10,10,10,10]),"middle") 212 | csvWriter.writerow(["ip/domain", "反查域名", "百度权重", "移动权重", "360权重", "搜狗权重", "谷歌权重"]) if mode!="OnlyPrint" else 0 213 | 214 | if __name__ == "__main__": 215 | fistDate = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()) 216 | fistTime = time.time() 217 | 218 | args = parseArgs() 219 | 220 | targetList = loadTarget(args.file, args.target) 221 | 222 | outFilePath = f"./Result/{args.output}.csv" 223 | os.mkdir(r"./Result") if not os.path.isdir(r"./Result") else 0 224 | existFile = True if os.path.exists(outFilePath) else False 225 | file = open(outFilePath, "a+", encoding="GBK", newline="") 226 | csvWriter = csv.writer(file) 227 | 228 | getTitle() if not existFile else getTitle("OnlyPrint") 229 | 230 | for target in targetList: 231 | getIpInfo(target) 232 | 233 | if not args.hidden: 234 | finallyDate = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()) 235 | finallyTime = time.time() 236 | timing = (finallyTime-fistTime) 237 | print(printTime()+"查询完毕,用时:%f秒"%(timing)) 238 | print(printTime()+f"结果已保存至:{outFilePath}") -------------------------------------------------------------------------------- /module/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | if __name__ == "__main__": 3 | pass -------------------------------------------------------------------------------- /module/font.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 3 | import os 4 | import sys 5 | import string 6 | sys.setrecursionlimit(100000) 7 | 8 | try: 9 | import terminal 10 | except: 11 | print('检测出您未安装terminal模块,将替您安装此模块,请稍候……') 12 | os.system('pip install terminal') 13 | import terminal 14 | try: 15 | import console 16 | except: 17 | print('检测出您未安装console模块,将替您安装此模块,请稍候……') 18 | os.system('pip install console') 19 | import console 20 | 21 | def red(text): 22 | return terminal.bold(terminal.red(text)) 23 | 24 | def green(text): 25 | return terminal.green(text) 26 | 27 | def blue(text): 28 | return terminal.bold(terminal.blue(text)) 29 | 30 | def magenta(text): 31 | return terminal.magenta(text) 32 | 33 | def yellow(text): 34 | return terminal.yellow(text) 35 | 36 | def cyan(text): 37 | return terminal.cyan(text) 38 | 39 | def bold(text):#高亮 40 | return terminal.bold(text) 41 | 42 | def Processing(): 43 | return terminal.magenta(r"[Processing] ") 44 | 45 | def Information(): 46 | return terminal.cyan(r"[Information] ") 47 | 48 | def Detected(): 49 | return terminal.bold(terminal.blue(r"[Detected] ")) 50 | 51 | def Result(): 52 | return terminal.bold(terminal.green(r"[Result] ")) 53 | 54 | def Error(): 55 | return terminal.bold(terminal.red(r"[Error] ")) 56 | 57 | def Input(*num): 58 | if(num and num[0]!= 1): 59 | data = r"- " 60 | else: 61 | data = r"$ " 62 | return terminal.bold(terminal.yellow(data)) 63 | 64 | #实现回车换行,而不是结束 65 | def Input_lines(): 66 | result = "" 67 | num = 0 68 | while True: 69 | num = num + 1 70 | data = str(input(Input(num))) 71 | if data == '': 72 | if(num==1): 73 | print(Error()+'首行不能为空,请重新输入!\n') 74 | result = "" 75 | num = 0 76 | continue 77 | return result 78 | result+= data+"\n"#换行 79 | 80 | #格式化输出 81 | def printF(strData, lenMax, placeHolder=" ", justify="center"): 82 | strData = str(strData) 83 | lenChina = 0 84 | for i in strData: 85 | lenChina+=1 if i not in string.printable else 0 86 | return strData.center(lenMax-lenChina,placeHolder) if justify=="center" else strData.ljust(lenMax-lenChina,placeHolder) if justify=="left" else strData.rjust(lenMax-lenChina,placeHolder) 87 | 88 | #调用直接打印table 89 | # printT( [8,13,13,10] ,"top") 90 | # printT( [["ip",8],["域名",13,"left"],["权重",13,"center"],["编号",10]]) 91 | # printT( [8,13,13,10] ,"middle") 92 | # printT( [["ip",8],["域名",13,"left"],["权重",13],["编号",10]],type="body") 93 | # printT( [8,13,13,10] ,"bottom") 94 | #tableStyle、fontStyle 分别控制字体和表格颜色 95 | def printT(dataList,type="body",getStr=False,tableStyle="red",fontStyle=""): 96 | 97 | def table(str): 98 | if tableStyle == "red": 99 | return red(str) 100 | elif tableStyle == "green": 101 | return green(str) 102 | elif tableStyle == "magenta": 103 | return magenta(str) 104 | elif tableStyle == "blue": 105 | return blue(str) 106 | elif tableStyle == "yellow": 107 | return yellow(str) 108 | elif tableStyle == "cyan": 109 | return cyan(str) 110 | elif tableStyle == "bold": 111 | return bold(str) 112 | else: 113 | return str 114 | 115 | def font(str): 116 | if fontStyle == "red": 117 | return red(str) 118 | elif fontStyle == "green": 119 | return green(str) 120 | elif fontStyle == "magenta": 121 | return magenta(str) 122 | elif fontStyle == "blue": 123 | return blue(str) 124 | elif fontStyle == "yellow": 125 | return yellow(str) 126 | elif fontStyle == "cyan": 127 | return cyan(str) 128 | elif fontStyle == "bold": 129 | return bold(str) 130 | else: 131 | return str 132 | 133 | try: 134 | str="" 135 | if type == "top": 136 | str = table("┌") 137 | for index, data in enumerate(dataList): 138 | str += table("─" * data) 139 | str += table("┬") if index != len(dataList)-1 else table("┐") 140 | elif type == "bottom": 141 | str = table("└") 142 | for index, data in enumerate(dataList): 143 | str += table("─" * data) 144 | str += table("┴") if index != len(dataList)-1 else table("┘") 145 | elif type == "middle": 146 | str = table("├") 147 | for index, data in enumerate(dataList): 148 | str += table("─" * data) 149 | str += table("┼") if index != len(dataList)-1 else table("┤") 150 | else: 151 | str = table("│") 152 | for data in dataList: 153 | justify = "center" if len(data)==2 else data[2] 154 | str += f"{font(printF(data[0], data[1], justify=justify))}{table('│')}" 155 | if getStr: 156 | return str 157 | else: 158 | print(str) 159 | except Exception as e: 160 | print(f"\033[31m[Error] {e}\r\n") 161 | print('正确使用方法:') 162 | print(' printT( [8,13,13,10] ,"top")') 163 | print(' printT( [["ip",8],["域名",13,"left"],["权重",13],["编号",10]])') 164 | print(' printT( [8,13,13,10] ,"middle")') 165 | print(' printT( [["ip",8],["域名",13,"left"],["权重",13],["编号",10]])') 166 | print(' printT( [8,13,13,10] ,"bottom")\033[0m') -------------------------------------------------------------------------------- /module/getDomain.bak.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import re 3 | import tldextract 4 | import requests 5 | requests.packages.urllib3.disable_warnings() 6 | 7 | headers = { 8 | "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 9 | # "Connection": "close" 数据量传输慢 不可立马关闭socket通道 10 | } 11 | 12 | def getDomain(ip): 13 | mainDomainList = [] 14 | domainList = [] 15 | 16 | try: 17 | req1 = requests.get(url=f"http://api.webscan.cc/?action=query&ip={ip}", headers=headers, timeout=20, verify=False) 18 | if req1.status_code != 200: 19 | domainList.append("NtError") 20 | return domainList 21 | if req1.text != "null": 22 | jsonData = req1.json() 23 | for data in jsonData: 24 | domain = data["domain"] 25 | if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", domain): 26 | #剔除ip 27 | continue 28 | if domain in mainDomainList: 29 | #剔除已有相同主域名 30 | continue 31 | # #domainObj:subdomain='www', domain='baidu', suffix='com' 获取主域名并保存 32 | domainObj = tldextract.extract(domain) 33 | mainDomainList.append(f"{domainObj.domain}.{domainObj.suffix}") if f"{domainObj.domain}.{domainObj.suffix}" not in mainDomainList else 0 34 | domainList=mainDomainList 35 | except Exception as e: 36 | # print(f"\033[31m[Error] {e}\033[0m") 37 | domainList.append("NtError") 38 | pass 39 | return domainList 40 | 41 | print(getDomain("110.242.68.66")) 42 | print(getDomain("baidu.com")) -------------------------------------------------------------------------------- /module/getDomain.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from lxml import etree 3 | import requests 4 | import socket 5 | import re 6 | import tldextract 7 | requests.packages.urllib3.disable_warnings() 8 | 9 | #传入ip可获取当前解析domain 10 | #传入domain可获取历史绑定ip 11 | #可获取ipPostion 12 | 13 | headers = { 14 | "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 15 | "Connection": "close" 16 | } 17 | 18 | def getIpList(domain): # 获取域名解析出的IP列表 19 | ip_list = [] 20 | try: 21 | addrs = socket.getaddrinfo(domain, None) 22 | for item in addrs: 23 | if item[4][0] not in ip_list: 24 | ip_list.append(item[4][0]) 25 | except Exception as e: 26 | pass 27 | return ip_list 28 | 29 | def getDomain(ip,replayNun=0): 30 | allData = []#爬取反查域名信息 31 | domainList = []#最终反查域名信息 32 | ipPosition = []#获取ip位置信息 33 | histryIp = []#历史绑定ip 34 | argIsDoamin = False#参数默认非domain 35 | try: 36 | req1 = requests.get(url=f"https://site.ip138.com/{ip}/", headers=headers, timeout=20, verify=False) 37 | if req1.status_code!=200 and replayNun < 2: 38 | replayNun += 1 39 | return getDomain(ip,replayNun) 40 | if req1.status_code != 200 and replayNun == 2: 41 | domainList.append(f"NtError c:{status_code}") 42 | return domainList 43 | html=etree.HTML(req1.text,etree.HTMLParser()) 44 | if re.match(r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", ip): 45 | allData = html.xpath('//ul[@id="list"]/li/a[@target="_blank"]/text()') #获取a节点下的内容,获取到ip曾解析到的domain 存在老旧数据 46 | else: 47 | argIsDoamin = True 48 | histryIp = html.xpath('//div[@id="J_ip_history"]/p/a[@target="_blank"]/text()') #获取a节点下的内容,获取到域名解析到的ip 存在老旧数据 49 | allData.append(ip) 50 | for domin in allData: 51 | #确保反查到的域名可解析到当前ip 剔除老旧数据 52 | if argIsDoamin or ( ip in getIpList(domin) ): 53 | #剔除相同域名 54 | domainObj = tldextract.extract(domin) 55 | domainData = f"{domainObj.domain}.{domainObj.suffix}" 56 | if domainData not in domainList: 57 | domainList.append(domainData) 58 | ipPosition=html.xpath('//div[@class="result result2"]/h3/text()') #获取ip位置信息 59 | except Exception as e: 60 | # print(f"\033[31m[Error] url:https://site.ip138.com/{ip}/ {e}\033[0m") 61 | domainList.append("NtError") 62 | pass 63 | return domainList 64 | # print(getDomain("110.242.68.66")) 65 | # print(getDomain("baidu.com")) -------------------------------------------------------------------------------- /module/getICP.bak.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import requests 3 | 4 | header = { 5 | "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 6 | "Connection": "close" 7 | } 8 | 9 | def getICP(domain): 10 | resultDict = {"domain":domain, "unitName": "-", "unitType": "-", "unitICP": "-", "title": "-"} 11 | try: 12 | req = requests.get(url=f"https://api.vvhan.com/api/icp?url={domain}", headers=header, timeout=20) 13 | if req.status_code != 200: 14 | resultDict["unitName"] = "NtError" 15 | resultDict["unitType"] = "NtError" 16 | resultDict["unitICP"] = "NtError" 17 | resultDict["title"] = "NtError" 18 | return resultDict 19 | if len(req.json()) != 2 : 20 | resultDict["unitName"] = req.json()["info"]["name"] 21 | resultDict["unitType"] = req.json()["info"]["nature"] 22 | resultDict["unitICP"] = req.json()["info"]["icp"] 23 | resultDict["title"] = req.json()["info"]["title"] 24 | elif req.json()["message"] == "请输入正确的域名": 25 | resultDict["unitName"] = "DmError" 26 | resultDict["unitType"] = "DmError" 27 | resultDict["unitICP"] = "DmError" 28 | resultDict["title"] = "DmError" 29 | else:#此域名未备案 30 | pass 31 | return resultDict 32 | except Exception as e: 33 | resultDict["unitName"] = "NtError" 34 | resultDict["unitType"] = "NtError" 35 | resultDict["unitICP"] = "NtError" 36 | resultDict["title"] = "NtError" 37 | # print(f"\033[31m[Error] {e}\033[0m") 38 | pass 39 | return resultDict -------------------------------------------------------------------------------- /module/getICP.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from lxml import etree 3 | import requests 4 | import socket 5 | import re 6 | import tldextract 7 | requests.packages.urllib3.disable_warnings() 8 | 9 | header = { 10 | "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 11 | "Connection": "close" 12 | } 13 | 14 | def getICP(domain,replayNun=0): 15 | resultDict = {"domain":domain, "unitName": "-", "unitType": "-", "unitICP": "-", "title": "-"} 16 | try: 17 | req = requests.get(url=f"https://icplishi.com/{domain}", headers=header, timeout=20) 18 | if req.status_code!=200 and replayNun < 2: 19 | replayNun += 1 20 | return getICP(domain,replayNun) 21 | if req.status_code != 200 and replayNun == 2: 22 | resultDict = {"domain":domain, "unitName": f"NtError:Code{req.status_code}", "unitType": "NtError", "unitICP": "NtError", "title": "NtError"} 23 | return resultDict 24 | html=etree.HTML(req.text,etree.HTMLParser()) 25 | SpanTag = html.xpath('//div[@class="module mod-panel"]/div[@class="bd"]/div[@class="box"]/div[@class="c-bd"]/table/tbody/tr/td/span/text()') 26 | ATag = html.xpath('//div[@class="module mod-panel"]/div[@class="bd"]/div[@class="box"]/div[@class="c-bd"]/table/tbody/tr/td/a/text()') 27 | token = html.xpath('//div[@id="J_beian"]/@data-token') 28 | if len(ATag)>=2 and len(SpanTag)>=2 and (SpanTag[1] != "未备案"): 29 | resultDict = {"domain":domain, "unitName": ATag[0], "unitType": SpanTag[1], "unitICP": ATag[1], "title": SpanTag[0]} 30 | if (token and resultDict["unitName"]=="-" ) or (token and "ICP" not in resultDict["unitICP"]) or (token and '-' in SpanTag[1]): 31 | resultDict = getIcpFromToken(domain,token[0]) 32 | except Exception as e: 33 | resultDict = {"domain":domain, "unitName": "NtError", "unitType": "NtError", "unitICP": "NtError", "title": "NtError"} 34 | # print(f"\033[31m[Error] func1 code:{req.status_code} {e}\033[0m") 35 | pass 36 | # print(req.text) 37 | # print(SpanTag) 38 | # print(ATag) 39 | return resultDict 40 | # print(getICP("potato.gold")) 41 | 42 | #两次出现"msg"="等待结果",为未查询出结果 43 | def getIcpFromToken(domain,token,replayNun=0): 44 | try: 45 | req = requests.get(f"https://icplishi.com/query.do?domain={domain}&token={token}", headers=header, timeout=20) 46 | # print(req.text) 47 | # print(req.status_code) 48 | # print(f"https://icplishi.com/query.do?domain={domain}&token={token}") 49 | if (req.status_code!=200 or req.json()["msg"]=="等待结果") and replayNun < 2: 50 | replayNun += 1 51 | return getIcpFromToken(domain,token,replayNun) 52 | data = req.json()["data"] 53 | if req.status_code!=200 or req.json()["msg"]=="等待结果" or len(data)==0 or len(data[0])==0 or data[0]["license"]== "未备案": 54 | resultDict = {"domain":domain, "unitName": "-", "unitType": "-", "unitICP": "-", "title": "-"} 55 | else: 56 | resultDict = {"domain":domain, "unitName": data[0]["company"], "unitType": data[0]["character"], "unitICP": data[0]["license"], "title": data[0]["home_site"]} 57 | except Exception as e: 58 | resultDict = {"domain":domain, "unitName": "NtError", "unitType": "NtError", "unitICP": "NtError", "title": "NtError"} 59 | # print(f"\033[31m[Error] func2 code:{req.status_code} msg:{e}\033[0m") 60 | pass 61 | return resultDict -------------------------------------------------------------------------------- /module/getRank.py: -------------------------------------------------------------------------------- 1 | import re 2 | import requests 3 | 4 | headers = { 5 | "Referer": "https://www.aizhan.com/cha/", 6 | "Host": "www.aizhan.com", 7 | "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", 8 | # "Connection": "close" 9 | } 10 | 11 | def getRank(domain): 12 | url = f"https://www.aizhan.com/cha/{domain}/"#f"https://seo.chinaz.com/{domain}" 13 | rankDict = {"baiduRank": 0, "yidongRank": 0, "360Rank": 0, "sougouRank": 0, "googleRank": 0} 14 | try: 15 | req = requests.get(url, headers=headers, timeout=20) 16 | if req.status_code != 200: 17 | rankDict["baiduRank"] = "NtError" 18 | rankDict["yidongRank"] = "NtError" 19 | rankDict["360Rank"] = "NtError" 20 | rankDict["sougouRank"] = "NtError" 21 | rankDict["googleRank"] = "NtError" 22 | return rankDict 23 | # 正则匹配爬虫权重特征 24 | baiduRank = re.compile(r'aizhan.com/images/br/(.*?).png') 25 | yidongRank = re.compile(r'aizhan.com/images/mbr/(.*?).png') 26 | _360Rank = re.compile(r'aizhan.com/images/360/(.*?).png') 27 | sougouRank = re.compile(r'aizhan.com/images/sr/(.*?).png') 28 | googleRank = re.compile(r'aizhan.com/images/pr/(.*?).png') 29 | try: 30 | rankDict["baiduRank"] = int(baiduRank.findall(req.text)[0]) 31 | rankDict["yidongRank"] = int(yidongRank.findall(req.text)[0]) 32 | rankDict["360Rank"] = int(_360Rank.findall(req.text)[0]) 33 | rankDict["sougouRank"] = int(sougouRank.findall(req.text)[0]) 34 | rankDict["googleRank"] = int(googleRank.findall(req.text)[0]) 35 | except Exception as e: 36 | # print(f"\033[31m[Error] {e}\033[0m") 37 | pass 38 | except Exception as e: 39 | rankDict["baiduRank"] = "NtError" 40 | rankDict["yidongRank"] = "NtError" 41 | rankDict["360Rank"] = "NtError" 42 | rankDict["sougouRank"] = "NtError" 43 | rankDict["googleRank"] = "NtError" 44 | # print(f"\033[31m[Error] {e}\033[0m") 45 | pass 46 | return rankDict -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | terminal 2 | console 3 | requests 4 | tldextract 5 | -------------------------------------------------------------------------------- /runThread.py: -------------------------------------------------------------------------------- 1 | from concurrent.futures import ThreadPoolExecutor 2 | import subprocess 3 | import time 4 | import argparse 5 | import os 6 | import sys 7 | 8 | def parseArgs(): 9 | fistDate = time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime()) 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument("-n", dest="num", required=False, type=int, default=60, help=f"最大线程数(默认60)") 12 | parser.add_argument("-c", dest="command", required=True, type=str, help="执行的命令(需要遍历部分请用{{data}}代替,并传入-f)") 13 | parser.add_argument("-f", dest="file", required=False, type=str, help=f"需要遍历数据的文件") 14 | parser.add_argument("-o", dest="output", required=False, type=str, default=f"{fistDate}", help=f"输出文件 (默认输出 ./Result/{fistDate}.txt)") 15 | argsObj = parser.parse_args() 16 | if not argsObj.command or ( "{{data}}" in argsObj.command and not argsObj.file ): 17 | print('\033[31m\n[Info] 多线程内部若存在输出文件,请改用时间戳命名或a+追加方式,防止覆盖输出\n[Info] 若需加载文件,启动命令需转换为单个目标 \n[x] 用法:python runThread.py [-n 线程数] [-c 执行的命令] [-f 需要遍历数据的文件] [-o 输出文件名]\n\n[-] 举例:python runThread.py -n 60 -c "python3 ipInfoSearch.py -t {{data}} -ipc -o csvOut -hidden" -f ./fileData.txt -o ipInfoText\033[0m') 18 | sys.exit() 19 | if argsObj.file: 20 | if not os.path.isfile(argsObj.file): 21 | print(f"\033[31m[Error] 加载文件[{argsObj.file}]失败\033[0m") 22 | sys.exit() 23 | print(f"[Info] -n : {argsObj.num}") 24 | print(f"[Info] -c : {argsObj.command}") 25 | print(f"[Info] -f : {argsObj.file}") 26 | print(f"[Info] -o : ./Result/{argsObj.output}.txt") 27 | print(f"[Info] 多线程内部若存在输出文件,请改用时间戳命名或a+追加方式,防止覆盖输出") 28 | print(f"[Info] 若需加载文件,启动命令需转换为单个目标") 29 | 30 | return argsObj 31 | 32 | def runThread(): 33 | start = time.time() 34 | 35 | targetList = [] 36 | if args.file: 37 | file = open(args.file, encoding="utf8") 38 | for line in file.readlines(): 39 | targetData = line.strip() 40 | if targetData and targetData not in targetList: 41 | targetList.append(targetData) 42 | file.close() 43 | 44 | # 创建线程 45 | with ThreadPoolExecutor(max_workers=args.num) as executor: 46 | if len(targetList)>1: 47 | [ executor.submit(func, args.command.replace("{{data}}",f"\"{i}\"")) for i in targetList ] 48 | else: 49 | [ executor.submit(func, args.command) for i in range(args.num) ] 50 | 51 | end = time.time() 52 | print(f'\033[32mProgram takes time: {end - start}\033[0m') 53 | 54 | def func(command): 55 | #多线程 转 多进程 56 | cmd = subprocess.run(command, shell=True) 57 | 58 | 59 | 60 | if __name__ == "__main__": 61 | args = parseArgs() 62 | runThread() 63 | --------------------------------------------------------------------------------