Indeedパブリッシャープログラムを利用して、求人広告をapiで取得する


求人サイトIndeedでは、求人広告を掲載することによって報酬を得られる**Indeedパブリッシャープログラム**という施策を行っています。
今回は、公式のAPIを用いて求人情報を取得する方法について、実装例を交えて共有したいと思います。

# アカウントを登録する
まず、[Indeedパブリッシャープログラム](https://jp.indeed.com/publisher)にアクセスしてログインorアカウント登録しましょう。
<img width="1076" alt="スクリーンショット 2019-11-15 10.01.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334600/08397b95-565b-59c2-4ac5-810defbde98f.png">

# サンプルリクエストを実行する
登録できたら、[求人検索apiタブ](https://ads.indeed.com/jobroll/xmlfeed)を選択しましょう。求人情報を取得する**サンプルリクエスト**や、検索する際に用いるアカウント独自の**パブリッシャーID**の確認などができます。
<img width="782" alt="スクリーンショット 2019-11-16 13.14.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334600/87951a0c-520c-e088-db2d-3b03b20b0587.png">
<img width="1440" alt="スクリーンショット 2019-11-16 13.23.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334600/67ac4b21-daa1-0f05-9113-6ac1a6b6a548.png">


早速、上記のサンプルリクエストを参考に求人情報を取得してみましょう。
下記コードでは、キーワード(q)が「java」で勤務地(l)がaustinの求人を、緯度経度(latlong)情報とともに**xml形式**で取得しています。

```
サンプルリクエスト
url = "http://api.indeed.com/ads/apisearch?publisher=#{あなたのパブリッシャーID}&q=java&l=austin&sort=&radius=&st=&jt=&start=&limit=&fromage=&filter=&latlong=1&co=us&chnl=&userip=1.2.3.4&useragent=Mozilla/%2F4.0%28Firefox%29&v=2"
jobs = URI.parse(url).open(&:read)
```

# パラメータを設定して求人を取得する

次に、URLパラメータを操作して検索にオプションをつけてみましょう(サンプルリクエストの表↑参考)
求人検索では日本語でクエリを設定する場合が多いので、日本語を含むURIをparseできないRubyの標準URIクラスのために[Addressable::URI](https://github.com/sporkmonger/addressable)というgemを用いてurlをencodeしています↓

```
出力形式:json, キーワード:ゲーム, 場所:東京都から20km圏内, 求人上限件数:4 の場合
url = "http://api.indeed.com/ads/apisearch?publisher=#{あなたのパブリッシャーID}&format=json&q=ゲーム&l=東京都&radius=20&limit=4&co=jp&userip=1.2.3.4&useragent=Mozilla/%2F4.0%28Firefox%29&v=2"
jobs = URI.parse(Addressable::URI.encode(url)).open(&:read)
```

非同期処理では特にxml形式よりjson形式の方が扱い易いのでオススメです。
また、キーワード(クエリq)が複数ある場合は「+or+」で繋ぎましょう。

```
q=ゲーム+or+テレビ
```

# 様々なクエリで検索する
クエリを意味するURLパラメータ「p」には様々な値を入れることが出来ます。
具体的にどのような値が使えるかは[検索オプションページ](https://jp.indeed.com/advanced_search)で実際に値を入力して確認してみましょう。

```
企業名「Google」で検索する場合 => q=company:google
職種名「医師」で検索する場合 => q=title:医師
```
以上でIndeedの求人取得方法の説明は終わりです。


# 実装例
最後に、非同期で求人情報を取得するapiコントローラー例を示して終わりたいと思います。
アクセスした人の場所に近い求人を出すために、ipアドレスと場所のデータベースである[Geolite2](http://dev.maxmind.com/ja/geolite2/)と、それを読み込む[maxminddb](https://github.com/yhirose/maxminddb)というgemを利用して、ipアドレスからアクセス元を取得しています。



``` app/controllers/api/indeeds_controller.rb
require 'open-uri'
require 'addressable/uri'

class Api::IndeedsController < Api::ApplicationController
  def show
    query = 'ゲーム'
    city = IpToCity.convert(request.remote_ip) if request.remote_ip
    url = "http://api.indeed.com/ads/apisearch?publisher=#{PUBLISHER_ID}&format=json&q=#{query}&l=#{city}&limit=4&co=jp&userip=1.2.3.4&useragent=Mozilla/%2F4.0%28Firefox%29&v=2"
    jobs = URI.parse(Addressable::URI.encode(url)).open(&:read)
    render json: { jobs: JSON.parse(jobs) }, status: :ok
  end
end
```
```config/initializers/ip_to_city.rb
require 'singleton'

class IpToCity
  include Singleton
  CITY_DB = MaxMindDB.new('db/seeds/GeoLite2-City.mmdb')
  def self.convert(ip)
    ret = CITY_DB.lookup(ip)
    ret.found? ? ret.city.name(:ja) : '東京都'
  end
end
```

最後までご覧いただきありがとうございました！
何かご意見やアドバイスがあればご指摘していただけると幸いです。