Explorar o código

完善在线工具箱功能

hongwenjun %!s(int64=3) %!d(string=hai) anos
pai
achega
33de52c7ed
Modificáronse 10 ficheiros con 364 adicións e 158 borrados
  1. 14 6
      README.md
  2. 32 73
      app.py
  3. 45 0
      china_shift.py
  4. BIN=BIN
      china_shift.so
  5. 51 0
      getmd.py
  6. 97 0
      ips.py
  7. 45 0
      templates/getmd.html
  8. 15 34
      templates/hello.html
  9. 26 45
      templates/ips.html
  10. 39 0
      templates/navbar.html

+ 14 - 6
README.md

@@ -1,15 +1,15 @@
-## ip:  Python WebAPI
+## ip: Python Flask WebAPI && Bootstrap Theme
 
 ### 演示网址  https://262235.xyz/ip/
 
 ### 本WebAPI支持IP城市定位和域名查IP定位,同时支持命令行查询
 
-![](https://262235.xyz/usr/uploads/2021/08/650223153.webp)
+![](https://262235.xyz/usr/uploads/2021/10/4246023144.png)
 
 ## 安装部署简易命令
 ```
 git clone https://github.com/hongwenjun/ip.git
-pip3  install Flask  ipip-ipdb
+pip3  install Flask  ipip-ipdb  html2text
 cd ip
 wget https://cdn.jsdelivr.net/npm/qqwry.ipdb/qqwry.ipdb
 flask run --host=0.0.0.0
@@ -21,9 +21,17 @@ flask run --host=0.0.0.0
 docker run -d -p 80:5000 --restart=always --name ip hongwenjun/ip
 ```
 
-### 搭建WebAPI参考文章
-[Python网络开发简单的IP城市定位WebAPI](https://262235.xyz/index.php/archives/342/)
-
+  * [github源码](https://github.com/hongwenjun/ip)
+  * [docker镜像](https://hub.docker.com/r/hongwenjun/ip)
+  * [搭建WebAPI参考文章](https://262235.xyz/index.php/search/webapi/)
+  * 在线工具箱
+    * [Bootstrap theme](https://262235.xyz/bs/)
+    * [编程中文文档](https://www.262235.xyz/index.php/246.html)
+    * [Linux 命令列表](https://262235.xyz/linux-command/)
+    * [IP定位和地图](https://262235.xyz/ip/)
+    * [批量IP查询](https://262235.xyz/ips/)
+    * [批量网址转Markdown](https://262235.xyz/getmd/)
+    * [Markdown编辑器](https://tool.lu/markdown/)
 
 [Pytyhon 使用百度地图API 进行 IP普通定位和地图显示](https://www.262235.xyz/index.php/archives/375/)
 

+ 32 - 73
app.py

@@ -1,74 +1,19 @@
+from typing import Text
 import ipdb, ipaddress, requests, re, json
 from flask import Flask, request, render_template, jsonify
 from socket import gethostbyname
 
-db = ipdb.BaseStation("qqwry.ipdb")
 app = Flask(__name__)
-
-def iplocated(ip):
-    city = db.find(ip, "CN")
-    return ip + " @" + city[0] + city[1] + city[2] + city[3] + "\n"
-
-def getcity(ip):
-    city = db.find(ip, "CN")
-    return  city[2] + '市'
-
-def getip():
-    ip = request.remote_addr
-    try:
-        _ip = request.headers["X-Real-IP"]
-        if _ip is not None:
-            ip = _ip
-    except Exception as e:
-        print(e)
-    return ip
-
-def is_Mozilla():
-    # Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
-    ua = request.headers["User-Agent"]
-    if (ua.find("Mozilla") != -1):
-        return True
-    else:
-        return False
-
-## 百度免费的 IP 普通定位 API 接口 
-def ip2bdgps(ip):
-    url = 'https://api.map.baidu.com/location/ip?ak=>>>百度AK码<<<&coor=bd09ll&ip=' + ip
-    try:
-        r = requests.get(url)
-        data = r.json()
-    except :
-        return
-
-    if data['status'] != 0 :
-        return  (116.39564504, 39.92998578 , data['status'])    # 查不到返回 北京 x,y
-    else:
-        x = data['content']['point']['x']
-        y = data['content']['point']['y']
-    return  (x, y, data['status'], data)
-
-## 免费试用500次,  1元能使用1万次 IP定位 API 接口   https://market.aliyun.com/products/57002002/cmapi00035184.html
-def ip2gdgps(ip):
-    url = 'http://ips.market.alicloudapi.com/iplocaltion?ip=' + ip
-    headers = {"Authorization":"APPCODE  <<<IP定位APPCODE>>>" ,"Content-Type":"application/json; charset=utf-8" }
-    try:
-        r = requests.get(url=url , headers=headers)
-        data = r.json()
-    except :
-        return
-    # print(data)
-    if data['code'] != 100:
-        return  (116.39564504, 39.92998578 , data['code'])    # 查不到返回 北京 x,y
-    elif data['message'] == "success":
-        x = data['result']['lng']
-        y = data['result']['lat']
-        return  (x, y, data['code'], data)
+from ips import *
+from getmd import *
 
 @app.route("/")
 def hello():
     ip = getip()
+    ipaddr = iplocated(ip)
     if is_Mozilla():
-        return ip + render_template('hello.html', ip=ip) + "\n\n" + request.headers["User-Agent"]
+        return  render_template('hello.html',  ip=ip, ipaddr=ipaddr, city=getcity(ip)) + \
+            "<div class=\"label label-default\"  style=\"text-align:center;\">"  + request.headers["User-Agent"]  + "</div>"  
     else:
         return ip
 
@@ -112,17 +57,6 @@ def show_ip(ipaddr=None):
 
     return ipaddr
 
-def select_ips(ips_text):
-    ret =''
-    iplist = re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", ips_text)
-    for ip in iplist:
-        try:
-            one = iplocated(ip)
-            ret+=one
-        except:
-            pass
-    return ret
-
 @app.route("/ips/", methods=['POST', 'GET'])
 def getips():
     if request.method == 'POST':
@@ -132,8 +66,33 @@ def getips():
     else:
         return render_template('ips.html')
 
[email protected]("/getmd/", methods=['POST', 'GET'])
+def getmd(): 
+    if request.method == 'POST' and request.form['passkey'] == make_passkey('262235.xyz') : 
+        urls = request.form['urls']
+        urls_list = check_urls(urls)
+        urls = urls_lines(urls_list)
+        if len(urls_list) < 5 :
+            texts = '测试 PASSKEY 一次只允许最多抓取5篇文章,当前数量:' + str(len(urls_list))
+            texts += pull_urls(urls_list)
+            return render_template('getmd.html', urls=urls, texts=texts, passkey=make_passkey('262235.xyz'))
+        else:
+            texts = '文章大于5: 测试 PASSKEY 一次只允许最多抓取5篇文章,当前数量:' + str(len(urls_list))
+            return render_template('getmd.html', urls=urls, texts=texts, passkey=make_passkey('262235.xyz')) 
+    else:
+        if request.method == 'POST' and request.form['passkey'] == 'UUID-1234-5678-1234' : 
+            urls = request.form['urls']
+            urls_list = check_urls(urls)
+            urls = urls_lines(urls_list)
+            texts = '授权 PASSKEY 无限制,当前数量:' + str(len(urls_list))
+            texts += pull_urls(urls_list)
+            return render_template('getmd.html', urls=urls, texts=texts)
+        pass
+    return render_template('getmd.html', passkey=make_passkey('262235.xyz'))
+
 if __name__ == '__main__':
-        app.run(host='0.0.0.0', debug=True, port=80)
+    #  app.run(host='0.0.0.0') 
+    app.run(host='0.0.0.0', debug=True, port=80) 
 
 # export FLASK_ENV=development   # 调试模式: 修改代码不用重启服务
 # flask run --host=0.0.0.0       # 监听所有公开的 IP

+ 45 - 0
china_shift.py

@@ -0,0 +1,45 @@
+# load dynamic C library for map shift
+from ctypes import *
+shift = cdll.LoadLibrary('./china_shift.so')
+
+class Location(Structure):
+    _fields_ = [
+        ('lon', c_double),
+        ('lat', c_double)]
+
+shift.transformFromWGSToGCJ.argtypes = [Location]
+shift.transformFromWGSToGCJ.restype = Location
+shift.transformFromGCJToWGS.argtypes = [Location]
+shift.transformFromGCJToWGS.restype = Location
+
+shift.bd_encrypt.argtypes = [Location]
+shift.bd_encrypt.restype = Location
+shift.bd_decrypt.argtypes = [Location]
+shift.bd_decrypt.restype = Location
+
+def test_china_shift():
+	# Location gps = { 119.465265, 29.1934702}; 
+	# 地球WGS-84 转 火星GCJ-02 转 百度BD-09
+	
+	loc = Location(lon = 119.465265, lat = 29.1934702)
+	print("地球WGS-84:",loc.lat, loc.lon)
+	
+	loc = shift.transformFromWGSToGCJ(loc)
+	print("火星GCJ-02:",loc.lat, loc.lon)
+	
+	loc = shift.bd_encrypt(loc)
+	print("百度 BD-09:",loc.lat, loc.lon)
+	
+	# 百度BD-09 转 火星GCJ-02 转 地球WGS-84
+	loc = Location(lon = 119.476936, lat = 29.196518 )
+	print("百度 BD-09:",loc.lat, loc.lon)
+	
+	loc = shift.bd_decrypt(loc)
+	print("火星GCJ-02:",loc.lat, loc.lon)
+	
+	loc = shift.transformFromGCJToWGS(loc)
+	print("地球WGS-84:",loc.lat, loc.lon)
+
+if __name__ == '__main__':
+	test_china_shift()
+

BIN=BIN
china_shift.so


+ 51 - 0
getmd.py

@@ -0,0 +1,51 @@
+import requests, html2text, re
+
+# 请求头,模拟浏览器UA
+headers = {'User-Agent': ' '.join(['Mozilla/5.0 (Windows NT 10.0; Win64; x64; ServiceUI 14)',
+            'AppleWebKit/537.36 (KHTML, like Gecko)', 'Chrome/70.0.3538.102', 'Safari/537.36','Edge/18.18363']) }
+
+def url_to_markdown(url):
+    # 发送请求
+    r = requests.get(url=url, headers=headers)
+    # html 转换 markdown
+    html = r.text
+    text = html2text.html2text(html)
+    return text
+
+def pull_urls(urls_list):
+    texts =''
+    for url in urls_list:
+      texts += url_to_markdown(url)
+    return texts
+
+# 正则搜索得到网址URL
+def get_url(line):
+    reg_https = r'(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]'
+    url = re.search(reg_https, line)
+    return url
+
+# 检查获得多行URL
+def check_urls(urls):
+    ret = []
+    lines = urls.split('\n')
+    for line in lines:
+        url = get_url(line)
+        if url is not None:
+            ret.append(url[0])
+    ret = list(set(ret))
+    return ret
+
+def urls_lines(urls_list):
+    str = '\n'.join(urls_list)
+    return str
+
+
+import base64 , hashlib, time
+# 构建 PASSKEY
+def make_passkey(str=''):
+    s = time.strftime("%Y%m%d-%H", time.localtime()) + str
+    b = s.encode("utf-8")
+    m = hashlib.sha256()
+    m.update(b)
+    passkey = base64.b64encode(m.digest()).decode("utf-8")[8:16]
+    return passkey

+ 97 - 0
ips.py

@@ -0,0 +1,97 @@
+import ipdb, ipaddress, requests, re, json
+from flask import Flask, request
+from socket import gethostbyname
+
+# load dynamic C library for map shift
+from ctypes import *
+# shift = cdll.LoadLibrary('./china_shift.so')
+
+class Location(Structure):
+    _fields_ = [
+        ('lon', c_double),
+        ('lat', c_double)]
+
+# shift.transformFromWGSToGCJ.argtypes = [Location]
+# shift.transformFromWGSToGCJ.restype = Location
+# shift.transformFromGCJToWGS.argtypes = [Location]
+# shift.transformFromGCJToWGS.restype = Location
+
+# shift.bd_encrypt.argtypes = [Location]
+# shift.bd_encrypt.restype = Location
+# shift.bd_decrypt.argtypes = [Location]
+# shift.bd_decrypt.restype = Location
+
+db = ipdb.BaseStation("qqwry.ipdb")
+
+def iplocated(ip):
+    city = db.find(ip, "CN")
+    return ip + " @" + city[0] + city[1] + city[2] + city[3] + "\n"
+
+def getcity(ip):
+    city = db.find(ip, "CN")
+    return  city[2] + '市'
+
+def getip():
+    ip = request.remote_addr
+    try:
+        _ip = request.headers["X-Real-IP"]
+        if _ip is not None:
+            ip = _ip
+    except Exception as e:
+        print(e)
+    return ip
+
+def is_Mozilla():
+    # Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
+    ua = request.headers["User-Agent"]
+    if (ua.find("Mozilla") != -1):
+        return True
+    else:
+        return False
+
+## 百度免费的 IP 普通定位 API 接口 
+def ip2bdgps(ip):
+    url = 'https://api.map.baidu.com/location/ip?ak=>>>百度AK码<<<&coor=bd09ll&ip=' + ip
+    try:
+        r = requests.get(url)
+        data = r.json()
+    except :
+        return
+
+    if data['status'] != 0 :
+        return  (116.39564504, 39.92998578 , data['status'])    # 查不到返回 北京 x,y
+    else:
+        x = data['content']['point']['x']
+        y = data['content']['point']['y']
+    return  (x, y, data['status'], data)
+
+## 免费试用500次,  1元能使用1万次 IP定位 API 接口   https://market.aliyun.com/products/57002002/cmapi00035184.html
+def ip2gdgps(ip):
+    url = 'http://ips.market.alicloudapi.com/iplocaltion?ip=' + ip
+    headers = {"Authorization":"APPCODE <<<APPCODE>>>" ,"Content-Type":"application/json; charset=utf-8" }
+    try:
+        r = requests.get(url=url , headers=headers)
+        data = r.json()
+    except :
+        return
+    # print(data)
+    if data['code'] != 100:
+        return  (116.39564504, 39.92998578 , data['code'])    # 查不到返回 北京 x,y
+    elif data['message'] == "success":
+        x = data['result']['lng']
+        y = data['result']['lat']
+        loc = Location(lon = float(x), lat = float(y))
+#       loc = shift.transformFromWGSToGCJ(loc)
+        # loc = shift.bd_encrypt(loc)
+        return  (loc.lon, loc.lat, data['code'], data)
+
+def select_ips(ips_text):
+    ret =''
+    iplist = re.findall(r"\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b", ips_text)
+    for ip in iplist:
+        try:
+            one = iplocated(ip)
+            ret+=one
+        except:
+            pass
+    return ret

+ 45 - 0
templates/getmd.html

@@ -0,0 +1,45 @@
+<!DOCTYPE html><html><head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>262235.xyz/ips | 批量ip查询地址</title>
+<meta name="keywords" content="批量网址转Markdown,开源WebAIP,开源IP定位,IP地址查询,极速批量IP地址查询,IP地址精确查询,IP精准定位,高精度IP定位,国外IP定位">
+<link rel="icon" href="/logo/favicon.png" type="image/png">
+<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
+<style type="text/css">
+body { padding-top: 40px; padding-bottom: 40px; background-color: #f5f5f5;
+font-family: "PingFang SC", "Helvetica Neue", "Helvetica", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; }
+a, input, button { outline: none !important; }
+a:focus, a:hover, .btn-link:focus, .btn-link:hover { text-decoration: underline; text-underline-position: under; }
+.main { max-width: 950px; padding: 19px 29px 29px; margin: 0 auto 20px; background-color: #fff;
+border: 1px solid #e5e5e5; -webkit-border-radius: 5px; -moz-border-radius: 5px;
+border-radius: 5px; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
+-moz-box-shadow: 0 1px 2px rgba(0,0,0,.05); box-shadow: 0 1px 2px rgba(0,0,0,.05); }
+.label-site { font-size: 14px;  vertical-align: middle; margin-right: 6px; }
+.text { width: 100%; height: 150px; }
+.btn-code { padding: 6px 16px; }
+</style>
+</head>
+<body>
+{% include 'navbar.html' %}
+<div class="main">
+{% if urls %}
+<legend><h3><span class="label label-success label-site">262235.xyz/getmd </span> 批量网址转Markdown: <a class="label label-info label-site" href="/getmd/">返回输入网址</a></h3></legend>
+<textarea type="text" name ="urls" cols=120 rows=5 class="form-control text">{{ urls }}</textarea>
+{% else %}
+<form action="/getmd/" method="post">
+<legend><h3><span class="label label-success label-site">262235.xyz/getmd </span> 批量网址转Markdown: <a class="label label-warning label-site" href="/">返回主页</a></h3></legend>
+<textarea type="text" name ="urls" cols=120 rows=20 class="form-control text" placeholder="示例输入: # Pthon 爬虫WebAPI版: 批量网址转Markdown
+https://262235.xyz/index.php/archives/584/"></textarea>
+<br>
+<h2 class="alert-success"><small>输入PASSKEY每次抓取5篇文章, PASSKEY:&nbsp;&nbsp;</small>{{ passkey }}</h2>
+<label for="inputPassword" class="sr-only">Password</label>
+<input type="text" id="inputPassword"  name='passkey' class="form-control" placeholder="PASSKEY" required>
+<br>
+  <button class="btn btn-lg btn-primary btn-block" type="submit">确认抓取Markdown</button>
+</form>
+{%  endif  %}
+{% if texts %}
+<div class="alert-success"><h3 style="text-align:center;">getmd 抓取Markdown文本 </h3></div>
+<textarea type="text" name ="texts" cols=120 rows=30 class="form-control text">{{ texts }}</textarea>
+{%  endif  %}
+</div></body></html>
+

+ 15 - 34
templates/hello.html

@@ -9,39 +9,20 @@ body { padding-top: 40px; padding-bottom: 40px; background-color: #f5f5f5;
 font-family: "PingFang SC", "Helvetica Neue", "Helvetica", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; }
 a, input, button { outline: none !important; }
 a:focus, a:hover, .btn-link:focus, .btn-link:hover { text-decoration: underline; text-underline-position: under; }
- .main { max-width: 950px; padding: 19px 29px 29px; margin: 0 auto 20px; background-color: #fff;
-    border: 1px solid #e5e5e5; -webkit-border-radius: 5px; -moz-border-radius: 5px;
-    border-radius: 5px; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
-    -moz-box-shadow: 0 1px 2px rgba(0,0,0,.05); box-shadow: 0 1px 2px rgba(0,0,0,.05); }
- .label-site { font-size: 14px;  vertical-align: middle; margin-right: 6px; }
- .text { width: 100%; height: 150px; }
- .btn-code { padding: 6px 16px; }
- .div-a{ float:left;width:45%;} 
- .div-b{ float:right;width:50%;} 
+.main { max-width: 950px; padding: 19px 29px 29px; margin: 0 auto 20px; background-color: #fff;
+border: 1px solid #e5e5e5; -webkit-border-radius: 5px; -moz-border-radius: 5px;
+border-radius: 5px; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
+-moz-box-shadow: 0 1px 2px rgba(0,0,0,.05); box-shadow: 0 1px 2px rgba(0,0,0,.05); }
+.label-site { font-size: 14px;  vertical-align: middle; margin-right: 6px; }
+.text { width: 100%; height: 150px; }
+.btn-code { padding: 6px 16px; }
+.div-a{ float:left;width:45%;} 
+.div-b{ float:right;width:50%;} 
 </style></head>
 <body style="text-align:center;">
-<nav class="navbar navbar-inverse navbar-fixed-top">
-    <div class="container">
-    <div class="navbar-header">
-        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
-        <span class="sr-only">Toggle navigation</span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-        </button>
-        <a class="navbar-brand" href="https://262235.xyz/ip/">Python Flask WebAPI</a>
-    </div>
-    <div id="navbar" class="collapse navbar-collapse">
-        <ul class="nav navbar-nav">
-        <li class="active"><a href="/">首页</a></li>
-        <li><a href="https://github.com/hongwenjun/ip">github源码</a></li>
-        <li><a href="https://hub.docker.com/r/hongwenjun/ip">docker镜像</a></li>
-        <li><a href="https://262235.xyz/index.php/archives/342/">搭建WebAPI参考文章</a></li>
-        </ul>
-    </div><!--/.nav-collapse -->
-    </div>
-</nav>
-    
+
+ {% include 'navbar.html' %}
+
 <div class="main">
 {% if ip %}
 <div class="panel panel-danger">
@@ -100,9 +81,9 @@ http://192.168.1.189:5000/ips/
     <div class="panel-heading">
       <h3 class="panel-title">命令行 curl 调用API:</h3>
     </div>
-<strong>curl https://262235.xyz/ip/</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 命令行 URL 要带 / <br>
-<strong>curl https://262235.xyz/ip/8.8.8.8</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 查询自定义 IP 定位<br>
-<strong>curl https://262235.xyz/ip/github.com</strong>&nbsp;&nbsp;# 按域名查 IP 定位
+<strong>curl -sL 262235.xyz/ip</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 命令行 -L 参数能重定向 <br>
+<strong>curl -sL 262235.xyz/ip/8.8.8.8</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# 查询自定义 IP 定位<br>
+<strong>curl -sL 262235.xyz/ip/github.com</strong>&nbsp;&nbsp;# 按域名查 IP 定位
 </div></div>
 
 <div class="div-b">

+ 26 - 45
templates/ips.html

@@ -6,54 +6,35 @@
 <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
 <style type="text/css">
 body { padding-top: 40px; padding-bottom: 40px; background-color: #f5f5f5;
-  font-family: "PingFang SC", "Helvetica Neue", "Helvetica", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; }
+font-family: "PingFang SC", "Helvetica Neue", "Helvetica", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif; }
 a, input, button { outline: none !important; }
 a:focus, a:hover, .btn-link:focus, .btn-link:hover { text-decoration: underline; text-underline-position: under; }
- .main { max-width: 950px; padding: 19px 29px 29px; margin: 0 auto 20px; background-color: #fff;
-  border: 1px solid #e5e5e5; -webkit-border-radius: 5px; -moz-border-radius: 5px;
-  border-radius: 5px; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
-  -moz-box-shadow: 0 1px 2px rgba(0,0,0,.05); box-shadow: 0 1px 2px rgba(0,0,0,.05); }
- .label-site { font-size: 14px;  vertical-align: middle; margin-right: 6px; }
- .text { width: 100%; height: 150px; }
- .btn-code { padding: 6px 16px; }
-  </style>
+.main { max-width: 950px; padding: 19px 29px 29px; margin: 0 auto 20px; background-color: #fff;
+border: 1px solid #e5e5e5; -webkit-border-radius: 5px; -moz-border-radius: 5px;
+border-radius: 5px; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.05);
+-moz-box-shadow: 0 1px 2px rgba(0,0,0,.05); box-shadow: 0 1px 2px rgba(0,0,0,.05); }
+.label-site { font-size: 14px;  vertical-align: middle; margin-right: 6px; }
+.text { width: 100%; height: 150px; }
+.btn-code { padding: 6px 16px; }
+</style>
 </head>
 <body>
-<nav class="navbar navbar-inverse navbar-fixed-top">
-  <div class="container">
-    <div class="navbar-header">
-      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
-        <span class="sr-only">Toggle navigation</span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-        <span class="icon-bar"></span>
-      </button>
-      <a class="navbar-brand" href="https://262235.xyz/ip/">Python Flask WebAPI</a>
-    </div>
-    <div id="navbar" class="collapse navbar-collapse">
-      <ul class="nav navbar-nav">
-        <li class="active"><a href="/">首页</a></li>
-        <li><a href="https://github.com/hongwenjun/ip">github源码</a></li>
-        <li><a href="https://hub.docker.com/r/hongwenjun/ip">docker镜像</a></li>
-        <li><a href="https://262235.xyz/index.php/archives/342/">搭建WebAPI参考文章</a></li>
-      </ul>
-    </div><!--/.nav-collapse -->
-  </div>
-</nav>
 
-  <div class="main">
-  <form action="/ips/" method="post">
-    <fieldset>
-  {% if ips %}
-    <legend><h3><span class="label label-success label-site">262235.xyz/ips </span> 批量ip查询地址: <a class="label label-warning label-site" href="/ips/">重新查询</a></h3></legend>
-    <textarea type="text" name ="ips" cols=120 rows=40 class="form-control text">{{ ips }}</textarea>
-  {% else %}
-    <legend><h3><span class="label label-success label-site">262235.xyz/ips </span> 批量ip查询地址:  <a class="label label-info label-site" href="/">返回主页</a></h3></legend>
-    <textarea type="text" name ="ips" cols=120 rows=20 class="form-control text" placeholder="输入多行包含ip地址的日志,例:
-  http://192.168.1.189:5000/ips/
-  172.67.158.52  cloudflare.com"></textarea>
-    <br><input type="submit" value="点击查询"  class="btn btn-primary btn-code" >
-  {%  endif  %}
-    </fieldset>
-    </form>
+  {% include 'navbar.html' %}
+
+<div class="main">
+<form action="/ips/" method="post">
+  <fieldset>
+{% if ips %}
+  <legend><h3><span class="label label-success label-site">262235.xyz/ips </span> 批量ip查询地址: <a class="label label-warning label-site" href="/ips/">重新查询</a></h3></legend>
+  <textarea type="text" name ="ips" cols=120 rows=40 class="form-control text">{{ ips }}</textarea>
+{% else %}
+  <legend><h3><span class="label label-success label-site">262235.xyz/ips </span> 批量ip查询地址:  <a class="label label-info label-site" href="/">返回主页</a></h3></legend>
+  <textarea type="text" name ="ips" cols=120 rows=20 class="form-control text" placeholder="输入多行包含ip地址的日志,例:
+http://192.168.1.189:5000/ips/
+172.67.158.52  cloudflare.com"></textarea>
+  <br><input type="submit" value="点击查询"  class="btn btn-primary btn-code" >
+{%  endif  %}
+  </fieldset>
+  </form>
 </div></body></html>

+ 39 - 0
templates/navbar.html

@@ -0,0 +1,39 @@
+<nav class="navbar navbar-inverse navbar-fixed-top">
+  <div class="container">
+  <div class="navbar-header">
+      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
+      <span class="sr-only">Toggle navigation</span>
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+      <span class="icon-bar"></span>
+      </button>
+      <a class="navbar-brand" href="https://262235.xyz/ip/">Python Flask WebAPI</a>
+  </div>
+  <div id="navbar" class="collapse navbar-collapse">
+      <ul class="nav navbar-nav">
+      <li class="active"><a href="/">首页</a></li>
+      <li><a href="https://github.com/hongwenjun/ip">github源码</a></li>
+      <li><a href="https://hub.docker.com/r/hongwenjun/ip">docker镜像</a></li>
+      <li><a href="https://262235.xyz/index.php/search/webapi/">搭建WebAPI参考文章</a></li>
+      
+      <li class="dropdown">
+          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">在线工具箱<span class="caret"></span></a>
+              <ul class="dropdown-menu">
+              <li><a href="https://262235.xyz/bs/">Bootstrap theme</a></li>
+              <li><a href="https://www.262235.xyz/index.php/246.html">编程中文文档</a></li>
+              <li><a href="https://262235.xyz/linux-command/">Linux 命令列表</a></li>
+              <li><a href="https://262235.xyz/ip/">IP定位和地图</a></li>
+              <li><a href="https://262235.xyz/ips/">批量IP查询</a></li>
+              <li><a href="https://262235.xyz/getmd/">批量网址转Markdown</a></li>
+              <li><a href="https://tool.lu/markdown/">Markdown编辑器</a></li>
+              
+             
+              </ul>
+          </li>
+      </ul>
+  </div><!--/.nav-collapse -->
+  </div>
+</nav>
+
+<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
+<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>