Swift GoogleBook APIで書籍検索

作業フロー

1-エンドポイントの調査

2-API Keyの取得

3-jsonデータの分析

4-コード作成

5-iOSにてView作成

1-エンドポイント、(接続するアドレス)はここに記載されている

https://developers.google.com/books/docs/v1/using

具体的にはここ

https://www.googleapis.com/books/v1/volumes?q=flowers+inauthor:keyes&key=yourAPIKey

&keyのkey部分へ自分のキーを配置する

2-keyを取得してエンドポイントへアクセスする。するとこの様なデータが帰ってきた。
これを解析する。 今回はここに時間をかける。

{
 "kind": "books#volumes",
 "totalItems": 100,
 "items": [
  {
   "kind": "books#volume",
   "id": "_oG_iTxP1pIC",
   "etag": "fPjIOwmEaME",
   "selfLink": "https://www.googleapis.com/books/v1/volumes/_oG_iTxP1pIC",
   "volumeInfo": {
    "title": "Flowers for Algernon",
    "authors": [
     "Daniel Keyes"
    ],
    "publisher": "Houghton Mifflin Harcourt",
    "publishedDate": "2007-12-01",
    "description": "The beloved, classic story of a mentally disabled man whose experimental quest for intelligence mirrors that of Algernon, an extraordinary lab mouse.",
    "industryIdentifiers": [
     {
      "type": "ISBN_10",
      "identifier": "0547539630"
     },
     {
      "type": "ISBN_13",
      "identifier": "9780547539638"
     }
    ],
    "readingModes": {
     "text": true,
     "image": true
    },
    "pageCount": 304,
    "printType": "BOOK",
    "categories": [
     "Fiction"
    ],
    "averageRating": 4.0,
    "ratingsCount": 165,
    "maturityRating": "NOT_MATURE",
    "allowAnonLogging": true,
    "contentVersion": "1.11.9.0.preview.3",
    "panelizationSummary": {
     "containsEpubBubbles": false,
     "containsImageBubbles": false
    },
    "imageLinks": {
     "smallThumbnail": "http://books.google.com/books/content?id=_oG_iTxP1pIC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
     "thumbnail": "http://books.google.com/books/content?id=_oG_iTxP1pIC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
    },
    "language": "en",
    "previewLink": "http://books.google.co.th/books?id=_oG_iTxP1pIC&pg=PA225&dq=flowers+inauthor:keyes&hl=&cd=1&source=gbs_api",
    "infoLink": "https://play.google.com/store/books/details?id=_oG_iTxP1pIC&source=gbs_api",
    "canonicalVolumeLink": "https://market.android.com/details?id=book-_oG_iTxP1pIC"
   },
   "saleInfo": {
    "country": "TH",
    "saleability": "FOR_SALE",
    "isEbook": true,
    "listPrice": {
     "amount": 422.28,
     "currencyCode": "THB"
    },
    "retailPrice": {
     "amount": 292.6,
     "currencyCode": "THB"
    },
    "buyLink": "https://play.google.com/store/books/details?id=_oG_iTxP1pIC&rdid=book-_oG_iTxP1pIC&rdot=1&source=gbs_api",
    "offers": [
     {
      "finskyOfferType": 1,
      "listPrice": {
       "amountInMicros": 4.2228E8,
       "currencyCode": "THB"
      },
      "retailPrice": {
       "amountInMicros": 2.926E8,
       "currencyCode": "THB"
      }
     }
    ]
   },

まず例題を考える-参照元

Working with JSON in Swift - Swift Blog - Apple Developer

この様なレストランから返却されたデータがあるとする

{
    "name": "Caffè Macs",
    "coordinates": {
        "lat": 37.330576,
        "lng": -122.029739
    },
    "meals": ["breakfast", "lunch", "dinner"]
}

クラスの実装はこう

import Foundation

struct Restaurant {
        //列挙体で、朝食、昼食、夕食をプロパティで持たせている
    enum Meal: String {
        case breakfast, lunch, dinner
    }
      
    let name: String
    let location: (latitude: Double, longitude: Double)
    //ここは上記mealsが3つ値を持っているので、列挙体をセットしている。
        let meals: Set<Meal>
}

構造体のextension こうすることで変数などプロパティを利用できるままで、機能を追加できる。 JSON表現からRestaurantオブジェクトに変換するには、JSON表現のデータを抽出してプロパティに変換するAny引数をとる初期化子を記述する。

extension Restaurant {
        //初期化
    init?(json: [String: Any]) {
                 //guard節 nilのときに{以下が実行される
        guard let name = json["name"] as? String,
            let coordinatesJSON = json["coordinates"] as? [String: Double],
            let latitude = coordinatesJSON["lat"],
            let longitude = coordinatesJSON["lng"],
            let mealsJSON = json["meals"] as? [String]
        else {
            return nil
        }

        var meals: Set<Meal> = []
        for string in mealsJSON {
            guard let meal = Meal(rawValue: string) else {
                return nil
            }

            meals.insert(meal)
        }

        self.name = name
        self.coordinates = (latitude, longitude)
        self.meals = meals
    }
}

Pyton3 cloud9 環境設定 |未完|

cloud9のpythonバージョンが2から3へ切り替わらない ここを参照、しかし問題は未解決。
Cloud9でpython3を動かす時にやっておきたいこと

pipとは

ピップと読むらしい。 パイソンのパッケージ管理ツール RailsのBundlerのようなものか。 またPyPI(パイピーアイ)というライブラリを集めたサイトがある。 Jupyter Notebookをインストールしておくとサンプルコードを追いやすくなる。

http://jupyter.org/install

そのためにAnacondaをインストールする。

https://www.anaconda.com/download/#macos

ec2-user:~/environment $ python --version Python 2.7.14 バージョンが2なので3へ変更 まずメニュー[Cloud9]→[Preferences]
f:id:happy_teeth_ago:20180816123801p:plain

which pythonでするとエイリアスだった。 よってpython3へエイリアスを設定。 python3のフォルダは以下

ec2-user:/usr/bin $ ls -l| grep python
lrwxrwxrwx   1 root root         24 Aug  7 13:11 python -> /etc/alternatives/python
lrwxrwxrwx   1 root root         17 Aug  7 13:11 python2 -> /usr/bin/python27
-rwxr-xr-x   1 root root       5120 May  2 18:32 python27
-rwxr-xr-x   1 root root       5120 May  2 18:32 python2.7
-rwxr-xr-x   1 root root       1846 May  2 18:31 python2.7-config
lrwxrwxrwx   1 root root         25 Aug  7 13:11 python3 -> /etc/alternatives/python3
-rwxr-xr-x   3 root root       6872 Apr 26 00:16 python36
-rwxr-xr-x   3 root root       6872 Apr 26 00:16 python3.6
lrwxrwxrwx   1 root root         17 Aug  7 13:11 python3.6-config -> python3.6m-config
-rwxr-xr-x   3 root root       6872 Apr 26 00:16 python3.6m
-rwxr-xr-x   1 root root        173 Apr 26 00:16 python3.6m-config
-rwxr-xr-x   1 root root       3373 Apr 25 23:57 python3.6m-x86_64

確認して

ec2-user:/usr/bin $ alias python='/etc/alternatives/python3'
ec2-user:/usr/bin $ python --version
Python 3.6.5

と思いきやpipのバージョンが違う

ec2-user:/usr/bin $ readlink -f /usr/bin/python
/usr/bin/python36
ec2-user:/usr/bin $ pip --version
pip 9.0.3 from /usr/lib/python2.7/dist-packages (python 2.7)
ec2-user:/usr/bin $ python3 --version
Python 3.6.5
ec2-user:/usr/bin $ pip3 --version
bash: pip3: command not found

pip3がないと言われているのでインストールしようと思ったが

AWS Cloud9でPython3を使う方法 のサイトによると

書き換え後はsourceコマンドをお忘れなく あとある。もうちょっと書いてくれると嬉しい sourceとは、環境設定フアイルをカスタマイズしたときには、現在のシェル環境に反映させるためのもの シェルファイルは.tcshrcなどrcの文字が最後についていることが多い。 ~/.bashrc のようである。

ec2-user:/usr/bin $ source ~/.bashrc
function

戻っているいみがわからない。

ec2-user:/usr/bin $ python --version
Python 2.7.14

今度はpython36にリンクを貼る

ec2-user:/usr/bin $ alias python='/usr/bin/python36'
ec2-user:/usr/bin $ python --version
Python 3.6.5

sourceコマンドを実行するとバージョンが戻ってしまう。??

ec2-user:/usr/bin $ source ~/.bashrc
function
ec2-user:/usr/bin $ python --version
Python 2.7.14

?? 今度はパスを指定せずにエイリアスを設定。 うまく行った。?? 理由がわかならいので、良くない。
どなたか理由教えていただけますか?

ec2-user:/usr/bin $ alias python=python36
ec2-user:/usr/bin $ python --version
Python 3.6.5

そしてどちらのバージョンを使うかを決めるコマンドを入力。

ec2-user:/usr/bin $ sudo update-alternatives --config python
ec2-user:/usr/bin $ pip --version
pip 9.0.3 from /usr/lib/python3.6/dist-packages (python 3.6)

モデルが詰まった機械学習パッケージをインストール

pip install scikit-learn

しかしエラー

Exception:
Traceback (most recent call last):
  File "/usr/lib/python3.6/dist-packages/pip/basecommand.py", line 215, in main
    status = self.run(options, args)
  File "/usr/lib/python3.6/dist-packages/pip/commands/install.py", line 342, in run

Rails 環境格闘記 !未完成!

Ignoring executable-hooks-1.4.2 because its extensions are not built. Try: gem pristine executable-hooks --version 1.4.2

このエラーが出る。 nokogirを指定の通り入れてもだめ。 この場合pathが通っていないことが多い よってgem の環境を確認.

 $ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 2.7.6
  - RUBY VERSION: 2.5.1 (2018-03-29 patchlevel 57) [x86_64-linux]
  - INSTALLATION DIRECTORY: /usr/local/rvm/gems/ruby-2.4.1
  - USER INSTALLATION DIRECTORY: /home/ec2-user/.gem/ruby/2.5.0
  - RUBY EXECUTABLE: /home/ec2-user/.rbenv/versions/2.5.1/bin/ruby
  - EXECUTABLE DIRECTORY: /usr/local/rvm/gems/ruby-2.4.1/bin
  - SPEC CACHE DIRECTORY: /home/ec2-user/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /home/ec2-user/.rbenv/versions/2.5.1/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-linux
  - GEM PATHS:
     - /usr/local/rvm/gems/ruby-2.4.1
     - /usr/local/rvm/gems/ruby-2.4.1@global
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000

rbenvで入れたのに実行環境がRVMになっている?? 再度rvmで入れることが可能なのか? このサイトを見ると不可能にちかい。というかエラーになること間違いない。

RVMからrbenvに移行した手順まとめ · GitHub rvmインストールしていないのだから、pathをrbenvに向けてあげればいいだけ。 以下明日に続く

Swift httpsサイトへ接続設定

infoPolistへ以下を追加

f:id:happy_teeth_ago:20180810202014p:plain

App Transport Security Settings

を入力して三角マークが出ている同じ行でプラスボタン押すのがポイント

Allow Arbitrary Loadsを更に入力。

しかしシミュレーターがアマゾンへ接続できない。

他のサイトならできるのに。?? f:id:happy_teeth_ago:20180810204958p:plain

アバストセキュリティーが邪魔してた。

ここから

f:id:happy_teeth_ago:20180810205148p:plain

WEBシールドを無効化する。

f:id:happy_teeth_ago:20180810205210p:plain

Swift AmazonAPI !書きかけ読まないこと!

Amazon APIへ接続して、データ表示というところを実装したい。 まず

アソシエイトタグ

アクセスキー

シークレットキー

が必要。これについては、他のブログを参照ください。

Swift3 モデルで渡す 忘備録

目的 別画面にイベントの一覧が表示されている。 そこに、テキストの文字列だけでなく、人物に紐付いたデータを渡したい。
理由
そこからECサイトにアクセスする際に、人物から表示するサイトのデータを変更したい。

クラスの作成 初期化も行う。 初期化するのでオプショナル型は必要ないが、人物だけは、データ持たない可能性もある。 そこでオプショナル型で宣言する。 初期化時には、nilを入れる。 swiftは一番最後の引数に初期値があるときは、引数を省略できるので、引数の最後にpersonを指定する。

   class EventToShow{
        var person:Person?
        var event:String
        var date:String
        
        init(date:String, event:String, person:Person? = nil){
            self.date = date
            self.event = event
            self.person = person
        }
    }

関数の戻り値をEventToShow型の配列にする。 classは型 初期化もしないといけない。

 static func searchEventperson(monthRange:Int) -> [EventToShow]

各関数の詰め込み時には、オブジェクトを作成し、渡してあげる。

 eventsToShows.append(EventToShow(date: dateFormater.string(from: eventdate!), event: birthdayEvent, person:person))

最後に日付順でソートして返してあげる。

   eventsToShows.sort(by: {$0.date < $1.date})
        print(eventsToShows)
        return eventsToShows

Swift3 API接続 !編集途中-読まないこと!

APIの接続についてまとめます。 ここがエンドポイントのようだ https://www.googleapis.com/calendar/v3/calendars/primary/events

ボタン押下時にエンドポイントのurlをget

 @IBAction func getSunrizeTime(_ sender: Any) {
        let url = "https://query.yahooapis.com/v1/public/yql?q=select%20astronomy.sunrise%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22\(cityNameInput.text!)%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
        getURL(url: url)
        
    }

取得するurlを別関数で切り出す。

   func getURL(url: String){
        do{
            let apiURL = URL(string: url)!
            let data = try Data(contentsOf: apiURL)
            let json = try JSONSerialization.jsonObject(with: data) as! [String:Any]
            print(json)
        }catch{
            self.sunTime.text = "can not connect"
        }
    }

ログの確認

["query": {
    count = 1;
    created = "2018-08-09T23:00:17Z";
    lang = "en-US";
    results =     {
        channel =         {
            astronomy =             {
                sunrise = "5:27 am";
            };
        };
    };
}]