asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_8.分割処理 Google Books API-

##棚画像を分割する方法について(Qiita説明用)

Qiitaでこれを全部説明したところでニーズもないので、掻い摘んでの説明になります！
1.本の文字部分をマウスで選択
2.Enterで本の画像を送信
-ここから非同期-
3.画像を分割
4.OCR処理
5.取得した文字を本検索
-ここまで非同期-
6.画面に結果表示

今回は、「5.取得した文字を本検索」です。
Google Books APIでの利用となります。



##Google Books APIの参考サイト
最初のきっかけはこのサイト

書籍検索APIはGoogleBooksAPIsがオススメ【導入も楽ちんです】：
　https://manablog.org/google-books-apis/

このサイトを見て導入を決め、もろもろ調べ、Google公式マニュアルを参考に実装しました。

##送受信するデータについて

他のサイトで山ほど情報があるので、説明する必要がないのですが、一応。。。
URLにパラメータを追加するだけで検索が行える！が他サイトの説明が多数となっておりますが、
検索結果の表示画面で、ページング処理も行いたいので、他のパラメータも追加して検索を実施します。

そして、Jsonフォーマットで返却されますが、C#上でどのように処理をするのか。という点では、
ニーズがあるかも。


##受信データ（JSON）のクラス化

さて、まずはクラスにしてしまいましょう。
これはご存知かと思いますが、JSONをC#の構造体クラスに変換してくれるサービスがあります。

各種API連携する場合には、必須のWebツールだと考えております。

json2csharp：
　http://json2csharp.com/


ということで、まずはベースとなるJSONデータを検索します。

https://www.googleapis.com/books/v1/volumes?q=生命と環境の化学
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/8ca45a65-7093-a7b6-9ff1-5fcc3e59aad7.png)

このJSONを、json2csharpへコピペ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/6fb21f1c-04e3-caa5-c051-d245e6625a3c.png)

↓　Generate　↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/5ebbcf25-4aa4-7612-39e0-fe18f8bf6001.png)

↓　Copy　↓

新しいクラスを作成して、貼り付け！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/6f7fface-08af-8608-987c-2da835384c4c.png)


```Models\GoogleBooks\GoogleBooks.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace sample2_1.Models.GoogleBooks
{
    public class GoogleBooks
    {

        public class IndustryIdentifier
        {
            public string type { get; set; }
            public string identifier { get; set; }
        }

        public class ReadingModes
        {
            public bool text { get; set; }
            public bool image { get; set; }
        }

        public class ImageLinks
        {
            public string smallThumbnail { get; set; }
            public string thumbnail { get; set; }
        }

        public class PanelizationSummary
        {
            public bool containsEpubBubbles { get; set; }
            public bool containsImageBubbles { get; set; }
        }

        public class VolumeInfo
        {
            public string title { get; set; }
            public List<string> authors { get; set; }
            public string publishedDate { get; set; }
            public string description { get; set; }
            public List<IndustryIdentifier> industryIdentifiers { get; set; }
            public ReadingModes readingModes { get; set; }
            public int pageCount { get; set; }
            public string printType { get; set; }
            public string maturityRating { get; set; }
            public bool allowAnonLogging { get; set; }
            public string contentVersion { get; set; }
            public ImageLinks imageLinks { get; set; }
            public string language { get; set; }
            public string previewLink { get; set; }
            public string infoLink { get; set; }
            public string canonicalVolumeLink { get; set; }
            public string subtitle { get; set; }
            public string publisher { get; set; }
            public List<string> categories { get; set; }
            public PanelizationSummary panelizationSummary { get; set; }
        }

        public class ListPrice
        {
            public double amount { get; set; }
            public string currencyCode { get; set; }
        }

        public class RetailPrice
        {
            public double amount { get; set; }
            public string currencyCode { get; set; }
        }

        public class ListPrice2
        {
            public double amountInMicros { get; set; }
            public string currencyCode { get; set; }
        }

        public class RetailPrice2
        {
            public double amountInMicros { get; set; }
            public string currencyCode { get; set; }
        }

        public class Offer
        {
            public int finskyOfferType { get; set; }
            public ListPrice2 listPrice { get; set; }
            public RetailPrice2 retailPrice { get; set; }
        }

        public class SaleInfo
        {
            public string country { get; set; }
            public string saleability { get; set; }
            public bool isEbook { get; set; }
            public ListPrice listPrice { get; set; }
            public RetailPrice retailPrice { get; set; }
            public string buyLink { get; set; }
            public List<Offer> offers { get; set; }
        }

        public class Epub
        {
            public bool isAvailable { get; set; }
            public string acsTokenLink { get; set; }
        }

        public class Pdf
        {
            public bool isAvailable { get; set; }
            public string acsTokenLink { get; set; }
        }

        public class AccessInfo
        {
            public string country { get; set; }
            public string viewability { get; set; }
            public bool embeddable { get; set; }
            public bool publicDomain { get; set; }
            public string textToSpeechPermission { get; set; }
            public Epub epub { get; set; }
            public Pdf pdf { get; set; }
            public string webReaderLink { get; set; }
            public string accessViewStatus { get; set; }
            public bool quoteSharingAllowed { get; set; }
        }

        public class SearchInfo
        {
            public string textSnippet { get; set; }
        }

        public class Item
        {
            public string kind { get; set; }
            public string id { get; set; }
            public string etag { get; set; }
            public string selfLink { get; set; }
            public VolumeInfo volumeInfo { get; set; }
            public SaleInfo saleInfo { get; set; }
            public AccessInfo accessInfo { get; set; }
            public SearchInfo searchInfo { get; set; }
        }

        public class RootObject
        {
            public string kind { get; set; }
            public int totalItems { get; set; }
            public List<Item> items { get; set; }
        }
    }
}
```

これで、受信データ（JSON）を変換することで、オブジェクトとして扱うことが出来ます。




##送信データ処理
こちらも、別クラスを作って処理を行います。


```Models\GoogleBooks\GoogleBooksApi.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks;

namespace sample2_1.Models.GoogleBooks
{
    public class GoogleBooksApi
    {
        public static async Task<GoogleBooks.RootObject> GetGoogleBooks(string s_word)
        {
            // 返却用オブジェクト
            GoogleBooks.RootObject rootObject = new GoogleBooks.RootObject();

            using (HttpClient client = new HttpClient())
            {
                var parameters = new Dictionary<string, string>()
                {
                    { "q", s_word },
                    { "Country", "JP" },
                    { "maxResults", "30" }
                };
                // パラメータつけてGET
                HttpResponseMessage response = await client.GetAsync($"https://www.googleapis.com/books/v1/volumes?{await new FormUrlEncodedContent(parameters).ReadAsStringAsync()}");
                response.EnsureSuccessStatusCode();
                // 返却値をJSONからクラスへ変換
                var serializer = new DataContractJsonSerializer(typeof(GoogleBooks.RootObject));
                rootObject = (GoogleBooks.RootObject)serializer.ReadObject(await response.Content.ReadAsStreamAsync());
            }
            // 出来たオブジェクトを変換
            return rootObject;
        }
    }
}
```

##Controllerへ実装

上記で作ったメソッドを呼び出すだけですね。
簡単簡単。

```Controllers\WorkController.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Drawing;
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

using sample2_1.Models;
using sample2_1.Models.Const;
using sample2_1.Models.Interface;
using sample2_1.Models.GoogleVision;
using sample2_1.Models.GoogleBooks;

namespace sample2_1.Controllers
{
    public class WorkController : Controller
    {
        // AmazonS3 インターフェイス
        private static IAmazonS3 client;

        public IActionResult Index()
        {
            -略-
        }

        [HttpPost("UploadFiles")]
        public async Task<IActionResult> FileUpload(List<IFormFile> files)
        {
            -略-
        }

        // S3 ストレージへアップロード！
        static async Task WritingAnObjectAsync(string s_upd_file_nm)
        {
            -略-
        }

        //asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_6.分割画面→Canvasオブジェクト- 追加
        public IActionResult Canvas()
        {
            -略-
        }


        [HttpPost]
        //FormからJsonを受け取り、クラス変換してくれます。
        public string Cut([FromBody]CutData cutData)
        {
            // 1.Imageへ画面に表示している画像ファイルを読み込み
            System.Drawing.Image image = null;
            try
            {
                image = System.Drawing.Image.FromFile(@"C:\work\work.jpg");
            }
            catch (Exception e)
            {
                throw e;
            }

            // 2.Bitmapに範囲指定したサイズを設定
            Bitmap destbmp = new Bitmap((int)cutData.width, (int)cutData.height);
            // 3.Graphicsに読み込ませるBitmapを設定
            Graphics graphics = Graphics.FromImage(destbmp);
            // 4.[1]でロードした画像を描画
            graphics.DrawImage(image, (cutData.x * -1) , (cutData.y * -1), image.Size.Width, image.Size.Height);
            // 5.保存先の指定
            var stream = new FileStream(@"C:\work\cutter.jpg", FileMode.Create);
            // 6.保存処理
            destbmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
            // 7.後処理
            stream.Close();

            // 8.Google Vision API 認証準備
            GCPVisonAPI ocr = new GCPVisonAPI();
            // 9.戻り値stringの変数作成、画像をByteArrayで開く
            string getText = "";
            byte[] imageArray = System.IO.File.ReadAllBytes(@"C:\work\cutter.jpg");
            // 10.Google Vision APIの実行
            ocr.getTextAndRoi(imageArray, ref getText);


            // 11.Google Books APIのパラメータ作成
            GoogleBooks.RootObject rootObject = GoogleBooksApi.GetGoogleBooks(getText).Result;
            // 12.検索結果の書籍名+著者名を返却する
            string s_res = "";
            foreach (var item in rootObject.items)
            {
                // タイトルの取得
                s_res = item.volumeInfo.title;
                s_res += " / ";

                // 作者名を取得
                var cnt = 0;
                foreach (string s_author in item.volumeInfo.authors)
                {
                    if (cnt != 0)
                    {
                        s_res += ",";
                    }
                    s_res += s_author;
                    cnt++;
                }
                // 1件目で終了！
                break;
            }

            // 検索結果の書籍名+著者名を返却する
            return s_res;

            // 受けとった文字列を返却
            //return getText;

            // 受け取ったheightプロパティを画面に返す。
            //return @"正常にCut出来ました！";
        }
    }
}
```


##デバッグ実行！

前回同様、「生命と環境の化学」を選択して、Enter！ターンッ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/27bf56ab-89f9-9577-ce62-551a388361c3.png)

↓　結果　↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/369a2f4a-81e8-82f0-961b-094fb4ab3c64.png)

「基礎から学ぶ生命・環境の化学　/　三浦洋四郎,船越浩海,岡崎三代」

ん？合ってるの？

GoogleBooksで実際に見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/7b48a0c9-56c6-1087-d830-658d591bda8d.png)


一応合ってるっぽい！良かった！

##最後に

これで、一通り実装は完了です。
簡単なアプリケーションなら作れそうな気がしませんか？
是非、色々遊んでみてください。

開発編は一旦ここまで。
ネタはあるのですが、ありきたりな話なので、また時間がある時に・・・。
ちなみにこんな感じを想定

asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_9.分割処理 DB登録-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_10.本一覧画面 DB検索-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_11.本一覧画面 ページング-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_12.本詳細画面-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_13.本修正画面→Google Books API検索-

ページングはそこそこ苦労しました。
未だに0件対応ちゃんとやってないし。。。

これからTanaToruの改修をもろもろやりきったら、また更新します。
次の予定は、サーバデプロイ編。
乞うご期待。

---

【是非お試しください】※完全無料です
TanaToru -本棚管理サービス-
　https://app.zero-one-system.co.jp/TanaToru/