{"id":4451,"date":"2017-02-23T20:40:19","date_gmt":"2017-02-23T12:40:19","guid":{"rendered":"http:\/\/blog.qdac.cc\/?p=4451"},"modified":"2025-03-10T13:08:46","modified_gmt":"2025-03-10T05:08:46","slug":"%e7%ba%af%e7%9c%9fip%e6%95%b0%e6%8d%ae%e5%ba%93%e8%a7%a3%e6%9e%90delphi-d10-1%e4%b8%8b%e6%ad%a3%e5%b8%b8%e4%bd%bf%e7%94%a8","status":"publish","type":"post","link":"https:\/\/blog.qdac.cc\/?p=4451","title":{"rendered":"\u7eaf\u771fIP\u6570\u636e\u5e93\u89e3\u6790Delphi D10.1\u4e0b\u6b63\u5e38\u4f7f\u7528"},"content":{"rendered":"\n<p>\u7eaf\u771fIP \u662f\u4e00\u4e2a\u5f88\u77e5\u540d\u7684IP\u5730\u5740\u6570\u636e\u5e93\uff0c\u5b98\u65b9\u7f51\u7ad9\uff1a<a href=\"https:\/\/www.cz88.net\">\u70b9\u51fb\u8df3\u8f6c<\/a><\/p>\n\n\n\n<p>\u5176\u4e2d\u793e\u533a\u7248IP\u5730\u5740\u5e93\uff0c\u53ea\u8981\u83b7\u5f97\u7eaf\u771f\u7684\u6388\u6743\u5c31\u80fd\u514d\u8d39\u4f7f\u7528\uff0c\u5e76\u4e0d\u65ad\u83b7\u53d6\u540e\u7eed\u66f4\u65b0\u7684\u7248\u672c\u3002\u5982\u679c\u6709\u9700\u8981\u514d\u8d39\u7248IP\u5e93\u7684\u670b\u53cb\u53ef\u4ee5\u524d\u5f80\u7eaf\u771f\u7684\u5b98\u7f51\u8fdb\u884c\u7533\u8bf7\u3002\u4ed6\u4eec\u9664\u4e86\u514d\u8d39\u7684\u793e\u533a\u7248IP\u5e93\u5916\uff0c\u8fd8\u63d0\u4f9b\u6570\u636e\u66f4\u52a0\u51c6\u786e\u3001\u670d\u52a1\u66f4\u52a0\u5468\u5168\u7684\u5546\u4e1a\u7248IP\u5730\u5740\u67e5\u8be2\u6570\u636e\u3002\u7eaf\u771f\u56f4\u7ed5IP\u5730\u5740\uff0c\u57fa\u4e8e \u7f51\u7edc\u7a7a\u95f4\u62d3\u6251\u6d4b\u7ed8 + \u79fb\u52a8\u4f4d\u7f6e\u5927\u6570\u636e \u65b9\u6848\uff0c\u5bf9IP\u5730\u5740\u5b9a\u4f4d\u3001IP\u7f51\u7edc\u98ce\u9669\u3001IP\u4f7f\u7528\u573a\u666f\u3001IP\u7f51\u7edc\u7c7b\u578b\u3001\u79d2\u62e8\u4fa6\u6d4b\u3001VPN\u4fa6\u6d4b\u3001\u4ee3\u7406\u4fa6\u6d4b\u3001\u722c\u866b\u4fa6\u6d4b\u3001\u771f\u4eba\u5ea6\u7b49\u5747\u6709\u8fd120\u5e74\u4e30\u5bcc\u7684\u6570\u636e\u6c89\u6dc0\u3002<\/p>\n\n\n\n<p>\u4e0b\u9762\u662f\u7eaf\u771fIP\u6570\u636e\u5e93\u7684 Delphi \u89e3\u6790\u4ee3\u7801\uff0c\u6ca1\u6709\u9002\u914d\u6700\u8fd1\u7684CZDB\u683c\u5f0f\uff0c\u6682\u65f6\u53ea\u652f\u6301 dat \u683c\u5f0f\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>unit Net.IPLocation;\n\ninterface\n\nuses System.Classes, System.SysUtils, Winapi.WinSock, Vcl.Forms,\n  System.Math, System.SyncObjs;\n\ntype\n  TIPLocation = class(TObject)\n  private\n    QQWryFileName: string;\n    QQWryFileStream: TBufferedFileStream;\n    QQWryFileSize: Cardinal;\n    IPRecordNum: Cardinal;\n    FirstIPIndexOffset, LastIPIndexOffset: Cardinal;\n    FLock: TCriticalSection;\n\n    function GetQQWryFileName: string;\n    function GetQQWryFileSize: Cardinal;\n    function GetIPRecordNum: Cardinal;\n    function GetQQWryDate: TDate;\n    function GetQQWryDataFrom: string;\n    function GetIPLocation(IPLocationOffset: Cardinal): TStringlist;\n    function GetIPMsg(IPRecordID: Cardinal): TStringlist;\n    function GetIPRecordID(IP: string): Cardinal;\n    function GetIPValue(IP: string): Cardinal;\n  public\n    constructor Create(cQQWryFileName: string);\n    destructor Destroy; override;\n    function GetLocation(IP: string): String;\n  end;\n\nfunction IPLocation: TIPLocation;\n\nimplementation\n\nvar\n  __IPLocation: TIPLocation;\n\nfunction IPLocation: TIPLocation;\nbegin\n  if __IPLocation = nil then\n    __IPLocation := TIPLocation.Create(ExtractFilePath(ParamStr(0)) +\n      'qqwry.dat');\n\n  Result := __IPLocation;\nend;\n\n{ TIPLocation }\n\nconstructor TIPLocation.Create(cQQWryFileName: string);\nbegin\n  inherited Create;\n  FLock := TCriticalSection.Create;\n  QQWryFileName := cQQWryFileName;\n  QQWryFileStream := TBufferedFileStream.Create(QQWryFileName,\n    fmOpenRead or fmShareDenyWrite, 0);\n  QQWryFileSize := QQWryFileStream.Size;\n  QQWryFileStream.Read(FirstIPIndexOffset, 4);\n  QQWryFileStream.Read(LastIPIndexOffset, 4);\n  IPRecordNum := (LastIPIndexOffset - FirstIPIndexOffset) div 7 + 1;\nend;\n\ndestructor TIPLocation.Destroy;\nbegin\n\n  QQWryFileStream.Free;\n  FLock.Free;\n  inherited Destroy;\nend;\n\nfunction TIPLocation.GetIPLocation(IPLocationOffset: Cardinal): TStringlist;\nconst\n  \/\/ \u5b9e\u9645\u4fe1\u606f\u5b57\u4e32\u5b58\u653e\u4f4d\u7f6e\u7684\u91cd\u5b9a\u5411\u6a21\u5f0f\n  REDIRECT_MODE_1 = 1;\n  REDIRECT_MODE_2 = 2;\nvar\n  RedirectMode: byte;\n  CountryFirstOffset, CountrySecondOffset: Cardinal;\n  CountryMsg, AreaMsg: string;\n  \/\/\n  function ReadString(StringOffset: Cardinal): ansistring;\n  var\n    ReadByte: ansichar;\n  begin\n    Result := '';\n    QQWryFileStream.Seek(StringOffset, soFromBeginning);\n    QQWryFileStream.Read(ReadByte, 1);\n    while ord(ReadByte) &lt;> 0 do\n    begin\n      Result := Result + ReadByte;\n      QQWryFileStream.Read(ReadByte, 1);\n    end;\n  end;\n\/\/\n  function ReadArea(AreaOffset: Cardinal): ansistring;\n  var\n    ModeByte: byte;\n    ReadAreaOffset: Cardinal;\n  begin\n    ReadAreaOffset := 0;\n    QQWryFileStream.Seek(AreaOffset, soFromBeginning);\n    QQWryFileStream.Read(ModeByte, 1);\n    if (ModeByte = REDIRECT_MODE_1) or (ModeByte = REDIRECT_MODE_2) then\n    begin\n      QQWryFileStream.Read(ReadAreaOffset, 3);\n      if ReadAreaOffset = 0 then\n        Result := '\u672a\u77e5\u5730\u533a'\n      else\n        Result := ReadString(ReadAreaOffset);\n    end\n    else\n    begin\n      Result := ReadString(AreaOffset);\n    end;\n  end;\n\nbegin\n  CountryFirstOffset := 0;\n  CountrySecondOffset := 0;\n  \/\/ \u8df3\u8fc74\u4e2a\u5b57\u8282\uff0c\u8be54\u5b57\u8282\u5185\u5bb9\u4e3a\u8be5\u6761IP\u4fe1\u606f\u91ccIP\u5730\u5740\u6bb5\u4e2d\u7684\u7ec8\u6b62IP\u503c\n  QQWryFileStream.Seek(IPLocationOffset + 4, soFromBeginning);\n  \/\/ \u8bfb\u53d6\u56fd\u5bb6\u4fe1\u606f\u7684\u91cd\u5b9a\u5411\u6a21\u5f0f\u503c\n  QQWryFileStream.Read(RedirectMode, 1);\n  \/\/ \u91cd\u5b9a\u5411\u6a21\u5f0f1\u7684\u5904\u7406\n  if RedirectMode = REDIRECT_MODE_1 then\n  begin\n    \/\/ \u6a21\u5f0f\u503c\u4e3a1\uff0c\u5219\u540e3\u4e2a\u5b57\u8282\u7684\u5185\u5bb9\u4e3a\u56fd\u5bb6\u4fe1\u606f\u7684\u91cd\u5b9a\u5411\u504f\u79fb\u503c\n    QQWryFileStream.ReadData(CountryFirstOffset, 3);\n    \/\/ \u8fdb\u884c\u91cd\u5b9a\u5411\n    QQWryFileStream.Seek(CountryFirstOffset, soFromBeginning);\n    \/\/ \u7b2c\u4e8c\u6b21\u8bfb\u53d6\u56fd\u5bb6\u4fe1\u606f\u7684\u91cd\u5b9a\u5411\u6a21\u5f0f\n    QQWryFileStream.Read(RedirectMode, 1);\n    \/\/ \u7b2c\u4e8c\u6b21\u91cd\u5b9a\u5411\u6a21\u5f0f\u4e3a\u6a21\u5f0f2\u7684\u5904\u7406\n    if RedirectMode = REDIRECT_MODE_2 then\n    begin\n      \/\/ \u540e3\u5b57\u8282\u7684\u5185\u5bb9\u5373\u4e3a\u7b2c\u4e8c\u6b21\u91cd\u5b9a\u5411\u504f\u79fb\u503c\n      QQWryFileStream.ReadData(CountrySecondOffset, 3);\n      \/\/ \u8bfb\u53d6\u7b2c\u4e8c\u6b21\u91cd\u5b9a\u5411\u504f\u79fb\u503c\u4e0b\u7684\u5b57\u7b26\u4e32\u503c\uff0c\u5373\u4e3a\u56fd\u5bb6\u4fe1\u606f\n      CountryMsg := ReadString(CountrySecondOffset);\n      \/\/ \u82e5\u7b2c\u4e00\u6b21\u91cd\u5b9a\u5411\u6a21\u5f0f\u4e3a1\uff0c\u8fdb\u884c\u91cd\u5b9a\u5411\u540e\u8bfb\u53d6\u7684\u7b2c\u4e8c\u6b21\u91cd\u5b9a\u5411\u6a21\u5f0f\u4e3a2\uff0c\n      \/\/ \u5219\u5730\u533a\u4fe1\u606f\u5b58\u653e\u5728\u7b2c\u4e00\u6b21\u56fd\u5bb6\u4fe1\u606f\u504f\u79fb\u503c\u7684\u540e\u9762\n      QQWryFileStream.Seek(CountryFirstOffset + 4, soFromBeginning);\n      \/\/ \u7b2c\u4e8c\u6b21\u91cd\u5b9a\u5411\u6a21\u5f0f\u4e0d\u662f\u6a21\u5f0f2\u7684\u5904\u7406\n    end\n    else\n    begin\n      CountryMsg := ReadString(CountryFirstOffset);\n    end;\n    \/\/ \u5728\u91cd\u5b9a\u5411\u6a21\u5f0f1\u4e0b\u8bfb\u5730\u533a\u4fe1\u606f\u503c\n    AreaMsg := ReadArea(QQWryFileStream.Position);\n    \/\/ \u91cd\u5b9a\u5411\u6a21\u5f0f2\u7684\u5904\u7406\n  end\n  else if RedirectMode = REDIRECT_MODE_2 then\n  begin\n    QQWryFileStream.ReadData(CountrySecondOffset, 3);\n    CountryMsg := ReadString(CountrySecondOffset);\n    AreaMsg := ReadArea(IPLocationOffset + 8);\n    \/\/ \u4e0d\u662f\u91cd\u5b9a\u5411\u6a21\u5f0f\u7684\u5904\u7406\uff0c\u5b58\u653e\u7684\u5373\u662fIP\u5730\u5740\u4fe1\u606f\n  end\n  else\n  begin\n    CountryMsg := ReadString(QQWryFileStream.Position - 1);\n    AreaMsg := ReadArea(QQWryFileStream.Position);\n  end;\n  Result := TStringlist.Create;\n  Result.Add(CountryMsg);\n  Result.Add(AreaMsg);\nend;\n\nfunction TIPLocation.GetIPMsg(IPRecordID: Cardinal): TStringlist;\nvar\n  aryStartIP: array &#91;1 .. 4] of byte;\n  strStartIP: string;\n  EndIPOffset: Cardinal;\n  aryEndIP: array &#91;1 .. 4] of byte;\n  strEndIP: string;\n  i: integer;\nbegin\n  EndIPOffset := 0;\n\n  \/\/ \u6839\u636e\u8bb0\u5f55ID\u53f7\u79fb\u5230\u8be5\u8bb0\u5f55\u53f7\u7684\u7d22\u5f15\u5904\n  QQWryFileStream.Seek(FirstIPIndexOffset + (IPRecordID - 1) * 7,\n    soFromBeginning);\n  \/\/ \u7d22\u5f15\u7684\u524d4\u4e2a\u5b57\u8282\u4e3a\u8d77\u59cbIP\u5730\u5740\n  QQWryFileStream.Read(aryStartIP, 4);\n  \/\/ \u540e3\u4e2a\u5b57\u8282\u662f\u5185\u5bb9\u533a\u57df\u7684\u504f\u79fb\u503c\n  \/\/ QQWryFileStream.Read(EndIPOffset, 3);\n  QQWryFileStream.ReadData(EndIPOffset, 3);\n  \/\/ \u79fb\u81f3\u5185\u5bb9\u533a\u57df\n  QQWryFileStream.Seek(EndIPOffset, soFromBeginning);\n  \/\/ \u5185\u5bb9\u533a\u57df\u7684\u524d4\u4e2a\u5b57\u8282\u4e3a\u7ec8\u6b62IP\u5730\u5740\n  QQWryFileStream.Read(aryEndIP, 4);\n\n  \/\/ \u5c06\u8d77\u6b62IP\u5730\u5740\u8f6c\u6362\u4e3a\u70b9\u5206\u7684\u5f62\u5f0f\n  strStartIP := '';\n  for i := 4 downto 1 do\n  begin\n    if i &lt;> 1 then\n      strStartIP := strStartIP + IntToStr(aryStartIP&#91;i]) + '.'\n    else\n      strStartIP := strStartIP + IntToStr(aryStartIP&#91;i]);\n  end;\n  strEndIP := '';\n  for i := 4 downto 1 do\n  begin\n    if i &lt;> 1 then\n      strEndIP := strEndIP + IntToStr(aryEndIP&#91;i]) + '.'\n    else\n      strEndIP := strEndIP + IntToStr(aryEndIP&#91;i]);\n  end;\n  Result := TStringlist.Create;\n  Result.Add(strStartIP);\n  Result.Add(strEndIP);\n  \/\/ \u83b7\u53d6\u8be5\u6761\u8bb0\u5f55\u4e0b\u7684IP\u5730\u5740\u4fe1\u606f\n  \/\/ \u4ee5\u4e0b\u4e09\u8005\u662f\u7edf\u4e00\u7684\uff1a\u2460\u5185\u5bb9\u533a\u57df\u7684\u504f\u79fb\u503c \u2461\u7ec8\u6b62IP\u5730\u5740\u7684\u5b58\u653e\u4f4d\u7f6e \u2462\u56fd\u5bb6\u4fe1\u606f\u7d27\u63a5\u5728\u7ec8\u6b62IP\u5730\u5740\u5b58\u653e\u4f4d\u7f6e\u540e\n  Result.AddStrings(GetIPLocation(EndIPOffset));\nend;\n\nfunction TIPLocation.GetIPRecordID(IP: string): Cardinal;\n  function SearchIPRecordID(IPRecordFrom, IPRecordTo, IPValue: Cardinal)\n    : Cardinal;\n  var\n    CompareIPValue1, CompareIPValue2: Cardinal;\n  begin\n    Result := 0;\n    CompareIPValue1 := 0;\n    CompareIPValue2 := 0;\n    QQWryFileStream.Seek(FirstIPIndexOffset + ((IPRecordTo - IPRecordFrom) div 2\n      + IPRecordFrom - 1) * 7, soFromBeginning);\n    QQWryFileStream.Read(CompareIPValue1, 4);\n    QQWryFileStream.Seek(FirstIPIndexOffset + ((IPRecordTo - IPRecordFrom) div 2\n      + IPRecordFrom) * 7, soFromBeginning);\n    QQWryFileStream.Read(CompareIPValue2, 4);\n    \/\/ \u627e\u5230\u4e86\n    if (IPValue >= CompareIPValue1) and (IPValue &lt; CompareIPValue2) then\n    begin\n      Result := (IPRecordTo - IPRecordFrom) div 2 + IPRecordFrom;\n    end\n    else\n      \/\/ \u540e\u534a\u6bb5\u627e\n      if IPValue > CompareIPValue1 then\n      begin\n        Result := SearchIPRecordID((IPRecordTo - IPRecordFrom) div 2 +\n          IPRecordFrom + 1, IPRecordTo, IPValue);\n      end\n      else\n        \/\/ \u524d\u534a\u6bb5\u627e\n        if IPValue &lt; CompareIPValue1 then\n        begin\n          Result := SearchIPRecordID(IPRecordFrom, (IPRecordTo - IPRecordFrom)\n            div 2 + IPRecordFrom - 1, IPValue);\n        end;\n  end;\n\nbegin\n  Result := SearchIPRecordID(1, GetIPRecordNum, GetIPValue(IP));\nend;\n\nfunction TIPLocation.GetIPRecordNum: Cardinal;\nbegin\n  Result := IPRecordNum;\nend;\n\nfunction TIPLocation.GetIPValue(IP: string): Cardinal;\nvar\n  tsIP: TStringlist;\n  i: integer;\n  function SplitStringToStringlist(aString: string; aSplitChar: string)\n    : TStringlist;\n  begin\n    Result := TStringlist.Create;\n    while pos(aSplitChar, aString) > 0 do\n    begin\n      Result.Add(copy(aString, 1, pos(aSplitChar, aString) - 1));\n      aString := copy(aString, pos(aSplitChar, aString) + 1,\n        length(aString) - pos(aSplitChar, aString));\n    end;\n    Result.Add(aString);\n  end;\n\nbegin\n  tsIP := SplitStringToStringlist(IP, '.');\n  Result := 0;\n  for i := 3 downto 0 do\n  begin\n    Result := Result + StrToInt(tsIP&#91;i]) * trunc(power(256, 3 - i));\n  end;\nend;\n\nfunction TIPLocation.GetLocation(IP: string): String;\nbegin\n  FLock.Enter;\n  try\n    Result := GetIPMsg(GetIPRecordID(IP))&#91;2];\n  finally\n    FLock.Leave;\n  end;\nend;\n\nfunction TIPLocation.GetQQWryDataFrom: string;\nbegin\n  Result := GetIPMsg(GetIPRecordNum)&#91;2];\nend;\n\nfunction TIPLocation.GetQQWryDate: TDate;\nvar\n  DateString: string;\nbegin\n  DateString := GetIPMsg(GetIPRecordNum)&#91;3];\n  DateString := copy(DateString, 1, pos('IP\u6570\u636e', DateString) - 1);\n  DateString := StringReplace(DateString, '\u5e74', '-',\n    &#91;rfReplaceAll, rfIgnoreCase]);\n  DateString := StringReplace(DateString, '\u6708', '-',\n    &#91;rfReplaceAll, rfIgnoreCase]);\n  DateString := StringReplace(DateString, '\u65e5', '-',\n    &#91;rfReplaceAll, rfIgnoreCase]);\n  Result := StrToDate(DateString);\nend;\n\nfunction TIPLocation.GetQQWryFileName: string;\nbegin\n  Result := QQWryFileName;\nend;\n\nfunction TIPLocation.GetQQWryFileSize: Cardinal;\nbegin\n  Result := QQWryFileSize;\nend;\n\ninitialization\n\nfinalization\n\nif __IPLocation &lt;> nil then\n  __IPLocation.Free;\n\nend.<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u7eaf\u771fIP \u662f\u4e00\u4e2a\u5f88\u77e5\u540d\u7684IP\u5730\u5740\u6570\u636e\u5e93\uff0c [&hellip;]<\/p>\n","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[8,603,21],"tags":[],"class_list":["post-4451","post","type-post","status-publish","format-standard","hentry","category-delphi","category-603","category-misc"],"views":3487,"_links":{"self":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/4451","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4451"}],"version-history":[{"count":5,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/4451\/revisions"}],"predecessor-version":[{"id":5999,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/4451\/revisions\/5999"}],"wp:attachment":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4451"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4451"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4451"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}