script.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // script
  2. package util
  3. import (
  4. "encoding/json"
  5. "fmt"
  6. "log"
  7. qu "qfw/util"
  8. "regexp"
  9. "strings"
  10. ljson "github.com/yuin/gopher-json"
  11. "github.com/yuin/gopher-lua"
  12. )
  13. type LuaScript struct {
  14. Code, Name, Script string
  15. Doc map[string]interface{} //经过前置过滤的源信息
  16. Block []*Block //分块信息
  17. KvMap map[string][]map[string]interface{}
  18. Result map[string][]map[string]interface{} //抽取结果信息
  19. L *lua.LState
  20. }
  21. func (s *LuaScript) ClearRunScript() map[string]interface{} {
  22. data := map[string]interface{}{}
  23. qu.Try(func() {
  24. s.L = lua.NewState() //创建lua虚拟机
  25. s.L.PreloadModule("json", ljson.Loader)
  26. defer s.L.Close()
  27. if err := s.L.DoString(s.Script); err != nil {
  28. data["err"] = err.Error()
  29. } else {
  30. //doc:每条结果数据
  31. //KvMap:合并数据的list
  32. tab := MapToLuaTable(s.L, s.Doc)
  33. kvMap := MapToLuaTable2(s.L, s.KvMap)
  34. if err := s.L.CallByParam(lua.P{
  35. Fn: s.L.GetGlobal("main"),
  36. NRet: 1,
  37. Protect: true,
  38. }, lua.LString(s.Code), tab, kvMap); err != nil {
  39. data["err"] = err.Error()
  40. }
  41. ret := s.L.Get(-1)
  42. s.L.Pop(1)
  43. if tmp, ok := ret.(*lua.LTable); ok {
  44. data = LuaTableToMap(tmp)
  45. } else {
  46. data["rep"] = ret
  47. }
  48. }
  49. }, func(err interface{}) {
  50. log.Println("lua err:", data["err"])
  51. })
  52. return data
  53. }
  54. //stype per:前置,core:抽取,back:后置
  55. func (s *LuaScript) RunScript(stype string) map[string]interface{} {
  56. data := map[string]interface{}{}
  57. qu.Try(func() {
  58. s.L = lua.NewState()
  59. //s.L.DoFile("lua/comm.lua")
  60. s.L.PreloadModule("json", ljson.Loader)
  61. s.L.SetGlobal("findOneText", s.L.NewFunction(func(S *lua.LState) int {
  62. nodetype := S.ToString(-3)
  63. gpath := S.ToString(-2)
  64. content := S.ToString(-1)
  65. ret := FindOneText(gpath, content, nodetype)
  66. S.Push(ret)
  67. return 1
  68. }))
  69. s.L.SetGlobal("findOneHtml", s.L.NewFunction(func(S *lua.LState) int {
  70. nodetype := S.ToString(-3)
  71. gpath := S.ToString(-2)
  72. content := S.ToString(-1)
  73. ret := FindOneHtml(gpath, content, nodetype)
  74. S.Push(ret)
  75. return 1
  76. }))
  77. s.L.SetGlobal("findListText", s.L.NewFunction(func(S *lua.LState) int {
  78. gpath := S.ToString(-2)
  79. content := S.ToString(-1)
  80. ret := s.L.NewTable()
  81. FindListText(gpath, content, ret)
  82. S.Push(ret)
  83. return 1
  84. }))
  85. s.L.SetGlobal("findListHtml", s.L.NewFunction(func(S *lua.LState) int {
  86. gpath := S.ToString(-2)
  87. content := S.ToString(-1)
  88. ret := s.L.NewTable()
  89. FindListHtml(gpath, content, ret)
  90. S.Push(ret)
  91. return 1
  92. }))
  93. s.L.SetGlobal("findMap", s.L.NewFunction(func(S *lua.LState) int {
  94. qmap := S.ToTable(-2)
  95. content := S.ToString(-1)
  96. ret := s.L.NewTable()
  97. FindMap(qmap, content, ret)
  98. S.Push(ret)
  99. return 1
  100. }))
  101. //支持正则
  102. s.L.SetGlobal("regexp", s.L.NewFunction(func(S *lua.LState) int {
  103. index := int(S.ToNumber(-1))
  104. regstr := S.ToString(-2)
  105. text := S.ToString(-3)
  106. reg := regexp.MustCompile(regstr)
  107. reps := reg.FindAllStringSubmatchIndex(text, -1)
  108. ret := s.L.NewTable()
  109. number := 0
  110. for _, v := range reps {
  111. number++
  112. ret.Insert(number, lua.LString(text[v[index]:v[index+1]]))
  113. }
  114. S.Push(ret)
  115. return 1
  116. }))
  117. //支持替换
  118. s.L.SetGlobal("replace", s.L.NewFunction(func(S *lua.LState) int {
  119. text := S.ToString(-3)
  120. old := S.ToString(-2)
  121. repl := S.ToString(-1)
  122. text = strings.Replace(text, old, repl, -1)
  123. S.Push(lua.LString(text))
  124. return 1
  125. }))
  126. defer s.L.Close()
  127. if err := s.L.DoString(s.Script); err != nil {
  128. data["err"] = err.Error()
  129. } else {
  130. if stype == "pre" {
  131. tab := MapToLuaTable(s.L, s.Doc)
  132. if err := s.L.CallByParam(lua.P{
  133. Fn: s.L.GetGlobal("main"),
  134. NRet: 1,
  135. Protect: true,
  136. }, lua.LString(s.Code), tab); err != nil {
  137. data["err"] = err.Error()
  138. }
  139. } else if stype == "core" {
  140. tab := MapToLuaTable(s.L, s.Doc)
  141. block, _ := json.Marshal(s.Block)
  142. kvMap := MapToLuaTable2(s.L, s.KvMap)
  143. if err := s.L.CallByParam(lua.P{
  144. Fn: s.L.GetGlobal("main"),
  145. NRet: 1,
  146. Protect: true,
  147. }, lua.LString(s.Code), tab, lua.LString(block), kvMap); err != nil {
  148. data["err"] = err.Error()
  149. log.Println(err.Error())
  150. }
  151. } else if stype == "back" {
  152. result := MapToLuaTable2(s.L, s.Result)
  153. if err := s.L.CallByParam(lua.P{
  154. Fn: s.L.GetGlobal("main"),
  155. NRet: 1,
  156. Protect: true,
  157. }, lua.LString(s.Code), result); err != nil {
  158. data["err"] = err.Error()
  159. }
  160. }
  161. ret := s.L.Get(-1)
  162. s.L.Pop(1)
  163. if tmp, ok := ret.(*lua.LTable); ok {
  164. data = LuaTableToMap(tmp)
  165. } else {
  166. data["rep"] = ret
  167. }
  168. }
  169. }, func(err interface{}) {
  170. log.Println("lua err:", err)
  171. })
  172. return data
  173. }
  174. func Logic(str string, doc map[string]interface{}) bool {
  175. b := false
  176. var errs error
  177. qu.Try(func() {
  178. L := lua.NewState()
  179. L.PreloadModule("json", ljson.Loader)
  180. defer L.Close()
  181. if err := L.DoString(str); err != nil {
  182. errs = err
  183. } else {
  184. tab := MapToLuaTable(L, doc)
  185. if err := L.CallByParam(lua.P{
  186. Fn: L.GetGlobal("logic"),
  187. NRet: 1,
  188. Protect: true,
  189. }, tab); err != nil {
  190. errs = err
  191. }
  192. ret := L.Get(-1)
  193. L.Pop(1)
  194. if ret.String() == "true" {
  195. b = true
  196. }
  197. }
  198. }, func(err interface{}) {
  199. log.Println("lua err:", errs)
  200. })
  201. return b
  202. }
  203. func MapToLuaTable(l *lua.LState, obj map[string]interface{}) *lua.LTable {
  204. tab := l.NewTable()
  205. for k, v := range obj {
  206. if val, ok := v.(string); ok {
  207. tab.RawSet(lua.LString(k), lua.LString(val))
  208. } else if val, ok := v.(int64); ok {
  209. tab.RawSet(lua.LString(k), lua.LNumber(val))
  210. } else if val, ok := v.(int32); ok {
  211. tab.RawSet(lua.LString(k), lua.LNumber(val))
  212. } else if val, ok := v.(int); ok {
  213. tab.RawSet(lua.LString(k), lua.LNumber(val))
  214. } else if val, ok := v.(float64); ok {
  215. tab.RawSet(lua.LString(k), lua.LNumber(val))
  216. } else if val, ok := v.(float32); ok {
  217. tab.RawSet(lua.LString(k), lua.LNumber(val))
  218. } else if val, ok := v.(bool); ok {
  219. tab.RawSet(lua.LString(k), lua.LBool(val))
  220. } else if val ,ok := v.(map[string]bool);ok{//把map的value值为true的存储为数组
  221. tb := l.NewTable()
  222. var i int
  223. for k2,_ := range val{
  224. tb.Insert(i, lua.LString(k2))
  225. i+=1
  226. }
  227. tab.RawSet(lua.LString(k), tb)
  228. } else if val, ok := v.(map[string]interface{}); ok {
  229. tab.RawSet(lua.LString(k), MapToLuaTable(l, val))
  230. } else if val, ok := v.([]string); ok {
  231. tb := l.NewTable()
  232. for k, vv := range val {
  233. tb.Insert(k, lua.LString(vv))
  234. }
  235. tab.RawSet(lua.LString(k), tb)
  236. } else if val, ok := v.([]map[string]interface{}); ok {
  237. tab2 := l.NewTable()
  238. for i, v := range val {
  239. tab2.Insert(i, MapToLuaTable(l, v))
  240. }
  241. tab.RawSet(lua.LString(k), tab2)
  242. } else if val, ok := v.([]interface{}); ok {
  243. bs, _ := json.Marshal(val)
  244. tab.RawSet(lua.LString(k), lua.LString(string(bs)))
  245. }
  246. }
  247. return tab
  248. }
  249. func MapToLuaTable2(l *lua.LState, obj map[string][]map[string]interface{}) *lua.LTable {
  250. tab := l.NewTable()
  251. for k, ms := range obj {
  252. tab2 := l.NewTable()
  253. for i, v := range ms {
  254. tab2.Insert(i+1 /*加1防止顺序错乱*/, MapToLuaTable(l, v))
  255. }
  256. tab.RawSet(lua.LString(k), tab2)
  257. }
  258. return tab
  259. }
  260. func LuaTableToMap(param *lua.LTable) map[string]interface{} {
  261. tmp := map[string]interface{}{}
  262. param.ForEach(func(key, val lua.LValue) {
  263. kk := fmt.Sprint(key)
  264. if v, ok := val.(lua.LString); ok {
  265. tmp[kk] = string(v)
  266. } else if v, ok := val.(*lua.LTable); ok {
  267. if kk == "blocktag"{//分块
  268. t := map[string]bool{}
  269. v.ForEach(func(value lua.LValue, value2 lua.LValue) {
  270. t[value2.String()]=true
  271. })
  272. tmp[kk] = t
  273. return
  274. }
  275. t := []map[string]interface{}{}
  276. v.ForEach(func(k, inv lua.LValue) {
  277. if vv, ok := inv.(*lua.LTable); ok {
  278. t = append(t, LuaTableToMap(vv))
  279. }
  280. })
  281. tmp[kk] = t
  282. } else if v, ok := val.(*lua.LBool); ok {
  283. if v.String() == "true" {
  284. tmp[kk] = true
  285. } else {
  286. tmp[kk] = false
  287. }
  288. } else if kk == "comeintime" || kk == "publishtime" {
  289. tmp[kk] = qu.Int64All(val.String())
  290. } else if v, ok := val.(*lua.LNumber); ok {
  291. tmp[kk] = qu.Float64All(v.String())
  292. } else if v, ok := val.(lua.LNumber); ok {
  293. tmp[kk] = qu.Float64All(v.String())
  294. } else {
  295. tmp[kk] = val
  296. }
  297. })
  298. return tmp
  299. }