Ответ 1
По популярному требованию, код для генерации заголовка SO-заголовков топ-10 (кроме аннотаций) с помощью SO API (это довольно опрятный и полный API, много плюсов там. Легко - см. мой код).
Обновить: добавлено приложение-ключ, чтобы обеспечить более эффективное взаимодействие кода с SO-API (более высокая ежедневная кепка звонка). Используйте его только для этого приложения.
Апрель 2011
Август 2011
версия MMA 8! Версия MMA7 далее вниз
getRepChanges[userID_Integer] :=
Module[{totalChanges},
totalChanges =
"total" /.
Import["http://api.stackoverflow.com/1.1/users/" <>
ToString[userID] <> "/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=1&page=1",
"JSON"
];
Join @@
Table[
"rep_changes" /.
Import["http://api.stackoverflow.com/1.1/users/" <>
ToString[userID] <>
"/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=100&page="
<> ToString[page],
"JSON"
],
{page, 1, Ceiling[totalChanges/100]}
]
]
topAnswerers =
({"display_name","user_id", "email_hash"} /. #) & /@
("user" /.
("top_users" /.
Import[
"http://api.stackoverflow.com/1.1/tags/mathematica/top-answerers/all-time",
"JSON"
]
)
)
topAnswerers = {#, #2,
Import["http://www.gravatar.com/avatar/" <> #3 <> ".jpg?s=36&d=identicon&d=identicon"]
} & @@@ topAnswerers
repChangesTopUsers =
Table[
repChange =
ReleaseHold[
(
Hold[
{
DateList["on_date" + AbsoluteTime["January 1, 1970"]],
"positive_rep" - "negative_rep"
}
] /. #
) & /@ getRepChanges[userID]
] // Sort;
accRepChange = {repChange[[All, 1]],Accumulate[repChange[[All, 2]]]}\[Transpose],
{userID, topAnswerers[[All, 2]]}
];
pl = DateListLogPlot[
Tooltip @@@
Take[({repChangesTopUsers, Row /@ topAnswerers[[All, {3, 1}]]}\[Transpose]),
10], Joined -> True, Mesh -> None, ImageSize -> 1000,
PlotRange -> {All, {10, All}},
BaseStyle -> {FontFamily -> "Arial-Bold", FontSize -> 16},
DateTicksFormat -> {"MonthNameShort", " ", "Year"},
GridLines -> {True, None},
FrameLabel -> (Style[#, FontSize -> 18] & /@ {"Date", "Reputation",
"Top-10 answerers", ""})]
ИЗМЕНИТЬ
Обратите внимание, что вы можете построить до и включая верхнюю 20, изменив значение в функции Take. Он очень быстро занят.
Попытался улучшить читабельность кода разметки. Я боюсь, что это скопирует некоторые ложные пространства.
ИЗМЕНИТЬ
Размер страницы обратно до 100 элементов/страница == > меньше вызовов API
Обратите внимание, что первый вызов API - это определение количества сообщений, которые пользователь имеет. Эти данные присутствуют независимо от размера страницы, поэтому это предпочтительно выбирается небольшим (10 или около того, возможно, 1, не проверял). Затем данные извлекаются на последующих страницах до тех пор, пока не будет достигнута последняя страница. Вы можете использовать максимальный размер страницы (100) для этого. Просто следите за тем, чтобы максимальное количество страниц в счете цикла было соответствующим образом скорректировано.
EDIT: лучший код MMA 7 (пт. 22 апреля)
MMA 7 не импортирует JSON, поэтому вместо текстового импорта вместо него выполняется трансляция JSON без костей. Я тестировал эту версию несколько раз (в MMA 8) и, похоже, работает без ошибок, которые я получил вчера.
getRepChanges[userID_Integer] :=
Module[{totalChanges},
totalChanges =
"total" /.
ImportString[
StringReplace[(Import[
"http://api.stackoverflow.com/1.1/users/" <>
ToString[userID] <>
"/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=1&page=1", "Text"]), {":" ->
"->", "[" -> "{", "]" -> "}"}], "NB"];
Join @@
Table["rep_changes" /.
ImportString[
StringReplace[
Import["http://api.stackoverflow.com/1.1/users/" <>
ToString[userID] <>
"/reputation?key=NgVJ4Y6vFkuF-oqI-eOvOw&fromdate=0&pagesize=100&page=" <> ToString[page],
"Text"], {":" -> "->", "[" -> "{", "]" -> "}"}],
"NB"], {page, 1, Ceiling[totalChanges/100]}]]
topAnswerers = ({"display_name", "user_id",
"email_hash"} /. #) & /@ ("user" /. ("top_users" /.
ImportString[
StringReplace[
" " <> Import[
"http://api.stackoverflow.com/1.1/tags/mathematica/top-answerers/all-time", "Text"], {":" -> "->", "[" -> "{", "]" -> "}"}],
"NB"]))
topAnswerers = {#, #2,
Import["http://www.gravatar.com/avatar/" <> #3 <>
".jpg?s=36&d=identicon&d=identicon"]} & @@@ topAnswerers
repChangesTopUsers =
Table[repChange =
ReleaseHold[(Hold[{DateList[
"on_date" + AbsoluteTime["January 1, 1970"]],
"positive_rep" - "negative_rep"}] /. #) & /@
getRepChanges[userID]] // Sort;
accRepChange = {repChange[[All, 1]],
Accumulate[repChange[[All, 2]]]}\[Transpose], {userID,
topAnswerers[[All, 2]]}];
DateListLogPlot[
Tooltip @@@
Take[({repChangesTopUsers,
Row /@ topAnswerers[[All, {3, 1}]]}\[Transpose]), 10],
Joined -> True, Mesh -> None, ImageSize -> 1000,
PlotRange -> {All, {10, All}},
BaseStyle -> {FontFamily -> "Arial-Bold", FontSize -> 16},
DateTicksFormat -> {"MonthNameShort", " ", "Year"},
GridLines -> {True, None},
FrameLabel -> (Style[#, FontSize -> 18] & /@ {"Date", "Reputation",
"Top-10 answerers", ""})]
EDIT: вспомогательные функции для фильтрации по тегам post
Эти функции могут использоваться для фильтрации прибыли репутации, чтобы найти прибыль только для определенных тегов.
tagLookup
получает целое число post_ID в качестве входных данных и дает конкретные теги сообщений. getQuestionIDs
и getAnswerIDsFrom...
идут в другую сторону. С учетом тега они находят все идентификаторы вопросов и ответов, чтобы можно было проверить с помощью MemberQ
, принадлежит ли данный post_ID этому тегу. И теги tagLookup, и getAnswerID медленны, потому что требуется много вызовов API. Я не мог проверить последние две функции, поскольку доступ к API недоступен или мой IP-адрес закрыт.
tagLookup[postID_Integer] :=
Module[{im},
im = Import["http://api.stackoverflow.com/1.1/questions/" <> ToString[postID],"JSON"];
If[("questions" /. im) != {},
First[("tags" /. ("questions" /. im))],
im = Import["http://api.stackoverflow.com/1.1/answers/" <> ToString[postID],"JSON"];
First[("tags" /. ("questions" /. Import["http://api.stackoverflow.com/1.1/questions/" <>
ToString[First["question_id" /. ("answers" /. im)]], "JSON"]))]
]
]
getQuestionIDs[tagName_String] := Module[{total},
total =
"total" /.
Import["http://api.stackoverflow.com/1.1/questions?tagged=" <>
tagName <> "&pagesize=1", "JSON"];
Join @@
Table[("question_id" /. ("questions" /.
Import["http://api.stackoverflow.com/1.1/questions?key=NgVJ4Y6vFkuF-oqI-eOvOw&tagged=" <>
tagName <> "&pagesize=100&page=" <> ToString[i],
"JSON"])), {i, 1, Ceiling[total/100]}]
]
getAnswerIDsFromQuestionID[questionID_Integer] :=
Module[{total},
total =
Import["http://api.stackoverflow.com/1.1/questions/" <>
ToString[questionID] <> "/answers?key=NgVJ4Y6vFkuF-oqI-eOvOw&pagesize=1", "JSON"];
If[total === $Failed, Return[$Failed], total = "total" /. total];
Join @@ Table[
"answer_id" /. ("answers" /.
Import["http://api.stackoverflow.com/1.1/questions/" <>
ToString[questionID] <> "/answers?key=NgVJ4Y6vFkuF-oqI-eOvOw&pagesize=100&page=" <>
ToString[i], "JSON"]), {i, 1, Ceiling[total/100]}]
]
getAnswerIDsFromTag[tagName_String] :=
Module[{},
Join @@ (getAnswerIDsFromQuestionID /@
Cases[getQuestionIDs[tagName], Except[$Failed]])
]