Gyazoの内部API
https://gyazo.com/:image_id.json
応答
OCR及びEXIFは、すでに解析済みならproでなくても取得できるようだ
詳細ページからは取得できないが、APIからなら取得できる
Proをやめても取得できるのはよくない設計な気もするが
types.tsinterface GyazoImage {
accessible: boolean;
image_id: string;
alias_id: string;
file_size: number;
metadata_is_public: boolean;
scale: {
width: number;
height: number;
scale: number;
};
type: GyazoType;
page_title: string;
updated_at: ISOTime | null;
exif_captured_at: ISOTime | null;
desc: string;
draw_src_id: string | null;
draw_materials: unknown | null;
deletable: boolean;
owned: boolean;
drawable: boolean;
is_pro: boolean;
access_policy: "anyone";
cross_origin: "anonymous";
url: IGyazoURL;
permalink_url: PermalinkURL;
permalink_path: `/${string}`;
file_only: boolean;
has_files: boolean;
attached_files: unknown[];
thumb_url: ThumbURL;
poster_thumb_url: ThumbURL;
thumb1000: IThumbURL;
grid_thumbs: GridThumbs;
non_cropped_thumb: {
url: ThumbURL;
scaled: {
url: ThumbURL;
size: number;
scale: number;
};
};
user: User | null;
explicit: boolean;
categories: string[];
next: {
image_id: string;
alias_id: string;
permalink_url: PermalinkURL;
permalink_path: `/${string}`;
};
prev: {
image_id: string;
alias_id: string;
permalink_url: PermalinkURL;
permalink_path: `/${string}`;
};
has_mp4: boolean;
mp4_url: `https://i.gyazo.com/${string}.mp4`;
download_mp4_url: `https://i.gyazo.com/download/${string}.mp4`;
download_gif_url: `https://i.gyazo.com/download/${string}.gif`;
is_preview_gif: boolean;
has_audio: boolean;
has_voice: boolean;
boards: unknown[];
external_comments: unknown[];
metadata?: {
app: string;
title: string;
url: string;
desc: string;
ocr_started: boolean;
ocr: {
locale: string;
description: string;
boundingPoly: BoundingPoly;
} | {
description: "";
};
ocrAnnotations: {
description: string;
boundingPoly: BoundingPoly;
}[] | null;
exif: Exif;
exif_status: {
captured_at: "from_created_at";
ok: true;
msg: "ok";
};
exif_normalized: {
timezone: "unknown";
} | {
timezone: "utc";
latitude: number;
longitude: number;
time: ISOTime;
};
};
}
/api/internal
internal
となっているが、
robots.txtではとくに制限されていないので、勝手に使っても問題なさそう
認証
ログアウトすれば無効になるみたい?
自動でログイン画面にredirectする
htmlファイル中に含まれている認証情報使っている?
https://gyazo.com/api/internal/images
画像一覧を取得
URL paramerters
page
(number)
per
(number)
一度に取得する画像の最大数
timestamp
(number)
なにこれ
応答
Image[]
PATCH https://gyazo.com/api/internal/images/:image_id
parameters
bodyにJSONとして送る
access_policy
"anyone"
: password解除
"passphrase"
: passwordかける
passphrase
access_policy: "passphase"
のときのみ必要
password
https://gyazo.com/api/internal/search_histories
検索履歴を取得する
URL parameters
page
(number)
paging
応答
SearchHistory[]
thumb
系が常にあるかは調べてない
types.tsinterface SearchHistory {
id: string;
title: string;
pinned: boolean;
image: {
alias_id: string;
image_id: string;
thumb_url: ThumbURL;
thumb_url_2x: ThumbURL;
thumb_url_webp: ThumbWebpURL;
thumb_url_webp_2x: ThumbWebpURL;
file_only: boolean;
has_files: boolean;
file_types: string | null; // nullしか観測していない
file_names: string | null; // nullしか観測していない
cross_origin: "anonymous";
};
};
https://gyazo.com/api/internal/search_result
検索する
URL parameters
必須
per
(number)
受け取る検索結果の最大数
10か30が使われる?
query
(string)
検索文字列
これを抜かすと500 internal errorが発生する
page
(number)
offset
exclude_linked_images
(boolean)
普通は true
不明
渡さなくてもエラーにならない
timestamp
(number)
応答
2024-11-10 11:16:31 今は不明
EXIFとサムネURL周りのpropertiesはoptionalかも
ヒット箇所は返されないようだ
types.tsinterface SearchResults {
captures: Image[];
number_of_captures: number;
query: string;
engine: "Elasticsearch";
index: `image-${number}`,
/** `false`のみ? */
start_indexing: boolean;
conditions: {
must: Query[];
must_not: Query[];
}
}
tstype Query = {
/** 複数条件当てはまるときは、その分だけQueryが返される */
match_phrase: { everything: string; } | { url: string } | { title: string } | { app: string } | { type: string };
} | {
/**
* lteがuntil, gteがsince
*
* month:2021-01にしたら、gteに"2021-01-01||+1M"が入った。
* date:2021-01-01だと、gteに"2021-01-01||+1d"が入った。
*
* 詳細なformatはhttps://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html に準拠しているようだ
*/
range: { date: { lte: `${number}-${number}-${number}`; } | { gte: `${number}-${number}-${number}`; }; };
};
関連するコード
js 32159: (e, t, a) => {
a.d(t, {
g: () => c
});
var s = a(96540)
, i = a(23041)
, r = a(72737)
, n = a(13930)
, o = a(34710);
const d = e => (0,
n.C6)()(e).then((e => ({
...e,
captures: e.captures.map((e => (0,
r.xZ)(e)))
})))
, c = ({query: e, perPage: t, excludeLinkedImages: a=!1}) => {
const {data: r, size: n, setSize: c} = (0,
i.Ay)(( (s, i) => {
if (!e)
return null;
if (0 < s && i.numberOfCaptures <= s * t)
return null;
const r = new URLSearchParams;
return r.append("query", e),
r.append("per", t.toString()),
r.append("page", (s + 1).toString()),
r.append("exclude_linked_images", a.toString()),
`/api/internal/search_result?${r}`
}
), d, {
use: [(0,
o.Cb)("images/update")],
revalidateFirstPage: !1
})
, l = (0,
s.useCallback)(( () => {
c(n + 1)
}
), [c, n]);
return {
images: r?.flatMap(( ({captures: e}) => e)),
loading: !r,
loadNext: l,
startIndexing: !!r?.[0]?.startIndexing,
numberOfResults: r?.[0]?.numberOfCaptures
}
}
}
n.C6=t=>w("GET", t)
w.js async function w(t, e, r=null, n=!1, i={}) {
const {disableCsrf: o, ...s} = i;
let a = e.startsWith("/") ? location.origin + e : e;
const c = m(e);
if (y(t, r) && Object.keys(r).length > 0) {
const t = new URLSearchParams;
Object.entries(r).forEach(( ([e,r]) => {
null != r && (Array.isArray(r) ? r.forEach((r => t.append(`${e}[]`, r.toString()))) : t.append(e, r.toString()))
}
)),
a = a + "?" + t.toString()
}
const u = await fetch(a, {
method: t,
..."GET" === t || null === r ? {} : {
body: JSON.stringify(r)
},
...g(t, o, c),
...s
});
return b(u, c, n)
}
https://gyazo.com/api/internal/images/:image_id/similar_images
関連画像
応答
Image[]
free userだと空配列が返ってくる
https://gyazo.com/api/internal/images/:image_id/close_date_images
前後にuploadされた画像
応答
types.tsinterface CloseDateImages {
before: Image[];
after: Image[];
}
https://gyazo.com/api/internal/images/:image_id/similar_metadata_images
各属性の関連画像
応答
free userだと空配列が返ってくる
types.tstype SimilarMetadata = {
[K in "title" | "app" | "url" | "ocr"]: {
keyword: string;
images: Image[];
};
};
https://gyazo.com/api/internal/images/:image_id/near_images
近くの場所で撮影された画像
応答
types.tstype NearImages = {
message: "no location";
count: 0;
images: [];
} | {
message: "ok";
count: number;
images: Image[];
};
https://gyazo.com/api/internal/boards/visits
https://gyazo.com/api/internal/images_summary
応答
なにこれ
types.tsinterface ImagesSummary {
monthly_counts: Record<number, Record<number, number>>;
}
https://gyazo.com/api/internal/boards/visits/images
画像の閲覧履歴を取得する
URL parameters
limit
取得する画像の最大数
cursor
paging用のID
応答
types.tsinterface VisitedImages {
cursor: string;
images:
}