70471
GitHubからAPIを通じてランダムにソースコードをダウンロードする方法について知りたいです。

[api.github.com/repositories?since=50000](https://api.github.com/repositories?since=50000)

上記のようにすればレポジトリまではランダムに特定できたような感じなのですが、  
なぜsinceというパラメータでランダムになるのかがわかりません。  
上記は登録不要のAPIを使っているようですが登録が必要なAPIを使っても構いません。  
また、レポジトリのライセンス、作者も取得したいです。  
よろしくお願いします。
CC BY-SA 4.0
2020-09-16T03:55:29.583
70430
2020-10-14T14:42:46.587
2020-09-28T11:52:24.667
3060
30511
question
github
GitHub からランダムにリポジトリを選択してソースコードをダウンロードしたい
すべて登録不要のAPIだけで可能です。

### ランダムにソースコードをダウンロードする方法

<https://api.github.com/repositories>  
で、100件ずつ取得できます。

`id` 順にソートされているので、この配列からランダムに要素を抽出すれば良いです。

`since` パラメータに与える数値を、ランダムに生成して  
クエリとして付けると、さらに良いと思います。

```

    html_url: "https://github.com/octocat/Hello-World",
    
```

のように、リポジトリのURLが入っているので  
この文字列を `git clone` に与えれば、ソースコードをダウンロードできます。

### レポジトリのライセンス、作者も取得したい

作者については、上記APIで返ってくる

```

      {
        "id": 1296269,
        "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
        "name": "Hello-World",
        "full_name": "octocat/Hello-World",
        "owner": {
          "login": "octocat",
          "id": 1,
          "node_id": "MDQ6VXNlcjE=",
          "avatar_url": "https://github.com/images/error/octocat_happy.gif",
          "gravatar_id": "",
          "url": "https://api.github.com/users/octocat",
          "html_url": "https://github.com/octocat",
    
```

の `owner` -> `login` の部分が該当します。  
作者ページのURLが必要ならば、`owner` -> `html_url` です。

  

ライセンスについては、上記APIだけでは取得できません。

上の例の場合、  
<https://api.github.com/repos/octocat/Hello-World>  
というAPIを2便目として投げれば、ライセンス情報の含まれたJSONが返ってきます。

このURLは、1便目である  
<https://api.github.com/repositories>  
の返すJSON内に、

```

        "url": "https://api.github.com/repos/octocat/Hello-World",
    
```

として含まれているので、それをそのまま使えます。

ちなみに、ライセンス情報はこんな感じで入っています。

```

        "license": {
          "key": "mit",
          "name": "MIT License",
          "spdx_id": "MIT",
          "url": "https://api.github.com/licenses/mit",
          "node_id": "MDc6TGljZW5zZW1pdA=="
        }
    
```

LICENSEファイルが置かれていないリポジトリの場合、

```

    license: null,
    
```

ですので、`name` キーが存在するとは限りません。  
nullチェックにご注意ください。

参考: <https://developer.github.com/v3/repos/>
CC BY-SA 4.0
2020-09-17T02:53:05.040
70471
2020-09-17T03:12:49.163
2020-09-17T03:12:49.163
41938
41938
70430
answer
railsのランナーでコードを持ってくるコードを載せておきます。  
ツッコミがあれば是非お願いします。  
テストしているうちにrate limitに到達してしまったため認証して使っています。  
Curbというgemを使っています。

```

    $ rails r CallGitHubApi.get
    
```

/lib/call_git_hub_api.rb

```

    class CallGitHubApi
        @@repo_num = 200000000
        @@user_agent = 'centos_rails'
        @@token = '*****'
        @@licenses = ['mit', 'apache-2.0', 'gpl-3.0']
        @@file_types = ['c', 'js', 'swift', 'py', 'cs', 'ts', 'cpp', 'go', 'java', 'php', 'rb']
        def self.get(url)
            http = Curl.get(url) |http|
                http.headers['User-Agent'] = @@user_agent
                http.headers['Authorization'] = 'token ' + @@token
            end
            json = JSON.load(http.body_str)
            return json
        end
        def self.get_code
            license = nil
            raw =nil
            while raw == nil do
                while license == nil do
                    license = nil
                    since = rand(@@repo_num)
                    puts 'get repo ' + since.to_s
                    json = get("https://api.github.com/repositories?since=#{since}")
                    if json[0]["private"] then
                        next
                    end
                    url = json[0]['url']
                    json = get(url)
                    if json['license'] != nil && 
                        @@licenses.include?(json['license']['key']) then
                        license = 'Free commercial'
                    end
                end
                puts 'end get repo'
                raw = find_file(url,true)
            end        
        end
        
        def self.find_file(url, first)
            if first then
                json = get("#{url}/contents")
            else
                json = get(url)
            end
            if json == nil then return nil end
            for content in json do
                if content == nil then return nil end
                if content[0] == "name" then
                    return nil
                end
       
                splite = content['name'].split(".")
                if splite.count <= 1 then
                    raw = find_file(content['url'], false)
                    if raw == nil then
                        next
                    end
                    return raw
                end
                if !@@file_types.include?(splite.last) then
                    next
                end
                puts content['url']
                http = Curl.get(content['download_url']) do |http|
                    http.headers['User-Agent'] = @@user_agent
                    http.headers['Authorization'] = 'token ' + @@token
                end
                raw = http.body_str
                return raw
            end
            return nil
        end
    end
    
```
CC BY-SA 4.0
2020-09-28T09:30:22.987
70781
2020-10-14T14:42:46.587
2020-10-14T14:42:46.587
30511
30511
70430
answer