Pixivから画像(サムネイル)を取得する

Pixivは外部にAPIなどを公開していないので、その画像を取得するのは容易ではありません(?) しかしながらTwitterクライアントを作っているとどうにもサムネイルを表示したいと感じることがままあります。

そこで、若干グレーなことをしつつPixivのIDから画像のURLを取得する方法を調べたので列挙しておきます。

既出だったら申し訳ないです (2016/06/20時点の記事です)

その1 ブログパーツ用のものから持ってくる

この方法では

  • 画像のIDがわかれば置換などで一発で取得できる
  • 画像に枠がつく
  • R-18不可

取得方法は簡単で以下のURLにアクセスするだけです。 http://embed.pixiv.net/decorate.php?illust_id=<イラストID>

こんな感じに画像が取得できます。 http://embed.pixiv.net/decorate.php?illust_id=32092803

その2 スクレイピング

その名の通り、スクレイピングをして画像のURLを取得する方法です。 が、めんどくさい割にR-18画像も取得できないのでおすすめはできません。

http://www.pixiv.net/member_illust.php?mode=medium&illust_id=32092803

注意したいのが、リクエストヘッダにRefererの指定がいることです。 画像取得時にも必須です。

C#によるサンプル

var url = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + id;

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36");
client.DefaultRequestHeaders.Add("Referer", url);

HttpResponseMessage response = await client.GetAsync(new Uri(url));
response.Content.Headers.ContentType.CharSet = "utf-8";
string contents = await response.Content.ReadAsStringAsync();

var doc = new HtmlDocument();
doc.LoadHtml(contents);
var imgContainer = doc.DocumentNode.Descendants("div").Where(d => d.Attributes.Contains("class") && d.Attributes["class"].Value.Contains("img-container"));
var imgUrl = imgContainer.First().Descendants("img").First().GetAttributeValue("src", "");

HtmlAgilityPackを使用しています。

その3 埋め込みパーツ用のものから持ってくる

この方法ではR-18画像をも持ってこれるので良さげです。 ただ、mediumサイズ以外ではCookie?の取得が必要っぽいので注意が入ります。 mediumサイズなら特に必要ないので楽ちんです。

流れとしては

  1. http://embed.pixiv.net/embed_json.phpにアクセスしてjsonp形式のデータを取得
    • パラメータはcallback, id, size
    • size{large, medium, small}のどれか
    • idはイラストID
    • callbackjsonpのやつ なんでもいい
    • 例) http://embed.pixiv.net/embed_json.php?callback=oppai&size=medium&id=32092803
  2. 得られたjsonpのデータを整形してparse
  3. imgのURLを読み取って終わり

画像サイズmediumの場合、得られる画像のURLが http://i2.pixiv.net/c/240x480/img-master/img/~ という形式になっているのですが、 これがsmallなら240x480の部分が150x150、largeなら600x600となるだけなので、 一回APIにアクセスするだけで3種類の画像サイズのURLが取得できるお得なものになっています。

C#によるサンプル

var url = "http://embed.pixiv.net/embed_json.php?callback=test&size=large&id=" + id;

HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36");
HttpResponseMessage response = await client.GetAsync(new Uri(url));

var resjson = await response.Content.ReadAsStringAsync();
resjson = resjson.Remove(0, 5).TrimEnd(')');
var jobject = JsonConvert.DeserializeObject<JObject>(resjson);
            
var imgUrl = jobject ["img"].ToString();

Newtonsoft.Jsonを使用しています。

その4 非公式APIを叩く

画像のURL取得にログインがいる上に、完全にグレーな感じなのでそこまでお勧めできません。 Pixivに関連するサービスを作る時以外は触らないほうが吉

宣伝ではないですが、自分がPixivビューアを作るときに作った.NET向けのライブラリがあるので、 それを使うと比較的簡単にURLが取得できるかなと思います。

Pythonならpip install pixivpypixivpyという便利なライブラリを叩けます。

C#によるサンプル

var tokens = await Pixeez.Auth.AuthorizeAsync("username", "password");
var work = await tokens.GetWorksAsync(51796422);
var thumbnailUrl = work.ImageUrls.Px480mw;
var imgUrl = work.ImageUrls.Large;

Pixeezを使用しています。

まとめ

取得方法 ログイン R-18 取得の簡単さ おすすめ度
ブログパーツ 不必要 ×
スクレイピング 不必要 ×
埋め込みパーツ 不必要
非公式API 必要 ?

お好きな方法をお選びください。

一番楽なのがブログパーツのものを使う方法なので、ツイッタークライアントのプレビュー用ならこれ一択かなと思います。

サムネイル用の何かをpixivさんが公開してくれると非常に嬉しいのですが・・・

間違いなどがあったら指摘してくれるとありがたいです。