Re: AHK: Разбор ответа VK API или JSON
То есть, без пропусков нельзя всё получить за раз, с учётом структуры комментариев и под-комментариев? Какими парсерами разбирают такие случаи?
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
То есть, без пропусков нельзя всё получить за раз, с учётом структуры комментариев и под-комментариев? Какими парсерами разбирают такие случаи?
Не уверен, что правильно понимаю, но кажется, ограничение, с которым Вы сталкиваетесь, либо в данных полученного ответа, либо понимания своей цели. Уточните пожалуйста, что конкретно должно пониматься под "всё", если сформулированное решение и так получает всё?
Напомню, что я никогда не имел дело с VK API и не представляю какова иерархия интересов в таких запросах.
Рискну предположить, что речь о паре "edges", находящихся в двух последних элементах, которые не пусты.
sKeys := ["id","text","created_at","owner","profile_pic_url","username","viewer_has_liked","edge_liked_by","edge_threaded_comments","edges"]
edges := JSON.Parse(ResponseText).data.shortcode_media.edge_media_to_parent_comment.edges
MsgBox % Clipboard := ListEdges(edges, sKeys)
ListEdges(edges, srchKeys, inner := false) {
list := ""
For k, v in edges {
list .= Format("{}| ========>&<======= [ {}edge #{} ] ========>&<======= |`n", inner ? "`t" : "", inner ? "Inner " : "", A_Index)
For index, item in srchKeys {
val := SearchKey(v.node, item)
innerEdges := item == "edges" ? val.Length() ? val : "" : ""
list .= Format("{}{}. - {} = {}`n", inner ? "`t`t" : "`t", A_Index, item, IsObject(val) ? JSON.Stringify(val) : val )
} if (innerEdges) {
list .= ListEdges(innerEdges, srchKeys, true)
}
list .= "`n"
} Return list
}
SearchKey(obj, key) {
for k, v in obj {
if (k = key)
Return v
if IsObject(v) {
res := SearchKey(v, key)
if (res != "")
Return res
}
}
}
Весь текст "MsgBox" не вмещает, поэтому он копируется в буфер, откуда его можно вставить в редактор и изучить.
Вот так спасибо! Да, под "всё" имелись в виду те оставшиеся значения по ключам, которые пропускались в предыдущих вариантах разбора этого JSON с Интсаграмма.
что конкретно должно пониматься под "всё", если сформулированное решение и так получает всё?
Заметил, что в этой JSON-выдаче, вложенный комментарий дублируется вместо предыдущего (в коде убрал лишние ключи для наглядности):
ResponseText =
(
{"data":{"shortcode_media":{"edge_media_to_parent_comment":{"count":112,"page_info":{"has_next_page":true,"end_cursor":"{\"bifilter_token\": \"KAkBAgAQAP__AAAA\"}"},"edges":[{"node":{"text":"Коммент1","owner":{"id":"3432418287"},"edge_liked_by":{"count":1},"edge_threaded_comments":{"count":6,"page_info":{"has_next_page":true,"end_cursor":"QVFCbGxYVThuMnJ5VVZSMktoc2Z1QlM4elVkYnZRMmQxQW1Ba2psZ1FSNFUwekdFc1RVMzlBLWIwUHN1QXpvNVRaYS1XY3JxNWRTdlpnYnpNc0c3a1J4bg=="},"edges":[{"node":{"text":"Коммент2","owner":{"id":"2221367895"},"edge_liked_by":{"count":0}}},{"node":{"text":"Коммент3","owner":{"id":"1514648096"},"edge_liked_by":{"count":1}}},{"node":{"text":"Коммент4","owner":{"id":"5527469791"},"edge_liked_by":{"count":0}}}]}}},{"node":{"text":"Коммент5","owner":{"id":"8620373103"},"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"text":"Коммент6","owner":{"id":"8620373103"},"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"text":"Коммент7","owner":{"id":"8620373103"},"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"text":"Коммент8","owner":{"id":"6226683833"},"edge_liked_by":{"count":2},"edge_threaded_comments":{"count":16,"page_info":{"has_next_page":true,"end_cursor":"QVFBS2tjN19Od3k5WmZTYXUxSE9qUmhzdHBzWTdULW1TRmFLb3A0amNWakx4aFh5dTZkY1MzZGFkak1VaWZ6U1lLTXNVU1VSQUx1bWRMNGExTUNUdWN1TQ=="},"edges":[{"node":{"text":"Коммент9","owner":{"id":"6226683833"},"edge_liked_by":{"count":1}}},{"node":{"text":"Коммент10","owner":{"id":"5480555413"},"edge_liked_by":{"count":1}}},{"node":{"text":"Коммент11","owner":{"id":"6226683833"},"edge_liked_by":{"count":0}}}]}}}]}}},"status":"ok"}
)
sKeys := ["text","created_at","end_cursor","edges"]
edges := JSON.Parse(ResponseText).data.shortcode_media.edge_media_to_parent_comment.edges
MsgBox % Clipboard := ListEdges(edges, sKeys)
ListEdges(edges, srchKeys, inner := false) {
list := ""
For k, v in edges {
list .= Format("{}| ========>&<======= [ {}edge #{} ] ========>&<======= |`n", inner ? "`t" : "", inner ? "Inner " : "", A_Index)
For index, item in srchKeys {
val := SearchKey(v.node, item)
innerEdges := item == "edges" ? val.Length() ? val : "" : ""
list .= Format("{}{}. - {} = {}`n", inner ? "`t`t" : "`t", A_Index, item, IsObject(val) ? JSON.Stringify(val) : val )
} if (innerEdges) {
list .= ListEdges(innerEdges, srchKeys, true)
}
list .= "`n"
} Return list
}
SearchKey(obj, key) {
for k, v in obj {
if (k = key)
Return v
if IsObject(v) {
res := SearchKey(v, key)
if (res != "")
Return res
}
}
}
class JSON
{
static JS := JSON._GetJScripObject()
Parse(JsonString) {
try oJSON := this.JS.("(" JsonString ")")
catch {
MsgBox, Wrong JsonString!
Return
}
Return this._CreateObject(oJSON)
}
_GetJScripObject() {
VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
FileAppend,
(
<component>
<public><method name='eval'/></public>
<script language='JScript'></script>
</component>
), % tmpFile
JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
FileDelete, % tmpFile
JSON._AddMethods(JS)
Return JS
}
_AddMethods(ByRef JS) {
JScript =
(
Object.prototype.GetKeys = function () {
var keys = []
for (var k in this)
if (this.hasOwnProperty(k))
keys.push(k)
return keys
}
Object.prototype.IsArray = function () {
var toStandardString = {}.toString
return toStandardString.call(this) == '[object Array]'
}
)
JS.("delete ActiveXObject; delete GetObject;")
JS.(JScript)
}
_CreateObject(ObjJS) {
res := ObjJS.IsArray()
if (res = "")
Return ObjJS
else if (res = -1) {
obj := []
Loop % ObjJS.length
obj[A_Index] := this._CreateObject(ObjJS[A_Index - 1])
}
else if (res = 0) {
obj := {}
keys := ObjJS.GetKeys()
Loop % keys.length
k := keys[A_Index - 1], obj[k] := this._CreateObject(ObjJS[k])
}
Return obj
}
}
Есть ли возможность для этих JSON получать все блоки (со входящими в каждый из них комментариями и тп) — без дублей, пропусков и структуры?
Заметил, что в этой JSON-выдаче, вложенный комментарий дублируется вместо предыдущего
Не совсем так. Дело в том, что итератор перебирает объект в алфавитном порядке и поскольку SearchKey() возвращает первое найденное совпадение, то находит его первым делом во вложенном "edges". Нужно только немного модифицировать SearchKey(), чтобы вначале исследовались поля текущего инстанса и, если нет найденных ключей, то искать во вложенных, если таковые имеются:
SearchKey(obj, key, outerFields := true) {
temp := []
for k, v in obj {
if (k = key)
Return v
if (outerFields && IsObject(v))
temp.Push(v)
else if IsObject(v) {
res := SearchKey(v, key)
if (res != "")
Return res
}
}
for index, item in temp
if ((res := SearchKey(item, key)) != "")
Return res
}
Здесь "outerFields" - отвечает за эту вариативность, по умолчанию устанавливая на такой алгоритм.
Для пущей корректности, последней строкой в теле этой функции стоило бы добавить возвращаемый результат в случае, если поиск оказался неудачным и ничего не было найдено(например Return "Неудачно"), но если Вы уверены, что искомые ключи там обязаны быть, то в этом действительно нет необходимости.
KusochekDobra, опять же заметил, что, хоть последовательность в содержимом комментариев соблюдается, но другие ключи внутри блока продолжают дублироваться и переноситься с вложенного блока на внешний. В примере это видно в 3 и 4 блоках, у которых "username" в результатах один и тот же, хотя в строке они разные, прошу взглянуть —
ResponseText =
(
{"data":{"shortcode_media":{"edge_media_to_parent_comment":{"count":224,"page_info":{"has_next_page":true,"end_cursor":"{\"cached_comments_cursor\": \"17988603055194856\", \"bifilter_token\": \"KC0BDABAABgAEAAQAAgACAB799_Lz77P7011eOpvf_W__wAUAAAAABAEQ0EgwBAA\"}"},"edges":[{"node":{"id":"18033126139045251","text":"cmt1","created_at":1549564430,"did_report_as_spam":false,"owner":{"id":"7147681468","is_verified":false,"profile_pic_url":"pic1","username":"uname1"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18035179396030512","text":"cmt2","created_at":1549564345,"did_report_as_spam":false,"owner":{"id":"9037884033","is_verified":false,"profile_pic_url":"pic2","username":"uname2"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17864531659321218","text":"cmt3","created_at":1549563973,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic3","username":"uname3"},"viewer_has_liked":false,"edge_liked_by":{"count":1},"edge_threaded_comments":{"count":3,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[{"node":{"id":"18031519045002885","text":"cmt4","created_at":1549565442,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic4","username":"uname4"},"viewer_has_liked":false,"edge_liked_by":{"count":3}}},{"node":{"id":"18014501047114258","text":"cmt5","created_at":1549622948,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic5","username":"uname5"},"viewer_has_liked":false,"edge_liked_by":{"count":0}}},{"node":{"id":"18012364975121513","text":"cmt6","created_at":1549624991,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic6","username":"uname6"},"viewer_has_liked":false,"edge_liked_by":{"count":1}}}]}}},{"node":{"id":"18014605018119580","text":"cmt7","created_at":1549563882,"did_report_as_spam":false,"owner":{"id":"1575737610","is_verified":false,"profile_pic_url":"pic7","username":"uname7"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18006807262092548","text":"cmt8","created_at":1549563710,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic8","username":"uname8"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014414656112658","text":"cmt9","created_at":1549563555,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic9","username":"uname9"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17899732756291214","text":"cmt10","created_at":1549563119,"did_report_as_spam":false,"owner":{"id":"2330649029","is_verified":false,"profile_pic_url":"pic10","username":"uname10"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18030447571010198","text":"cmt11","created_at":1549562991,"did_report_as_spam":false,"owner":{"id":"5763461995","is_verified":false,"profile_pic_url":"pic11","username":"uname11"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18016886404100187","text":"cmt12","created_at":1549562982,"did_report_as_spam":false,"owner":{"id":"321345545","is_verified":false,"profile_pic_url":"pic12","username":"uname12"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17992787185168932","text":"cmt13","created_at":1549562672,"did_report_as_spam":false,"owner":{"id":"3267878847","is_verified":false,"profile_pic_url":"pic13","username":"uname13"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014099035112644","text":"cmt14","created_at":1549562649,"did_report_as_spam":false,"owner":{"id":"7495332966","is_verified":false,"profile_pic_url":"pic14","username":"uname14"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17851892326346682","text":"cmt15","created_at":1549562460,"did_report_as_spam":false,"owner":{"id":"8692656309","is_verified":false,"profile_pic_url":"pic15","username":"uname15"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}}]}}},"status":"ok"}
)
sKeys := ["text","username","profile_pic_url","end_cursor","edges"]
edges := JSON.Parse(ResponseText).data.shortcode_media.edge_media_to_parent_comment.edges
MsgBox % Clipboard := ListEdges(edges, sKeys)
ListEdges(edges, srchKeys, inner := false) {
list := ""
For k, v in edges {
list .= Format("{}| ========>&<======= [ {}edge #{} ] ========>&<======= |`n", inner ? "`t" : "", inner ? "Inner " : "", A_Index)
For index, item in srchKeys {
val := SearchKey(v.node, item)
innerEdges := item == "edges" ? val.Length() ? val : "" : ""
list .= Format("{}{}. - {} = {}`n", inner ? "`t`t" : "`t", A_Index, item, IsObject(val) ? JSON.Stringify(val) : val )
} if (innerEdges) {
list .= ListEdges(innerEdges, srchKeys, true)
}
list .= "`n"
} Return list
}
SearchKey(obj, key, outerFields := true) {
temp := []
for k, v in obj {
if (k = key)
Return v
if (outerFields && IsObject(v))
temp.Push(v)
else if IsObject(v) {
res := SearchKey(v, key)
if (res != "")
Return res
}
}
for index, item in temp
if ((res := SearchKey(item, key)) != "")
Return res
}
class JSON
{
static JS := JSON._GetJScripObject()
Parse(JsonString) {
try oJSON := this.JS.("(" JsonString ")")
catch {
MsgBox, Wrong JsonString!
Return
}
Return this._CreateObject(oJSON)
}
_GetJScripObject() {
VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
FileAppend,
(
<component>
<public><method name='eval'/></public>
<script language='JScript'></script>
</component>
), % tmpFile
JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
FileDelete, % tmpFile
JSON._AddMethods(JS)
Return JS
}
_AddMethods(ByRef JS) {
JScript =
(
Object.prototype.GetKeys = function () {
var keys = []
for (var k in this)
if (this.hasOwnProperty(k))
keys.push(k)
return keys
}
Object.prototype.IsArray = function () {
var toStandardString = {}.toString
return toStandardString.call(this) == '[object Array]'
}
)
JS.("delete ActiveXObject; delete GetObject;")
JS.(JScript)
}
_CreateObject(ObjJS) {
res := ObjJS.IsArray()
if (res = "")
Return ObjJS
else if (res = -1) {
obj := []
Loop % ObjJS.length
obj[A_Index] := this._CreateObject(ObjJS[A_Index - 1])
}
else if (res = 0) {
obj := {}
keys := ObjJS.GetKeys()
Loop % keys.length
k := keys[A_Index - 1], obj[k] := this._CreateObject(ObjJS[k])
}
Return obj
}
}
В этом случае, будет проще описать относительные пути к каждому из полей, и проходя по элементам массива, запрашивать их значения напрямую по списку, а так же проверять Length() вложенных edges, на предмет наличия элементов, у которых аналогичная структура, за исключением возможности иметь вложенные edges. Это исключит ошибки наверняка.
Имелось в виду, что данные из одного блока переносятся в другой. Нельзя ли убрать структурирование — представляя подряд все блоки в сплошном виде — но чтобы данные из блоков соответствовали строке?
Обратите внимание, что если элементы edges содержат вложенные edges, то это неизбежно ведёт к дублированию имён. Список запрашиваемых имён описан линейно, а их фактическое расположение имеет разный уровень вложенности. В этом случае, нужно либо сопровождать каждое имя соответствующим ему уровнем вложенности и описывать взаимодействие с этой механикой в алгоритме функции, либо, просто описать их относительные пути и обращаться к ним на каждой итерации, как описано выше. Даже если просто перечислить всё в сплошном виде, но чтобы данные соответствовали структуре, то это всё равно подразумевает описание сигнатуры для каждого искомого элемента. К тому же, раз Вы запрашиваете объект с одной и той же структурой, это не потребует от Вас много усилий.
Прошу прощения, надо было сразу обратить внимание на это, а так я только время у Вас отнял.
А какой-то простой правкой json-строки этого можно добиться, или если получать не "edges", а "node", которые охватывают все блоки?
Регулярками. Но тогда будет неочевидно, какие из них были вложены.
В смысле: что на что править? Я как ни экспериментировал — не вытанцовывается.
Так же прибавка после «.edges» — «.node», — все node не выводит:
edges := JSON.Parse(ResponseText).data.shortcode_media.edge_media_to_parent_comment.edges
ResponseText = {"data":{"shortcode_media":{"edge_media_to_parent_comment":{"count":224,"page_info":{"has_next_page":true,"end_cursor":"{\"cached_comments_cursor\": \"17988603055194856\", \"bifilter_token\": \"KC0BDABAABgAEAAQAAgACAB799_Lz77P7011eOpvf_W__wAUAAAAABAEQ0EgwBAA\"}"},"edges":[{"node":{"id":"18033126139045251","text":"cmt1","created_at":1549564430,"did_report_as_spam":false,"owner":{"id":"7147681468","is_verified":false,"profile_pic_url":"pic1","username":"uname1"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18035179396030512","text":"cmt2","created_at":1549564345,"did_report_as_spam":false,"owner":{"id":"9037884033","is_verified":false,"profile_pic_url":"pic2","username":"uname2"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17864531659321218","text":"cmt3","created_at":1549563973,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic3","username":"uname3"},"viewer_has_liked":false,"edge_liked_by":{"count":1},"edge_threaded_comments":{"count":3,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[{"node":{"id":"18031519045002885","text":"cmt4","created_at":1549565442,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic4","username":"uname4"},"viewer_has_liked":false,"edge_liked_by":{"count":3}}},{"node":{"id":"18014501047114258","text":"cmt5","created_at":1549622948,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic5","username":"uname5"},"viewer_has_liked":false,"edge_liked_by":{"count":0}}},{"node":{"id":"18012364975121513","text":"cmt6","created_at":1549624991,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic6","username":"uname6"},"viewer_has_liked":false,"edge_liked_by":{"count":1}}}]}}},{"node":{"id":"18014605018119580","text":"cmt7","created_at":1549563882,"did_report_as_spam":false,"owner":{"id":"1575737610","is_verified":false,"profile_pic_url":"pic7","username":"uname7"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18006807262092548","text":"cmt8","created_at":1549563710,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic8","username":"uname8"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014414656112658","text":"cmt9","created_at":1549563555,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic9","username":"uname9"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17899732756291214","text":"cmt10","created_at":1549563119,"did_report_as_spam":false,"owner":{"id":"2330649029","is_verified":false,"profile_pic_url":"pic10","username":"uname10"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18030447571010198","text":"cmt11","created_at":1549562991,"did_report_as_spam":false,"owner":{"id":"5763461995","is_verified":false,"profile_pic_url":"pic11","username":"uname11"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18016886404100187","text":"cmt12","created_at":1549562982,"did_report_as_spam":false,"owner":{"id":"321345545","is_verified":false,"profile_pic_url":"pic12","username":"uname12"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17992787185168932","text":"cmt13","created_at":1549562672,"did_report_as_spam":false,"owner":{"id":"3267878847","is_verified":false,"profile_pic_url":"pic13","username":"uname13"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014099035112644","text":"cmt14","created_at":1549562649,"did_report_as_spam":false,"owner":{"id":"7495332966","is_verified":false,"profile_pic_url":"pic14","username":"uname14"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17851892326346682","text":"cmt15","created_at":1549562460,"did_report_as_spam":false,"owner":{"id":"8692656309","is_verified":false,"profile_pic_url":"pic15","username":"uname15"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}}]}}},"status":"ok"}
sKeys := { "text": []
, "username": ["owner"]
, "profile_pic_url": ["owner"]
, "end_cursor": ["edge_threaded_comments", "page_info"]
, "edges": ["edge_threaded_comments"]}
edges := JSON.Parse(ResponseText).data.shortcode_media.edge_media_to_parent_comment.edges
MsgBox % ListValues(edges, sKeys)
ExitApp
ListValues(edges, srchKeys, inner := false) {
list := ""
For k, v in edges {
tmpArray := []
list .= Format("{}| ====>&<==== [ {}edge #{} ] ====>&<==== |`n", inner ? "`t" : "", inner ? "Inner " : "", A_Index)
For name, path in srchKeys {
tmp := v.node
For index, item in path {
tmp := tmp[ item ]
}
if (IsObject(val := tmp[ name ])) {
tmpArray := val
}
list .= Format("{}{}. - {} = {}`n", inner ? "`t`t" : "`t", A_Index, name, IsObject(val) ? "[]" : val ? val : "No value" )
} (tmpArray.Length() && (list .= ListValues(tmpArray, srchKeys, true)))
} Return list
}
Сгодится?
Спасибо! Возник по ходу вопрос: можно ли без правки строки получать значения "edge_liked_by" и "edge_threaded_comments"? И как разбить содержимое sKeys по переменным, — чтобы, к примеру, в переменной с названием "created_at" — было время и т.д.? Это нужно, чтобы разом оборачивать все переменные из блоков, в тэги.
Непонятно.
без правки строки получать значения "edge_liked_by" и "edge_threaded_comments"
Какой строки?
разбить содержимое sKeys по переменным, — чтобы, к примеру, в переменной с названием "created_at" — было время и т.д.
Нужен пример. В примере выше этого поля нет.
чтобы сразу оборачивать содержимое sKeys в комментарий из тэгов.
В общем-то, тоже, пример для наглядности.
Если что, завтра отвечу. Глаза слипаются.
Под строкой, имелась в виду json-строка. Хотелось бы без правки также получать из неё значения "edge_liked_by" и "edge_threaded_comments", которые в обычном виде следуют после "count", да ещё без кавычек:
"edge_liked_by|edge_threaded_comments":{"count":1}
"created_at" упомянул как пример одного из ключей, название которого после отработки json будет соответствовать значению ключа, так чтобы можно было по следующему типу легко сформировать отдельный комментарий, где вместо переменных с названиями "match" — переменные с названиями из нашей json-строки:
cmt .= "<div class=""comment"">`n<img class=""img"" src=""" matchh3 """>`n<div class=""info""><a href=""" matchh4 """>" matchh2 "</a> – <a href=""watch?v=" videoId "&lc=" matchh1 """>" matchh7 "</a><span class=""vote"">" matchh6 "</span></div>`n<div class=""content"">" matchh5 "</div>`n</div>`n"
Код полностью:
ResponseText = {"data":{"shortcode_media":{"edge_media_to_parent_comment":{"count":224,"page_info":{"has_next_page":true,"end_cursor":"{\"cached_comments_cursor\": \"17988603055194856\", \"bifilter_token\": \"KC0BDABAABgAEAAQAAgACAB799_Lz77P7011eOpvf_W__wAUAAAAABAEQ0EgwBAA\"}"},"edges":[{"node":{"id":"18033126139045251","text":"cmt1","created_at":1549564430,"did_report_as_spam":false,"owner":{"id":"7147681468","is_verified":false,"profile_pic_url":"pic1","username":"uname1"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18035179396030512","text":"cmt2","created_at":1549564345,"did_report_as_spam":false,"owner":{"id":"9037884033","is_verified":false,"profile_pic_url":"pic2","username":"uname2"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17864531659321218","text":"cmt3","created_at":1549563973,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic3","username":"uname3"},"viewer_has_liked":false,"edge_liked_by":{"count":1},"edge_threaded_comments":{"count":3,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[{"node":{"id":"18031519045002885","text":"cmt4","created_at":1549565442,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic4","username":"uname4"},"viewer_has_liked":false,"edge_liked_by":{"count":3}}},{"node":{"id":"18014501047114258","text":"cmt5","created_at":1549622948,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic5","username":"uname5"},"viewer_has_liked":false,"edge_liked_by":{"count":0}}},{"node":{"id":"18012364975121513","text":"cmt6","created_at":1549624991,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic6","username":"uname6"},"viewer_has_liked":false,"edge_liked_by":{"count":1}}}]}}},{"node":{"id":"18014605018119580","text":"cmt7","created_at":1549563882,"did_report_as_spam":false,"owner":{"id":"1575737610","is_verified":false,"profile_pic_url":"pic7","username":"uname7"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18006807262092548","text":"cmt8","created_at":1549563710,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic8","username":"uname8"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014414656112658","text":"cmt9","created_at":1549563555,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic9","username":"uname9"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17899732756291214","text":"cmt10","created_at":1549563119,"did_report_as_spam":false,"owner":{"id":"2330649029","is_verified":false,"profile_pic_url":"pic10","username":"uname10"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18030447571010198","text":"cmt11","created_at":1549562991,"did_report_as_spam":false,"owner":{"id":"5763461995","is_verified":false,"profile_pic_url":"pic11","username":"uname11"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18016886404100187","text":"cmt12","created_at":1549562982,"did_report_as_spam":false,"owner":{"id":"321345545","is_verified":false,"profile_pic_url":"pic12","username":"uname12"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17992787185168932","text":"cmt13","created_at":1549562672,"did_report_as_spam":false,"owner":{"id":"3267878847","is_verified":false,"profile_pic_url":"pic13","username":"uname13"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014099035112644","text":"cmt14","created_at":1549562649,"did_report_as_spam":false,"owner":{"id":"7495332966","is_verified":false,"profile_pic_url":"pic14","username":"uname14"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17851892326346682","text":"cmt15","created_at":1549562460,"did_report_as_spam":false,"owner":{"id":"8692656309","is_verified":false,"profile_pic_url":"pic15","username":"uname15"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}}]}}},"status":"ok"}
sKeys := { "edge_liked_by": []
, "edge_threaded_comments": []
, "text": []
, "id": []
, "created_at": []
, "username": ["owner"]
, "profile_pic_url": ["owner"]
, "end_cursor": ["edge_threaded_comments", "page_info"]
, "edge_threaded_comments": ["edge_threaded_comments"]
, "edges": ["edge_threaded_comments"]}
edges := JSON.Parse(ResponseText).data.shortcode_media.edge_media_to_parent_comment.edges
res := % ListValues(edges, sKeys)
MsgBox % res
;fileappend %res%`n, _____.txt, UTF-8
ExitApp
ListValues(edges, srchKeys, inner := false) {
list := ""
For k, v in edges {
tmpArray := []
list .= Format("`n{}█ {}#{} `n", inner ? "`t" : "", inner ? "" : "", A_Index)
For name, path in srchKeys {
tmp := v.node
For index, item in path {
tmp := tmp[ item ]
}
if (IsObject(val := tmp[ name ])) {
tmpArray := val
}
list .= Format("{}{}. - {} = {}`n", inner ? "`t" : "", A_Index, name, IsObject(val) ? "[]" : val ? val : "NoValue" )
} (tmpArray.Length() && (list .= ListValues(tmpArray, srchKeys, true)))
} Return list
}
class JSON
{
static JS := JSON._GetJScripObject()
Parse(JsonString) {
try oJSON := this.JS.("(" JsonString ")")
catch {
MsgBox, Wrong JsonString!
Return
}
Return this._CreateObject(oJSON)
}
_GetJScripObject() {
VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
FileAppend,
(
<component>
<public><method name='eval'/></public>
<script language='JScript'></script>
</component>
), % tmpFile
JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
FileDelete, % tmpFile
JSON._AddMethods(JS)
Return JS
}
_AddMethods(ByRef JS) {
JScript =
(
Object.prototype.GetKeys = function () {
var keys = []
for (var k in this)
if (this.hasOwnProperty(k))
keys.push(k)
return keys
}
Object.prototype.IsArray = function () {
var toStandardString = {}.toString
return toStandardString.call(this) == '[object Array]'
}
)
JS.("delete ActiveXObject; delete GetObject;")
JS.(JScript)
}
_CreateObject(ObjJS) {
res := ObjJS.IsArray()
if (res = "")
Return ObjJS
else if (res = -1) {
obj := []
Loop % ObjJS.length
obj[A_Index] := this._CreateObject(ObjJS[A_Index - 1])
}
else if (res = 0) {
obj := {}
keys := ObjJS.GetKeys()
Loop % keys.length
k := keys[A_Index - 1], obj[k] := this._CreateObject(ObjJS[k])
}
Return obj
}
}
Было бы нагляднее, если бы Вы привели пример попытки конечной реализации. С трудом понимаю, что требуется конкретно. Это ведь должно к чему-то приводить, верно?
Если я правильно понимаю, результат ListValues(), Вы потом снова разбираете на составляющие, чтобы вновь получить значения, только из более упрощённого источника, так?
"edge_liked_by" и "edge_threaded_comments" - не следуют в "ResponseText" после "count", напротив, оба они содержат "count" являясь объектами.
Наверное следовало так же дать пояснение, что "sKeys" - это объект, поля которого содержат нисходящие пути по иерархии текущего элемента "node", в виде массивов, порядок элементов которых соответствует имени каждого уровня вложенности для искомого элемента, имя которого, в свою очередь, соответствует имени этого поля. Но это должно быть и так очевидным и тем не менее, Вы допускаете ошибку, устанавливая для "edge_threaded_comments" путь, заканчивающийся на самом себе:
, "edge_threaded_comments": ["edge_threaded_comments"]
Хотя он там же, где и "edge_liked_by":
"edge_liked_by": []
В самом верхнем уровне. В корне.
Так же, то, что "edge_liked_by" и "edge_threaded_comments" - объекты, говорит о том, что их значения являются другими полями, а значит, если нужно их получить, то следует добавить их в "sKeys", присвоив разумные имена их полям и описав значениями их массивов вложенность, согласно иерархии.
Ещё раз хочу напомнить, что самый простой путь, это получать значения по относительному пути. Это и в плане описания проще и понятнее и получать Вы их будете в одном цикле, а не в трёх.
И ещё, ListValues() собирает данные в строку только для наглядности и Вы можете изменить её для получения данных в любом формате. В следующем примере, ListValues() вернёт объект с полями "txt" и "data", в которых первое, будет представлять искомое содержимое в текстовом виде, как и раньше, а второе, будет массивом с той же структурой из 12 элементов, в котором третий, будет содержать поле "edges" в виде массива из трёх элементов с той же структурой, что и его родитель.
#Include <JSON>
ResponseText = {"data":{"shortcode_media":{"edge_media_to_parent_comment":{"count":224,"page_info":{"has_next_page":true,"end_cursor":"{\"cached_comments_cursor\": \"17988603055194856\", \"bifilter_token\": \"KC0BDABAABgAEAAQAAgACAB799_Lz77P7011eOpvf_W__wAUAAAAABAEQ0EgwBAA\"}"},"edges":[{"node":{"id":"18033126139045251","text":"cmt1","created_at":1549564430,"did_report_as_spam":false,"owner":{"id":"7147681468","is_verified":false,"profile_pic_url":"pic1","username":"uname1"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18035179396030512","text":"cmt2","created_at":1549564345,"did_report_as_spam":false,"owner":{"id":"9037884033","is_verified":false,"profile_pic_url":"pic2","username":"uname2"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17864531659321218","text":"cmt3","created_at":1549563973,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic3","username":"uname3"},"viewer_has_liked":false,"edge_liked_by":{"count":1},"edge_threaded_comments":{"count":3,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[{"node":{"id":"18031519045002885","text":"cmt4","created_at":1549565442,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic4","username":"uname4"},"viewer_has_liked":false,"edge_liked_by":{"count":3}}},{"node":{"id":"18014501047114258","text":"cmt5","created_at":1549622948,"did_report_as_spam":false,"owner":{"id":"3881253436","is_verified":false,"profile_pic_url":"pic5","username":"uname5"},"viewer_has_liked":false,"edge_liked_by":{"count":0}}},{"node":{"id":"18012364975121513","text":"cmt6","created_at":1549624991,"did_report_as_spam":false,"owner":{"id":"1514648096","is_verified":false,"profile_pic_url":"pic6","username":"uname6"},"viewer_has_liked":false,"edge_liked_by":{"count":1}}}]}}},{"node":{"id":"18014605018119580","text":"cmt7","created_at":1549563882,"did_report_as_spam":false,"owner":{"id":"1575737610","is_verified":false,"profile_pic_url":"pic7","username":"uname7"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18006807262092548","text":"cmt8","created_at":1549563710,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic8","username":"uname8"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014414656112658","text":"cmt9","created_at":1549563555,"did_report_as_spam":false,"owner":{"id":"3451206464","is_verified":false,"profile_pic_url":"pic9","username":"uname9"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17899732756291214","text":"cmt10","created_at":1549563119,"did_report_as_spam":false,"owner":{"id":"2330649029","is_verified":false,"profile_pic_url":"pic10","username":"uname10"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18030447571010198","text":"cmt11","created_at":1549562991,"did_report_as_spam":false,"owner":{"id":"5763461995","is_verified":false,"profile_pic_url":"pic11","username":"uname11"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18016886404100187","text":"cmt12","created_at":1549562982,"did_report_as_spam":false,"owner":{"id":"321345545","is_verified":false,"profile_pic_url":"pic12","username":"uname12"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17992787185168932","text":"cmt13","created_at":1549562672,"did_report_as_spam":false,"owner":{"id":"3267878847","is_verified":false,"profile_pic_url":"pic13","username":"uname13"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"18014099035112644","text":"cmt14","created_at":1549562649,"did_report_as_spam":false,"owner":{"id":"7495332966","is_verified":false,"profile_pic_url":"pic14","username":"uname14"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}},{"node":{"id":"17851892326346682","text":"cmt15","created_at":1549562460,"did_report_as_spam":false,"owner":{"id":"8692656309","is_verified":false,"profile_pic_url":"pic15","username":"uname15"},"viewer_has_liked":false,"edge_liked_by":{"count":0},"edge_threaded_comments":{"count":0,"page_info":{"has_next_page":false,"end_cursor":null},"edges":[]}}}]}}},"status":"ok"}
sKeys := { "edge_liked_by": []
, "edge_threaded_comments": []
, "text": []
, "id": []
, "created_at": []
, "username": ["owner"]
, "profile_pic_url": ["owner"]
, "end_cursor": ["edge_threaded_comments", "page_info"]
, "edge_threaded_comments": []
, "edges": ["edge_threaded_comments"] }
edges := JSON.Parse(ResponseText).data.shortcode_media.edge_media_to_parent_comment.edges
res := % ListValues(edges, sKeys)
;MsgBox % res
Gui,1: Margin, 10, 10
Gui,1: Font,,Consolas
Gui,1: Add, Edit,w700 r40 HScroll,% res.txt
Gui,1: Font
Gui,1: Show,,JSON src
Return
GuiClose:
ExitApp
ListValues(edges, srchKeys, inner := false) {
list := "", data := []
For k, v in edges {
tmpArray := [], list .= Format("`n{}█ {}#{} `n", inner ? "`t" : "", inner ? "" : "", A_Index), o := {}
For name, path in srchKeys {
tmp := v.node
For index, item in path
tmp := tmp[ item ]
if (IsObject(val := tmp[ name ]) && name == "edges")
tmpArray := val
list .= Format("{}{}. - {} = {}`n", inner ? "`t" : "", A_Index, name, IsObject(val) ? JSON.Stringify(val) : val ? val : "NoValue" )
o[name] := val
} (tmpArray.Length() && (list .= (iObj := ListValues(tmpArray, srchKeys, true)).txt, o.edges := iObj.data)), data.Push(o)
} Return {"txt": list, "data": data}
}
Обращаться к его содержимому будет проще, чем ещё раз разбирать разбирать строку. Это, по сути, уже упрощённый вариант изначального JSON, описанный согласно установкам в "sKeys".
Если я правильно понимаю, результат ListValues(), Вы потом снова разбираете на составляющие, чтобы вновь получить значения, только из более упрощённого источника, так?
Да, именно это). Иными словами, мне надо, чтобы были переменные с названиями ключей, в каждой из которых содержалось бы соответствующее полученное значение ключа. Например: переменная с названием %text% — содержит значение ключа "text", и т.д. Это позволит распредилить все переменные по каркасу из HTML-тегов и накапливать в цикле как комментарий, по типу:
cmt .= "<div class=""comment"">`n<img class=""img"" src=""" matchh3 """>`n<div class=""info""><a href=""" matchh4 """>" matchh2 "</a> – <a href=""watch?v=" videoId "&lc=" matchh1 """>" matchh7 "</a><span class=""vote"">" matchh6 "</span></div>`n<div class=""content"">" matchh5 "</div>`n</div>`n"
То есть, каждый блок нужен не в том виде, как выводится сейчас — а как отдельный комментарий в тегах. В этом скрипте пример такого вывода результатов:
str =
(
{"replycount":173,"comments":[{"collapsed":0,"shown":1,"collapsed":0,"userpic":"https://l-userpic.livejournal.com/125166311/76306440","actions":[{"allowed":1,"href":"https://livejournal.com/2796915.html?replyto=1321676147","name":"reply","title":"Ответить","footer":1},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321676147#t1321676147","name":"permalink","title":"ссылка"},{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321676147#t1321676147","name":"collapse","title":"Свернуть"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321676147#t1321676147","name":"expand","title":"Развернуть"}],"uname":"leyb_bronshteyn","loaded":1,"p_tracked":0,"commenter_journal_base":"https://leyb-bronshteyn.livejournal.com/","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321676147,"talkid":5162797,"thread_url":"https://livejournal.com/2796915.html?thread=1321676147#t1321676147","above":1321663091,"upictitle":"leyb_bronshteyn: trotsky","article":"КОММЕНТАРИЙ1","controls":[{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://www.livejournal.com/manage/subscriptions/comments.bml?talkid=1321676147&journal=jour","name":"track","title":"Отслеживать"}],"siteroot":"https://www.livejournal.com","poster":"tema","stime":"4 дня назад","ctime":"30 июня 2018, 17:12:32 UTC","parent":1321663091,"massactions":1,"subject":"","deleted":0,"username":[{"journal_url":"https://leyb-bronshteyn.livejournal.com/","striked":null,"journaltype":"P","userhead_url":"https://l-stat.livejournal.net/img/userinfo_v8.svg?v=17080?v=257.1","color":null,"noctxpopup":0,"side_alias":0,"journal":"leyb_bronshteyn","inline_css":0,"attrs":null,"is_identity":0,"bold":1,"show_userhead":1,"username":"leyb_bronshteyn","user_alias":"","profile_url":"https://leyb-bronshteyn.livejournal.com/profile","alias":0}],"is_promo":0,"dname":"leyb_bronshteyn","ctime_ts":1530378752,"is_best":0,"tracked":0},{"shown":0,"collapsed":1,"uname":"","loaded":0,"p_tracked":0,"commenter_journal_base":"","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321677683,"talkid":5162803,"thread_url":"https://livejournal.com/2796915.html?thread=1321677683#t1321677683","above":1321676147,"siteroot":"https://www.livejournal.com","poster":"tema","stime":"4 дня назад","below":1321699955,"parent":1321676147,"massactions":1,"deleted":1,"is_promo":0,"dname":"","ctime_ts":1530378800,"leafclass":"deleted","is_best":0,"tracked":0},{"shown":1,"collapsed":0,"userpic":"https://l-userpic.livejournal.com/121339544/65211451","actions":[{"allowed":1,"href":"https://livejournal.com/2796915.html?replyto=1321846131","name":"reply","title":"Ответить","footer":1},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321846131#t1321846131","name":"permalink","title":"ссылка"},{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321846131#t1321846131","name":"collapse","title":"Свернуть"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321846131#t1321846131","name":"expand","title":"Развернуть"}],"uname":"ext_2042553","loaded":1,"p_tracked":0,"commenter_journal_base":"http://my.mail.ru/list/iwasko/","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321846131,"talkid":5163461,"thread_url":"https://livejournal.com/2796915.html?thread=1321846131#t1321846131","above":1321806195,"upictitle":"Иван Пирогов: pic#121339544","article":"КОММЕНТАРИЙ2","controls":[{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://www.livejournal.com/manage/subscriptions/comments.bml?talkid=1321846131&journal=jour","name":"track","title":"Отслеживать"}],"siteroot":"https://www.livejournal.com","poster":"tema","stime":"3 дня назад","ctime":"1 июля 2018, 16:26:49 UTC","parent":1321806195,"massactions":1,"subject":"","deleted":0,"username":[{"journal_url":"http://my.mail.ru/list/iwasko/","striked":null,"journaltype":"I","userhead_url":"https://l-stat.livejournal.net/img/mailru-profile.gif?v=12149?v=257.1","color":null,"noctxpopup":0,"side_alias":0,"journal":"Иван Пирогов","inline_css":0,"attrs":null,"is_identity":1,"bold":1,"show_userhead":1,"username":"ext_2042553","user_alias":"","profile_url":"https://www.livejournal.com/profile?userid=65211451&t=I","alias":0}],"is_promo":0,"dname":"Иван Пирогов","ctime_ts":1530462409,"is_best":0,"tracked":0},{"shown":1,"collapsed":0,"actions":[{"allowed":1,"href":"https://livejournal.com/2796915.html?replyto=1321712499","name":"reply","title":"Ответить","footer":1},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321712499#t1321712499","name":"permalink","title":"ссылка"},{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321712499#t1321712499","name":"collapse","title":"Свернуть"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321712499#t1321712499","name":"expand","title":"Развернуть"}],"uname":"v_unitaz","loaded":1,"p_tracked":0,"commenter_journal_base":"https://v-unitaz.livejournal.com/","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321712499,"talkid":5162939,"thread_url":"https://livejournal.com/2796915.html?thread=1321712499#t1321712499","above":1321677683,"upictitle":"v_unitaz: pic#0","article":"КОММЕНТАРИЙ3","controls":[{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://www.livejournal.com/manage/subscriptions/comments.bml?talkid=1321712499&journal=jour","name":"track","title":"Отслеживать"}],"siteroot":"https://www.livejournal.com","poster":"tema","stime":"4 дня назад","ctime":"30 июня 2018, 19:08:18 UTC","parent":1321677683,"massactions":1,"subject":"","deleted":0,"username":[{"journal_url":"https://v-unitaz.livejournal.com/","striked":null,"journaltype":"P","userhead_url":"https://l-stat.livejournal.net/img/userinfo_v8.svg?v=17080?v=257.1","color":null,"noctxpopup":0,"side_alias":0,"journal":"v_unitaz","inline_css":0,"attrs":null,"is_identity":0,"bold":1,"show_userhead":1,"username":"v_unitaz","user_alias":"","profile_url":"https://v-unitaz.livejournal.com/profile","alias":0}],"is_promo":0,"dname":"v_unitaz","ctime_ts":1530385698,"is_best":0,"tracked":0},{"shown":1,"collapsed":0,"userpic":"https://l-userpic.livejournal.com/127834290/83644284","actions":[{"allowed":1,"href":"https://livejournal.com/2796915.html?replyto=1321713779","name":"reply","title":"Ответить","footer":1},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321713779#t1321713779","name":"permalink","title":"ссылка"},{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321713779#t1321713779","name":"collapse","title":"Свернуть"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321713779#t1321713779","name":"expand","title":"Развернуть"}],"uname":"lovelement","loaded":1,"p_tracked":0,"commenter_journal_base":"https://lovelement.livejournal.com/","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321713779,"talkid":5162944,"thread_url":"https://livejournal.com/2796915.html?thread=1321713779#t1321713779","above":1321712499,"upictitle":"lovelement: pic#127834290","article":"КОММЕНТАРИЙ4","controls":[{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://www.livejournal.com/manage/subscriptions/comments.bml?talkid=1321713779&journal=jour","name":"track","title":"Отслеживать"}],"siteroot":"https://www.livejournal.com","poster":"tema","stime":"4 дня назад","below":1321768563,"ctime":"30 июня 2018, 19:15:49 UTC","parent":1321712499,"massactions":1,"subject":"","deleted":0,"username":[{"journal_url":"https://lovelement.livejournal.com/","striked":null,"journaltype":"P","userhead_url":"https://l-stat.livejournal.net/img/userinfo_v8.svg?v=17080?v=257.1","color":null,"noctxpopup":0,"side_alias":0,"journal":"lovelement","inline_css":0,"attrs":null,"is_identity":0,"bold":1,"show_userhead":1,"username":"lovelement","user_alias":"","profile_url":"https://lovelement.livejournal.com/profile","alias":0}],"is_promo":0,"dname":"lovelement","ctime_ts":1530386149,"is_best":0,"tracked":0},{"shown":1,"collapsed":0,"actions":[{"allowed":1,"href":"https://livejournal.com/2796915.html?replyto=1321720435","name":"reply","title":"Ответить","footer":1},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321720435#t1321720435","name":"permalink","title":"ссылка"},{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321720435#t1321720435","name":"collapse","title":"Свернуть"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321720435#t1321720435","name":"expand","title":"Развернуть"}],"uname":"v_unitaz","loaded":1,"p_tracked":0,"commenter_journal_base":"https://v-unitaz.livejournal.com/","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321720435,"talkid":5162970,"thread_url":"https://livejournal.com/2796915.html?thread=1321720435#t1321720435","above":1321713779,"upictitle":"v_unitaz: pic#0","article":"КОММЕНТАРИЙ5","controls":[{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://www.livejournal.com/manage/subscriptions/comments.bml?talkid=1321720435&journal=jour","name":"track","title":"Отслеживать"}],"siteroot":"https://www.livejournal.com","poster":"tema","stime":"4 дня назад","ctime":"30 июня 2018, 20:29:16 UTC","parent":1321713779,"massactions":1,"subject":"","deleted":0,"username":[{"journal_url":"https://v-unitaz.livejournal.com/","striked":null,"journaltype":"P","userhead_url":"https://l-stat.livejournal.net/img/userinfo_v8.svg?v=17080?v=257.1","color":null,"noctxpopup":0,"side_alias":0,"journal":"v_unitaz","inline_css":0,"attrs":null,"is_identity":0,"bold":1,"show_userhead":1,"username":"v_unitaz","user_alias":"","profile_url":"https://v-unitaz.livejournal.com/profile","alias":0}],"is_promo":0,"dname":"v_unitaz","ctime_ts":1530390556,"is_best":0,"tracked":0},{"shown":1,"collapsed":0,"userpic":"https://l-userpic.livejournal.com/127834290/83644284","actions":[{"allowed":1,"href":"https://livejournal.com/2796915.html?replyto=1321720691","name":"reply","title":"Ответить","footer":1},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321720691#t1321720691","name":"permalink","title":"ссылка"},{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321720691#t1321720691","name":"collapse","title":"Свернуть"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321720691#t1321720691","name":"expand","title":"Развернуть"}],"uname":"lovelement","loaded":1,"p_tracked":0,"commenter_journal_base":"https://lovelement.livejournal.com/","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321720691,"talkid":5162971,"thread_url":"https://livejournal.com/2796915.html?thread=1321720691#t1321720691","above":1321720435,"upictitle":"lovelement: pic#127834290","article":"КОММЕНТАРИЙ6","controls":[{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://www.livejournal.com/manage/subscriptions/comments.bml?talkid=1321720691&journal=jour","name":"track","title":"Отслеживать"}],"siteroot":"https://www.livejournal.com","poster":"tema","stime":"4 дня назад","ctime":"30 июня 2018, 20:35:06 UTC","parent":1321720435,"massactions":1,"subject":"","deleted":0,"username":[{"journal_url":"https://lovelement.livejournal.com/","striked":null,"journaltype":"P","userhead_url":"https://l-stat.livejournal.net/img/userinfo_v8.svg?v=17080?v=257.1","color":null,"noctxpopup":0,"side_alias":0,"journal":"lovelement","inline_css":0,"attrs":null,"is_identity":0,"bold":1,"show_userhead":1,"username":"lovelement","user_alias":"","profile_url":"https://lovelement.livejournal.com/profile","alias":0}],"is_promo":0,"dname":"lovelement","ctime_ts":1530390906,"is_best":0,"tracked":0},{"shown":1,"collapsed":0,"userpic":"https://l-userpic.livejournal.com/82196355/5817510","actions":[{"allowed":1,"href":"https://livejournal.com/2796915.html?replyto=1321717619","name":"reply","title":"Ответить","footer":1},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321717619#t1321717619","name":"permalink","title":"ссылка"},{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321717619#t1321717619","name":"collapse","title":"Свернуть"},{"allowed":1,"href":"https://livejournal.com/2796915.html?thread=1321717619#t1321717619","name":"expand","title":"Развернуть"}],"uname":"poulsam","loaded":1,"p_tracked":0,"commenter_journal_base":"https://poulsam.livejournal.com/","statprefix":"https://l-stat.livejournal.net","lj_statprefix":"https://l-stat.livejournal.net","dtalkid":1321717619,"talkid":5162959,"thread_url":"https://livejournal.com/2796915.html?thread=1321717619#t1321717619","above":1321695859,"upictitle":"Poul: pic#82196355","article":"КОММЕНТАРИЙ7","controls":[{"checkbox":1,"allowed":1,"name":"checkbox","title":"Выбрать"},{"allowed":1,"href":"https://www.livejournal.com/manage/subscriptions/comments.bml?talkid=1321717619&journal=jour","name":"track","title":"Отслеживать"}],"siteroot":"https://www.livejournal.com","poster":"tema","stime":"4 дня назад","ctime":"30 июня 2018, 19:47:49 UTC","parent":1321650291,"massactions":1,"subject":"","deleted":0,"username":[{"journal_url":"https://poulsam.livejournal.com/","striked":null,"journaltype":"P","userhead_url":"https://l-stat.livejournal.net/img/userinfo_v8.svg?v=17080?v=257.1","color":null,"noctxpopup":0,"side_alias":0,"journal":"poulsam","inline_css":0,"attrs":null,"is_identity":0,"bold":1,"show_userhead":1,"username":"poulsam","user_alias":"","profile_url":"https://poulsam.livejournal.com/profile","alias":0}],"is_promo":0,"dname":"poulsam","ctime_ts":1530388069,"is_best":0,"tracked":0}]}
)
obj := JSON.Parse(str)
keys =
(
userpic
uname
commenter_journal_base
dtalkid
upictitle
article
ctime
userhead_url
dname
)
for k, v in obj.comments {
Loop, parse, keys, `n, `r
%A_LoopField%%k% := SearchKey(v, A_LoopField)
}
loop
MsgBox, % userpic%a_index% "`n" uname%a_index% "`n" commenter_journal_base%a_index% "`n" dtalkid%a_index% "`n" upictitle%a_index% "`n" article%a_index% "`n" ctime%a_index% "`n" userhead_url%a_index% "`n" dname%a_index% "`n"
SearchKey(obj, key) {
for k, v in obj {
if (k = key)
Return v
if IsObject(v) {
res := SearchKey(v, key)
if (res != "")
Return res
}
}
}
class JSON
{
static JS := JSON._GetJScripObject()
Parse(JsonString) {
try oJSON := this.JS.("(" JsonString ")")
catch {
MsgBox, Wrong JsonString!
Return
}
Return this._CreateObject(oJSON)
}
_GetJScripObject() {
VarSetCapacity(tmpFile, (MAX_PATH := 260) << !!A_IsUnicode, 0)
DllCall("GetTempFileName", Str, A_Temp, Str, "AHK", UInt, 0, Str, tmpFile)
FileAppend,
(
<component>
<public><method name='eval'/></public>
<script language='JScript'></script>
</component>
), % tmpFile
JS := ObjBindMethod( ComObjGet("script:" . tmpFile), "eval" )
FileDelete, % tmpFile
JSON._AddMethods(JS)
Return JS
}
_AddMethods(ByRef JS) {
JScript =
(
Object.prototype.GetKeys = function () {
var keys = []
for (var k in this)
if (this.hasOwnProperty(k))
keys.push(k)
return keys
}
Object.prototype.IsArray = function () {
var toStandardString = {}.toString
return toStandardString.call(this) == '[object Array]'
}
)
JS.("delete ActiveXObject; delete GetObject;")
JS.(JScript)
}
_CreateObject(ObjJS) {
res := ObjJS.IsArray()
if (res = "")
Return ObjJS
else if (res = -1) {
obj := []
Loop % ObjJS.length
obj[A_Index] := this._CreateObject(ObjJS[A_Index - 1])
}
else if (res = 0) {
obj := {}
keys := ObjJS.GetKeys()
Loop % keys.length
k := keys[A_Index - 1], obj[k] := this._CreateObject(ObjJS[k])
}
Return obj
}
}
Насчёт "edge_liked_by"/"edge_threaded_comments", вроде указывал разные вариации вложенности, но значения не выводятся.
Да, именно это).
Весьма прискорбно. Вы бы могли возвращать сразу готовую строку из такой функции, на подобии той, которую она уже возвращает, но только в нужной Вам конфигурации.
Если я Вам так и не смог помочь, то добавить мне уже нечего. Доработать решение "напильником" под свои нужды, не сложно.
Но там формат, в котором переменная общая для каждого ключа —
list .= Format("{}{}. - {} = {}`n", inner ? "`t" : "", A_Index, name, IsObject(val) ? JSON.Stringify(val) : val ? val : "NoValue" )
и поэтому, насколько могу судить, каждую строку придется повторно изменять.
"edge_liked_by"/"edge_threaded_comments" — записывал в том числе так, согласно иерархии, но значения не выводятся:
"edge_liked_by": ["owner", "edges"]