connpassの２つイベント間で重複する参加者を調べる

関連記事
[connpassのイベント参加者リストをcsv形式で取得し、重複する参加者を調べる](https://qiita.com/gx3n-inue/items/2577d379ca8ce6d8e8fb)

にて、connpassイベントの参加者一覧をcsvファイルに出力したり、出力したcsvファイルを比較して重複する参加者を出力する処理を紹介しましたが、

csvファイルに保存せずに、２つのイベントの参加者一覧および重複ユーザーをそのまま出力する処理を作成してみました。

GitHub上のソースへのリンク
　[get_participant_duplicates.py](https://github.com/NobuyukiInoue/get_connpass_participants/blob/master/get_participant_duplicates.py)

スクレイピング処理に関しての留意事項
・**[Webスクレイピングの注意事項一覧](https://qiita.com/nezuq/items/c5e827e1827e7cb29011)**
・**[connpass利用規約](https://connpass.com/term/)**


##1. ２つのイベントの参加者一覧および重複ユーザーの取得方法

HTMLのparse処理に`beautifulsoup4`を使用しています。

管理者権限で`pip install beautifulsoup4`コマンドを実行し、事前にインストールしておいてください。

コマンドの実行方法は、以下のとおりです。
それぞれのイベントの参加者一覧が表示されたあと、重複する参加者が出力されます。

```
$ python ./get_participant_duplicates.py https://グループ名１.connpass.com/event/イベントID/ https://グループ名２.connpass.com/event/イベントID/
```

もしくは、

```
$ chmod u+x get_participant_duplicates.py
$ ./get_participant_duplicates.py https://グループ名１.connpass.com/event/イベントID/ https://グループ名２.connpass.com/event/イベントID/

```


##2. ソース

MS-Windows環境では、１行目は削除し、２行目は`# coding: cp932`に置き換えると良いと思います。

一般的なWebスクレイピングの手順なので、詳細な解説は割愛させていただこうと思います。

```Python:get_participant_duplicates.py
#!/usr/bin/env python
# coding: utf-8

import sys
import urllib.request
import urllib.error
from bs4 import BeautifulSoup


def print_arg_error(commandName):
    """引数エラー時のメッセージ出力"""
    print("Usage: python {cmd} connpassURL1 connpassURL2\n"
          "\n"
          "example)\n"
          "python {cmd} https://GROUP_A.connpass.com/event/xxxxx/"
                      " https://GROUP_B.connpass.com/event/yyyyy/"
          .format(cmd=commandName))
    exit(0)


def is_url(url):
    """URL書式チェック"""
    return url.startswith("https://") or url.startswith("http://")


def participation_url(url):
    """参加者URLに変換"""
    if url.endswith("/participation/"):
        return url
    if url.endswith("/participation"):
        return url + "/"
    if url.endswith("/"):
        return url + "participation/"
    else:
        return url + "/participation/"


def users(tags):
    """ユーザー情報の取得(ユーザ名とユーザURLのCSV形式)"""
    for tag in tags:
        try:
            if tag.text and tag.text != "\n\n":
                href = tag['href']
                if "/open/" in href or "/user/" in href:
                    yield '"{name}","{url}"\n'.format(name=tag.text, url=href)
        except:
            pass


def getDuplicateUsers(users1, users2):
    """２つのcsv配列を比較し、profile URLが一致するレコードを出力する"""
    urls2 = {user2.split(",")[1] for user2 in users2}
    for user1 in users1:
        name1, url1 = user1.split(",")
        if url1 in urls2:
            yield user1


class Connpass:
    """Compassイベント参加者情報"""

    def __init__(self, url):
        self.url = participation_url(url)
        html = urllib.request.urlopen(self.url)
        soup = BeautifulSoup(html, "html.parser")
        tags = soup.find_all("a")
        self.users = list(users(tags))

    def show_users(self):
        """抽出した参加者リストを標準出力に表示する"""
        print("\n===== %s ==== " % self.url)
        for user in self.users:
            print(user, end="")


def main():

    # URL Format
    # "https://xxxxxx.connpass.com/event/xxxxx/"

    cmd, *args = sys.argv
    argc = len(args)
    if argc != 2:
        print_arg_error(cmd)
    url1, url2 = args

    if not is_url(url1) or not is_url(url2):
        print_arg_error(cmd)

    connpass1 = Connpass(url1)
    connpass2 = Connpass(url2)

    connpass1.show_users()
    connpass2.show_users()

    # 重複するユーザーを表示する
    print("\n===== Duplicate Users ==== ")
    for user in getDuplicateUsers(connpass1.users, connpass2.users):
        print(user, end="")
    print()

if __name__ == "__main__":
    main()
```