{"id":7177,"date":"2026-04-12T11:53:52","date_gmt":"2026-04-12T03:53:52","guid":{"rendered":"http:\/\/192.168.1.29\/?p=7177"},"modified":"2026-04-12T11:53:54","modified_gmt":"2026-04-12T03:53:54","slug":"%e6%a0%91%e8%8e%93%e6%b4%be%e7%bd%91%e5%9d%80nginx%e8%ae%bf%e9%97%ae%e6%97%a5%e5%bf%97%e5%88%86%e6%9e%90","status":"publish","type":"post","link":"http:\/\/cnliutz.ipyingshe.net\/?p=7177","title":{"rendered":"\u6811\u8393\u6d3e\u7f51\u5740nginx\u8bbf\u95ee\u65e5\u5fd7\u5206\u6790"},"content":{"rendered":"\n<p>\u65e5\u5fd7\u89e3\u6790\u5b8c\u6210\uff0c\u603b\u8bbf\u95ee\u91cf\uff1a641805 \u6761<\/p>\n\n\n\n<p>===== \u7edf\u8ba1\u7ed3\u679c =====<br>\u603b\u8bbf\u95ee\u91cf\uff1a641805<br>\u72ec\u7acbIP\u6570\uff1a14<br>\u6700\u6d3b\u8dc3IP\uff1a192.168.1.29\uff08\u8bbf\u95ee492948\u6b21\uff09<br>\u8bbf\u95ee\u9ad8\u5cf0\u65f6\u6bb5\uff1a16\u65f6\uff0859997\u6b21\uff09<br>\u56fe\u8868\u5df2\u4fdd\u5b58\u81f3\uff1aC:\/Users\/czliu\/Downloads\/nginx_analysis.png<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"634\" src=\"http:\/\/192.168.1.29\/wp-content\/uploads\/2026\/04\/image-1024x634.png\" alt=\"\" class=\"wp-image-7178\" srcset=\"http:\/\/cnliutz.ipyingshe.net\/wp-content\/uploads\/2026\/04\/image-1024x634.png 1024w, http:\/\/cnliutz.ipyingshe.net\/wp-content\/uploads\/2026\/04\/image-300x186.png 300w, http:\/\/cnliutz.ipyingshe.net\/wp-content\/uploads\/2026\/04\/image-768x476.png 768w, http:\/\/cnliutz.ipyingshe.net\/wp-content\/uploads\/2026\/04\/image-1536x952.png 1536w, http:\/\/cnliutz.ipyingshe.net\/wp-content\/uploads\/2026\/04\/image-2048x1269.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>import re\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom collections import Counter\nfrom datetime import datetime\n\n# ===================== \u914d\u7f6e\u9879\uff08\u4f60\u7684\u65e5\u5fd7\u8def\u5f84\uff09 =====================\nLOG_PATH = r\"C:\\Users\\czliu\\Downloads\\access.log\"\n# ==================================================================\n\n# \u8f85\u52a9\u51fd\u6570\uff1a\u6e05\u7406\u5b57\u7b26\u4e32\u4e2d\u7684\u65e0\u6548\u5b57\u7b26\ndef clean_string(s):\n    if isinstance(s, str):\n        # \u79fb\u9664\u975e\u6253\u5370\u5b57\u7b26\u548c\u4e8c\u8fdb\u5236\u6570\u636e\n        return ''.join(c for c in s if c.isprintable())\n    return s\n\n# 1. Nginx\u65e5\u5fd7\u6b63\u5219\u8868\u8fbe\u5f0f\uff08\u901a\u7528\u683c\u5f0f\uff09\n# \u5339\u914d\u683c\u5f0f\uff1aIP - - &#91;\u65f6\u95f4] \"\u8bf7\u6c42\" \u72b6\u6001\u7801 \u5927\u5c0f \"\u6765\u6e90\" \"UA\"\nlog_pattern = re.compile(\n    r'(\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+-\\s+-\\s+\\&#91;(.*?)\\]\\s+\"(.*?)\"\\s+(\\d+)\\s+(\\d+|-)'\n)\n\n# 2. \u89e3\u6790\u65e5\u5fd7\nparsed_data = &#91;]\nwith open(LOG_PATH, 'r', encoding='utf-8', errors='ignore') as f:\n    for line in f:\n        # \u6e05\u7406\u65e5\u5fd7\u884c\u4e2d\u7684\u65e0\u6548\u5b57\u7b26\n        clean_line = clean_string(line)\n        match = log_pattern.match(clean_line.strip())\n        if match:\n            ip, time_str, request, status, size = match.groups()\n            \n            # \u6e05\u7406\u5404\u4e2a\u5b57\u6bb5\n            ip = clean_string(ip)\n            time_str = clean_string(time_str)\n            request = clean_string(request)\n            status = clean_string(status)\n            size = clean_string(size)\n            \n            # \u5904\u7406\u65f6\u95f4\n            dt = None\n            try:\n                # \u65e5\u5fd7\u65f6\u95f4\u683c\u5f0f\uff1a03\/Jan\/2025:12:34:56 +0800\n                dt = datetime.strptime(time_str, '%d\/%b\/%Y:%H:%M:%S %z')\n                hour = dt.hour  # \u6309\u5c0f\u65f6\u7edf\u8ba1\n            except:\n                hour = -1\n            \n            # \u63d0\u53d6\u8bf7\u6c42\u65b9\u6cd5\u548cURL\n            req_parts = request.split()\n            method = req_parts&#91;0] if len(req_parts) > 0 else 'UNKNOWN'\n            url = req_parts&#91;1] if len(req_parts) > 1 else '\/'\n            \n            # \u518d\u6b21\u6e05\u7406\u65b9\u6cd5\u548cURL\n            method = clean_string(method)\n            url = clean_string(url)\n            \n            parsed_data.append({\n                'ip': ip,\n                'time': dt,\n                'hour': hour,\n                'method': method,\n                'url': url,\n                'status': int(status),\n                'size': int(size) if size != '-' else 0\n            })\n\n# \u8f6c\u4e3aDataFrame\u65b9\u4fbf\u5206\u6790\ndf = pd.DataFrame(parsed_data)\nprint(f\"\u65e5\u5fd7\u89e3\u6790\u5b8c\u6210\uff0c\u603b\u8bbf\u95ee\u91cf\uff1a{len(df)} \u6761\")\n\n# \u6e05\u7406\u6570\u636e\nif len(df) > 0:\n    df&#91;'ip'] = df&#91;'ip'].apply(clean_string)\n    df&#91;'method'] = df&#91;'method'].apply(clean_string)\n    df&#91;'url'] = df&#91;'url'].apply(clean_string)\n\n# 3. \u5206\u6790\u6838\u5fc3\u6570\u636e\n# 3.1 \u8bbf\u95ee\u91cfTOP10 IP\nip_top10 = Counter(df&#91;'ip']).most_common(10)\n\n# 3.2 \u6309\u5c0f\u65f6\u8bbf\u95ee\u8d8b\u52bf\nhour_counts = df&#91;df&#91;'hour'] != -1]&#91;'hour'].value_counts().sort_index()\n\n# 3.3 HTTP\u72b6\u6001\u7801\u5206\u5e03\nstatus_counts = df&#91;'status'].value_counts()\n\n# 3.4 \u8bf7\u6c42\u65b9\u6cd5\u5206\u5e03\nmethod_counts = df&#91;'method'].value_counts()\n\n# 4. \u7ed8\u5236\u7efc\u5408\u56fe\u8868\uff082x2\u5b50\u56fe\uff09\nif len(df) > 0:\n    plt.rcParams&#91;'font.sans-serif'] = &#91;'SimHei']  # \u89e3\u51b3\u4e2d\u6587\u4e71\u7801\n    plt.rcParams&#91;'axes.unicode_minus'] = False\n    plt.rcParams&#91;'text.usetex'] = False  # \u7981\u7528LaTeX\n    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 10))\n    fig.suptitle('Nginx\u8bbf\u95ee\u65e5\u5fd7\u5206\u6790\u62a5\u544a', fontsize=18, fontweight='bold')\n    \n    # \u5b50\u56fe1\uff1aTOP10\u8bbf\u95eeIP\n    if ip_top10:\n        # \u6e05\u7406IP\u5730\u5740\u4e2d\u7684\u7279\u6b8a\u5b57\u7b26\u5e76\u9650\u5236\u957f\u5ea6\n        clean_ips = &#91;]\n        for ip, _ in ip_top10:\n            clean_ip = clean_string(ip)\n            # \u9650\u5236IP\u663e\u793a\u957f\u5ea6\uff0c\u907f\u514d\u8fc7\u957f\n            if len(clean_ip) > 15:\n                clean_ip = clean_ip&#91;:15] + '...'\n            clean_ips.append(clean_ip)\n        ax1.barh(clean_ips, &#91;cnt for _, cnt in ip_top10], color='#1f77b4')\n        ax1.set_title('TOP10 \u8bbf\u95eeIP', fontsize=14)\n        ax1.set_xlabel('\u8bbf\u95ee\u6b21\u6570')\n    else:\n        ax1.set_title('TOP10 \u8bbf\u95eeIP', fontsize=14)\n        ax1.text(0.5, 0.5, '\u65e0\u6570\u636e', ha='center', va='center')\n    \n    # \u5b50\u56fe2\uff1a\u5c0f\u65f6\u8bbf\u95ee\u8d8b\u52bf\n    if not hour_counts.empty:\n        ax2.plot(hour_counts.index, hour_counts.values, marker='o', color='#ff7f0e', linewidth=2)\n        ax2.set_title('24\u5c0f\u65f6\u8bbf\u95ee\u8d8b\u52bf', fontsize=14)\n        ax2.set_xlabel('\u5c0f\u65f6')\n        ax2.set_ylabel('\u8bbf\u95ee\u91cf')\n        ax2.grid(alpha=0.3)\n    else:\n        ax2.set_title('24\u5c0f\u65f6\u8bbf\u95ee\u8d8b\u52bf', fontsize=14)\n        ax2.text(0.5, 0.5, '\u65e0\u6570\u636e', ha='center', va='center')\n    \n    # \u5b50\u56fe3\uff1aHTTP\u72b6\u6001\u7801\u5206\u5e03\n    if not status_counts.empty:\n        colors = &#91;'#2ca02c', '#d62728', '#9467bd', '#8c564b']\n        # \u786e\u4fdd\u6807\u7b7e\u662f\u5b57\u7b26\u4e32\u4e14\u5e72\u51c0\n        labels = &#91;str(label) for label in status_counts.index]\n        ax3.pie(status_counts.values, labels=labels, autopct='%1.1f%%', colors=colors&#91;:len(status_counts)])\n        ax3.set_title('HTTP\u72b6\u6001\u7801\u5206\u5e03', fontsize=14)\n    else:\n        ax3.set_title('HTTP\u72b6\u6001\u7801\u5206\u5e03', fontsize=14)\n        ax3.text(0.5, 0.5, '\u65e0\u6570\u636e', ha='center', va='center')\n    \n    # \u5b50\u56fe4\uff1a\u8bf7\u6c42\u65b9\u6cd5\u5206\u5e03\n    if not method_counts.empty:\n        # \u6e05\u7406\u8bf7\u6c42\u65b9\u6cd5\u4e2d\u7684\u7279\u6b8a\u5b57\u7b26\u5e76\u8fc7\u6ee4\u6389\u65e0\u6548\u65b9\u6cd5\n        clean_methods = &#91;]\n        clean_values = &#91;]\n        for method, cnt in method_counts.items():\n            clean_method = clean_string(method)\n            # \u53ea\u4fdd\u7559\u6709\u6548\u7684HTTP\u65b9\u6cd5\n            if clean_method in &#91;'GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'] or cnt > 10:\n                clean_methods.append(clean_method)\n                clean_values.append(cnt)\n        \n        if clean_methods:\n            ax4.bar(clean_methods, clean_values, color='#e377c2')\n            ax4.set_title('\u8bf7\u6c42\u65b9\u6cd5\u5206\u5e03', fontsize=14)\n            ax4.set_ylabel('\u6b21\u6570')\n        else:\n            ax4.set_title('\u8bf7\u6c42\u65b9\u6cd5\u5206\u5e03', fontsize=14)\n            ax4.text(0.5, 0.5, '\u65e0\u6570\u636e', ha='center', va='center')\n    else:\n        ax4.set_title('\u8bf7\u6c42\u65b9\u6cd5\u5206\u5e03', fontsize=14)\n        ax4.text(0.5, 0.5, '\u65e0\u6570\u636e', ha='center', va='center')\n    \n    plt.tight_layout()\n    plt.savefig(r'C:\\Users\\czliu\\Downloads\\nginx_analysis.png', dpi=300, bbox_inches='tight')\n    plt.close()  # \u5173\u95ed\u56fe\u8868\uff0c\u907f\u514d\u5728\u975e\u4ea4\u4e92\u5f0f\u73af\u5883\u4e2d\u51fa\u73b0\u95ee\u9898\n\n# 5. \u6253\u5370\u5173\u952e\u7edf\u8ba1\nprint(\"\\n===== \u7edf\u8ba1\u7ed3\u679c =====\")\nprint(f\"\u603b\u8bbf\u95ee\u91cf\uff1a{len(df)}\")\nprint(f\"\u72ec\u7acbIP\u6570\uff1a{df&#91;'ip'].nunique()}\")\nif ip_top10:\n    print(f\"\u6700\u6d3b\u8dc3IP\uff1a{ip_top10&#91;0]&#91;0]}\uff08\u8bbf\u95ee{ip_top10&#91;0]&#91;1]}\u6b21\uff09\")\nelse:\n    print(\"\u6700\u6d3b\u8dc3IP\uff1a\u65e0\u6570\u636e\")\nif not hour_counts.empty:\n    print(f\"\u8bbf\u95ee\u9ad8\u5cf0\u65f6\u6bb5\uff1a{hour_counts.idxmax()}\u65f6\uff08{hour_counts.max()}\u6b21\uff09\")\nelse:\n    print(\"\u8bbf\u95ee\u9ad8\u5cf0\u65f6\u6bb5\uff1a\u65e0\u6570\u636e\")\nif len(df) > 0:\n    print(f\"\u56fe\u8868\u5df2\u4fdd\u5b58\u81f3\uff1aC:\/Users\/czliu\/Downloads\/nginx_analysis.png\")\nelse:\n    print(\"\u56fe\u8868\uff1a\u65e0\u6570\u636e\uff0c\u672a\u751f\u6210\")<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u65e5\u5fd7\u89e3\u6790\u5b8c\u6210\uff0c\u603b\u8bbf\u95ee\u91cf\uff1a641805 \u6761 ===== \u7edf\u8ba1\u7ed3\u679c =====\u603b\u8bbf\u95ee <span class=\"readmore\"><a href=\"http:\/\/cnliutz.ipyingshe.net\/?p=7177\">Continue Reading<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1,6,11],"tags":[],"class_list":["post-7177","post","type-post","status-publish","format-standard","hentry","category-uncategorized","category-6","category-11"],"_links":{"self":[{"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=\/wp\/v2\/posts\/7177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7177"}],"version-history":[{"count":1,"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=\/wp\/v2\/posts\/7177\/revisions"}],"predecessor-version":[{"id":7179,"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=\/wp\/v2\/posts\/7177\/revisions\/7179"}],"wp:attachment":[{"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7177"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/cnliutz.ipyingshe.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}