逻辑

文件路径

同目录下“.jianou”文件,多个文件会提示,默认使用第一个(后续考虑改为修改时间最新的)。

配置文件设计

为了便于前台操作(复选框),改为MarkDown语法的编辑页。

显示

image.png

运行结果

image.png

数据合法有效时

image.png
image.png

!数据合法有效时

image.png
image.png
主要不同点在于,如果字符串类型的Key没有对应个数的Value,会将Value全部设为空字符串。

代码

🐍Python🐍

  1. # encoding = utf-8
  2. import os
  3. import pathlib
  4. import re
  5. from addict import Dict
  6. msgStart = r"——————————Python脚本:Start——————————"
  7. strN = '\n'
  8. strMarkCheck = '- ['
  9. title2 = '\n## '
  10. title3 = '### '
  11. strAnchorEnd = "\"></a>"
  12. strBR = r"<br />"
  13. strNull = ""
  14. msgEnd = r"——————————Python脚本:End——————————"
  15. # 读取配置文件字符串
  16. def ReadMarkDownText():
  17. pathSelf = os.getcwd()
  18. print("当前工作目录:", pathSelf)
  19. listFile = list(pathlib.Path(pathSelf).glob('*.jianou'))
  20. nJianou = len(listFile)
  21. if nJianou == 0:
  22. print("无配置文件“*.jianou”")
  23. else:
  24. pathConf = listFile[0]
  25. if nJianou == 1:
  26. print("使用配置文件:", pathConf)
  27. else:
  28. print("有多个文件:", listFile)
  29. print("默认使用第一个:", pathConf)
  30. with open(pathConf, 'r+', encoding='utf-8') as f:
  31. textMarkDown = f.read()
  32. return textMarkDown
  33. def ExtractConf(textMarkDown):
  34. listLevel2 = textMarkDown.split(title2)
  35. # print("2级标题列表:", listLevel2)
  36. listValueAll = []
  37. for strLevel2 in listLevel2:
  38. # print("2级标题字符串:", strLevel2)
  39. if title3 in strLevel2:
  40. strTypeLevel2 = strLevel2.split(strN)[0]
  41. # print("2级标题类型:", strTypeLevel2)
  42. listValue2Filtered = []
  43. listValue2 = re.split(r"\n|<br />", strLevel2)
  44. # print("2级标题的值:", listValue2)
  45. for iValue in listValue2:
  46. if strAnchorEnd in iValue:
  47. pass
  48. elif iValue == strNull:
  49. # 输入输出目录可能为空
  50. pass
  51. elif "//" in iValue:
  52. # 备注
  53. pass
  54. else:
  55. if strBR in iValue:
  56. iValue = iValue.strip(strBR)
  57. listValue2Filtered.append(iValue)
  58. # print("过滤后的Level2:", listValue2Filtered)
  59. listValueAll.append(listValue2Filtered)
  60. # print("3级标题列表:", listValueAll)
  61. listKey = []
  62. listValue = []
  63. dictConfAll = { }
  64. for iLevel2 in listValueAll:
  65. # print(iLevel2)
  66. strTypeLevel2 = iLevel2[0]
  67. listValueLevel2 = iLevel2[1:]
  68. listConfKey = []
  69. listConfValue = []
  70. for iValueLevel2 in listValueLevel2:
  71. if title3 in iValueLevel2:
  72. strLevel3 = iValueLevel2.split(title3)[1:][0].strip()
  73. # print(strLevel3)
  74. listConfKey.append(strLevel3)
  75. elif strMarkCheck in iValueLevel2:
  76. if '[x]' in iValueLevel2:
  77. listConfValue.append(True)
  78. elif '[ ]' in iValueLevel2:
  79. listConfValue.append(False)
  80. elif iValueLevel2 == strNull:
  81. # 如:文件夹
  82. listConfValue.append(iValueLevel2)
  83. else:
  84. if CaseStrIn(iValueLevel2, "True"):
  85. listConfValue.append(True)
  86. elif CaseStrIn(iValueLevel2, "False"):
  87. listConfValue.append(False)
  88. else:
  89. # 如:文件夹
  90. listConfValue.append(iValueLevel2)
  91. # print(listConfKey)
  92. # print(listConfValue)
  93. listKey.append(listConfKey)
  94. listValue.append(listConfValue)
  95. if len(listConfKey) != len(listConfValue):
  96. print("字典的Key列表和Value列表个数不一致:")
  97. print(listConfKey)
  98. listConfValue = []
  99. for i in range(len(listConfKey)):
  100. listConfValue.append(strNull)
  101. print("Value列表值被置为空字符串")
  102. zipConf = zip(listConfKey, listConfValue)
  103. # print(listConf)
  104. dictConf = dict(zipConf)
  105. # print(dictConf)
  106. dictConfAll.update(dictConf)
  107. # print(dictConfAll)
  108. return dictConfAll
  109. def CaseStrIn(str2CMP, strBeCMP):
  110. if strBeCMP.lower() in str2CMP.lower():
  111. bCMP = True
  112. else:
  113. bCMP = False
  114. return bCMP
  115. def DictObj():
  116. textConf = ReadMarkDownText()
  117. dictConf = ExtractConf(textConf)
  118. objCof = Dict(dictConf)
  119. # print(objCof)
  120. return objCof
  121. if __name__ == '__main__':
  122. print(msgStart)
  123. objCof = DictObj()
  124. print(msgEnd)

📝MarkDown📝

有一些锚点,懒得删了,在代码里过滤了

  1. # 配置文件
  2. **命名**:*.jianou<br />**格式**:以MarkDown文本格式<br />**路径**:exe同目录<br />**选项**:复选框以及大小写不敏感的TrueFalse
  3. <a name="CP9TX"></a>
  4. ## 显示:窗口消息
  5. <a name="xAWsM"></a>
  6. ### 单个组织
  7. - [ ] <br />
  8. <a name="ASPlp"></a>
  9. ### 全部组织
  10. - [ ] <br />
  11. <a name="MeEtg"></a>
  12. ## 异常提醒
  13. <a name="Dm1HK"></a>
  14. ### Table数据异常
  15. - [x] <br />
  16. <a name="Nn8vz"></a>
  17. ### Code非常见类型
  18. - [x] <br />
  19. <a name="V2qh5"></a>
  20. ### Code有异常符号
  21. - [x] <br />
  22. <a name="iFsK0"></a>
  23. ## 导出文件
  24. <a name="b3NRZ"></a>
  25. ### IoCs表格
  26. - [ ] <br />
  27. <a name="qBbRD"></a>
  28. ### 完成后打开IoCs表格
  29. - [ ] <br />
  30. <a name="fLncF"></a>
  31. ### 规则和代码
  32. - [x] <br />
  33. <a name="wCdf9"></a>
  34. ### 原文链接
  35. - [x] <br />
  36. <a name="WRv52"></a>
  37. ### 所有组织的IoCs数量统计
  38. - [x] <br />
  39. <a name="pM7jE"></a>
  40. ### 所有需要提取IoCs的MarkDown文件路径
  41. 支持大写的Bool值:TRUE
  42. <a name="xQn4E"></a>
  43. ### 代码有异常符号
  44. - [x] 支持复选框
  45. <a name="igKf7"></a>
  46. ### 不符合IoCs标题的文件
  47. 也支持小写的Bool值:false
  48. <a name="Ks1xA"></a>
  49. ## 文件夹
  50. <a name="fYnvY"></a>
  51. ### 输入
  52. C:\Users\Administrator\Desktop
  53. <a name="wzTIn"></a>
  54. ### 输出
  55. C:\Users\Administrator\Desktop\APT情报输出<br />// 缺省:exe同目录

参考

虽然没有采用,但是下次比较急的时候我应该会直接用现成的库和其对应的配置文件格式。这次自己构建自己的方式也是当练练Python语法。

python读取配置文件&&简单封装