Advent Calendarで組織内部でいいねを押しあっている選手権（コードのみ）

# はじめに

さてさて、Advent Calendarもひとしきり盛り上がり、個人的にも[VIP](https://qiita.com/peisuke/items/80984db8b47cd8243019)とか[株AI](https://qiita.com/peisuke/items/f836aa245eb54b703cee)とかバズったし楽しめた１ヶ月でした。全然バズらなかったけど、本当は[社員2vec](https://qiita.com/peisuke/items/05e2c0fa4c77ab993205)が一番気に入ってるんだけどね。仕事も収まったので、一人ハイボールを飲みながら次のネタを考えつつ、記事を書いています。

いつもは機械学習とかコンピュータビジョンを中心に活動しているけど、たまにはこういったプログラミングを始めたときの純粋なノリで、好きなものを作るのは良いものだ。

・
・
・

そんな綺麗にはAdvent Calendarを終わらせない、最後に禍根を残すスタイルで行ってみようと思います。

Advent Calenarでは「いいね」の順位が付いており、やはり上位の企業は嬉しいものだし目立つもの。でも、皆思わない？

**「ていうか、自分でいいね押し合ってない？」**

本日は、そんな「いいね」押し合いをしている会社を探しに行ってみようと思います。悪ノリの記事なので、気分を害された方は、この辺でページを閉じることをオススメします。

# やってみよう！

## 会社情報の抽出

Qiita APIで取ってくることは出来ないようなので、スクレイピングで取ってきます。アドベントカレンダーに参加している企業は下記のように取ってこれるみたい。

```python
# アドベントカレンダーに参加している会社リストの取得
ret = requests.get('https://qiita.com/advent-calendar/2019/categories/company')

soup = bs4.BeautifulSoup(ret.text, "html.parser")
companies = soup.find_all("a", class_="ac-Item_name")
companies = [{'name': c.text.strip(), 'href': c['href']} for c in companies]
```

次に企業内でQiita向けに書いた記事リストを取ってきます。外部向けに記事を書いている場合はユーザIDのみを保存します。

```python

ret = requests.get('https://qiita.com' + company['href'])

soup = bs4.BeautifulSoup(ret.text, "html.parser")
contents = soup.find_all("div", class_="adventCalendarItem")

data = []
for content in contents:
    d = {}
    author = content.find("a", class_='adventCalendarItem_author')
    user_name = author['href'][1:]

    d['user'] = user_name
    entry = content.find("div", class_="adventCalendarItem_entry")
    if entry is not None:
        item = entry.find('a')
        if item is not None and 'https://qiita.com' in item['href']:
            d['href'] = item['href']
            d['title'] = item.text.strip()
    data.append(d)

target_list.append({'name': company['name'], 'items': data})
```

## いいねの抽出

Qiita APIを使って「いいね」をしているユーザを取ってこよう。最初に記事の総いいね数を取ってきて、その上でページを指定して「いいね」をしているユーザIDを抽出します。TOKENは右上にある自分のアイコンをクリック、設定➝アプリケーション➝個人用アクセストークンで発行できます。

```python

def get_likes(content_id, token):
    headers = {'Authorization': f'Bearer {token}'}
    per_page = 100
    
    ret = requests.get(f'https://qiita.com/api/v2/items/{content_id}', headers=headers)
    if ret.status_code != 200:
        print(f'https://qiita.com/api/v2/items/{content_id}')
        raise requests.ConnectionError("Expected status code 200, but got {}".format(ret.status_code))
    likes_count = json.loads(ret.content.decode('utf-8'))['likes_count']
    nb_pages = math.ceil(likes_count / per_page)
    #time.sleep(3)
    
    likes = []
    for p in range(nb_pages):
        params = {'page': 1 + p, 'per_page': per_page}
        ret = requests.get(f'https://qiita.com/api/v2/items/{content_id}/likes', params=params, headers=headers)
        if ret.status_code != 200:
            raise requests.ConnectionError("Expected status code 200, but got {}".format(ret.status_code))
        likes.extend(json.loads(ret.content.decode('utf-8')))
        #time.sleep(3)
        
    return likes
```

ここで、問題発生。Qiita APIはなんと1時間に1000回しか呼び出せないらしい。なのでスクレイピングで取ってくることにする。URLを入力して、各ページから「いいね」をしているユーザを取ってきます。

```python

def get_likes_direct(url):
    page = 1
    likes = []
    while True:
        ret = requests.get(f'{url}/likers?page={page}')
        soup = bs4.BeautifulSoup(ret.text, "html.parser")
        users = soup.find_all("li", class_="GridList__user")
        local_likes = []
        if users is not None:
            local_likes = [u.find('h4', class_='UserInfo__name').find('a')['href'][1:] for u in users]
        if len(local_likes) == 0:
            break
        local_likes = [{'user': {'id': ll}} for ll in local_likes]
        likes.extend(local_likes)
        page += 1
    return likes
```

## 順位の計算

さて、ここが一番悩んだ所ですが、悩んだ結果難しいこと考えずに、以下のようにしました。

- 組織内の記事に「いいね」をつけたユーザのうち、1/4以上の記事に「いいね」を付けた人を抽出
- 組織内のQiita記事数が5本を超えている場合のみを対象とする

例えば、組織の記事が8本あり、うち2本を超えて「いいね」を付けたら、一旦は組織内「いいね」とみなすことにしました。厳密には、その人が別組織でどの位「いいね」を付けてるかも見ないといけないんだけど、1/4の割合で記事に「いいね」を付けまくっている人は、早々いないので、まずはこの条件としました。

# 結果発表！

すみません、皆さん興味あるかと思いますが、流石に公表するのは良くないので、[ここ](https://github.com/peisuke/qiita_like_analysis)にコードを置いておくので実施してみて下さい。以下はとても重要な事だけど**手を動かす者だけが結果を得られるのです。**

なお、ABEJAは内部いいね順位は27位でした。それでは、良いお年を！