NETWORK APPS

Pythonでネットワークアプリを作る|API・スクレイピング・ソケット通信の完成コード13本

APIからデータを取る、Webページを読む、LANの中で会話する。通信を使うデスクトップアプリでつまずくのは、画面の作り方より「待ち時間」と「相手のルール」の扱いです。当サイトの完成コード13本を通信の種類ごとに読み比べ、どれから作るかを決められるようにまとめました。

🎯 対象: tkinterの基本が書ける中級手前〜中級 ⏱️ 読了: 約13分 🌐 収録: 通信を使うアプリ13本(完成コード付き)

1. 結論:APIなら為替、Web取得ならスクレイピングツール、仕組みならチャット

13本のコードを読み比べると、画面を固めない書き方は共通で、違いは通信の相手でした。分割幅の上限超えやAPIの移転など、コードを読んで見つけた注意点は各節に書いています。

✅
目的別の最初の1本

APIからデータを取りたい → 為替レートウィジェット(253行・★★☆)。標準ライブラリだけで動き、APIキーも不要です。
Webページから情報を抜き出したい → Webスクレイピングツール(420行・★★★)。robots.txtの確認とアクセス間隔の調整が入っています。
通信の仕組みを知りたい → チャットアプリ(332行・★★★)。1台のPCでサーバーとクライアントの両方を試せます。

LANを調べる2本は、自分の機器専用の道具です。使う前に§8を読んでください。

2. 13本の早見表

ネットワーク越しにデータをやり取りする当サイトの中級アプリから13本を選びました。行数は配布している.pyの実際の行数(空行・コメント込み)です。

アプリ通信の種類主な部品行数難易度コード
為替レートウィジェットHTTP(API・urllib)Treeview/Combobox253★★☆app067.py
多言語翻訳ツールHTTP(API・urllib)Text×2/Combobox242★★☆app065.py
GitHub APIビューアHTTP(API・requests)Treeview/Text287★★★app061.py
REST APIテスターHTTP(任意のAPI・urllib)Notebook/Text287★★☆app028.py
APIテストクライアントHTTP(任意のAPI・urllib)Notebook/Listbox263★★☆app064.py
WebスクレイピングツールHTTP(requests+BeautifulSoup)Radiobutton/Listbox420★★★app068.py
Webスクレイパー UIHTTP(urllib・BeautifulSoupは任意)Radiobutton/Treeview327★★☆app034.py
Webページ監視ツールHTTP(urllib+hashlib)Treeview/Text239★★★app063.py
チャットアプリTCPソケット(独自の送受信ルール)Text/Listbox332★★★app017.py
メールクライアントIMAP(受信)+SMTP(送信)Notebook/Treeview496★★★app040.py
FTPクライアントFTPTreeview×2452★★★app039.py
ネットワークスキャナーping(外部コマンド)+TCPTreeview/Progressbar335★★☆app013.py
ポートスキャナーTCP接続の可否Treeview/Spinbox246★★★app066.py

動作確認の範囲は、12本がWindows 11(実機)で起動と基本操作、Linux Mint 22.3(仮想マシン)で起動と画面表示までです。ネットワークスキャナーは両OSで起動と画面表示を確認しただけで、スキャンは実行していません。macOSは未検証です。

3. 共通の土台:待つ処理はスレッドへ

urlopen()は相手が返事をするまで戻らず、recv()はデータが届くまで止まります。これをボタンの処理の中で呼ぶと、tkinterが画面を描き直せず「応答なし」になります。

13本はすべて、通信する関数をthreading.Thread(..., daemon=True)で別スレッドに出し、結果をroot.after(0, 表示用の関数, 結果)で画面側へ渡しています。queue.Queueを使う受け渡し方はtkinterが固まるときの直し方で勧めています。

例外として、チャットアプリの接続・メールクライアントの削除・FTPクライアントの削除とフォルダ作成・ネットワークスキャナーのホスト名解決の4か所は、メインスレッドで通信しています。相手が応答しないとタイムアウトまで画面が止まるため、最初の改造課題に向きます。

4. HTTPでAPIを呼ぶ:urllib.request と requests

API系の5本のうち4本は標準ライブラリのurllib.request、1本はrequestsを使います。

urllib.requestrequests
インストール不要pip install requests
クエリ文字列urlencode()で組み立てるparams=に辞書を渡す
JSONの読み込みjson.loads(resp.read().decode())resp.json()
4xx・5xxHTTPError例外になるraise_for_status()で例外にする

GETを数種類送るだけならurllib.requestで足り、配る相手にpipを頼まずに済みます。認証やページ送りが何度も出るならrequestsが短く書けます(ライブラリ一覧)。

為替レートウィジェット(253行・★★☆)

12通貨を扱い、基準通貨に対するほかの11通貨のレートを表に並べ、換算電卓で金額を変換します。取得したレートはすべて「基準通貨1単位あたり」なので、ドルからユーロへの換算も金額 ÷ 元通貨のレート × 換算先のレートと基準通貨を経由して求めます。完成コード(app067.py)

コードの接続先https://api.frankfurter.appは、2026年11月4日の確認でhttps://api.frankfurter.dev/v1へ恒久的に転送(301)されていました。urllib.requestは転送を自動でたどりますが、API_BASEは新しいアドレスに書き換えておくのが確実です。データは欧州中央銀行のもので更新は1日1回のため、「1分おきに自動更新」をオンにしても同じ日のうちは値が変わりません。表の「前日比」列はコード上いつも空欄で、埋める改造が手頃な練習になります。

多言語翻訳ツール(242行・★★☆)

12言語の間で文章を翻訳し、結果を履歴に残します。長い入力は分割して1回ずつAPIに送り、最後につなげます。完成コード(app065.py)

注意点は分割の幅です。MyMemoryのAPIは1回に送る文章を500バイトまでとしていますが、コードは400文字ごとに区切ります。日本語はUTF-8で1文字3バイトのものが多く、400文字では500バイトを超えることがあるため、長文を訳すなら幅を150文字程度に縮めてください。入力した文章は外部サービスに送られるので、仕事の文書や個人情報は入れないでください。

GitHub APIビューア(287行・★★★)

ユーザー情報・リポジトリ一覧・検索・使用言語の集計の4モードで、GitHubの公開データを表示します。見どころはページ送りで、一覧は1回100件までしか返らないため、pageを増やして最大3回取得し、100件未満が返ったら打ち切ります。完成コード(app061.py)

公式ドキュメントでは、トークンなしは1時間に60回、個人用アクセストークンで認証すると5,000回が上限です。トークンはGitHubが推奨するfine-grained(権限を細かく選べる)方式で、読み取り権限だけにしてください。Token欄は伏せ字で、保存もされません。

REST APIテスター(287行・★★☆)とAPIテストクライアント(263行・★★☆)

どちらもURL・メソッド・ヘッダー・ボディを指定して送り、レスポンスを表示するツールです。作りがほぼ重なるので、1本で十分です。

  • REST APIテスター:サンプルが5件あり、選ぶだけでURLとボディが入ります。送信中はボタンが押せず、二重送信を防ぎます。完成コード(app028.py)
  • APIテストクライアント:認証方式(なし・Bearer・Basic)をラジオボタンで切り替えます(REST APIテスターは入力した欄の方式)。キャンセルは通信を止めず、結果を表示しないだけです。完成コード(app064.py)

共通の見どころはHTTPErrorの扱いで、404や500の例外からe.codeとe.read()で本文を取り出し、APIのエラーメッセージを画面に出します。相手に伝わるボディの形式は、ボディ欄の選択でなくヘッダー欄のContent-Typeで決まります。

5. Webページを読む:スクレイピングと変更の監視

スクレイピングのコードを書く前に、確認することが3つあります。

  • 利用規約:自動取得を禁止しているサイトでは行いません。規約はrobots.txtより優先します
  • robots.txt:取得してよいパスかを確認します。ただし標準仕様(RFC 9309)が「アクセスを許可する仕組みではない」と明記しており、禁止されていないことは取得してよい理由になりません
  • アクセス間隔:連続取得は数秒あけます

規約の調べ方は株価スクレイピングは禁止?規約とrobots.txtの確認方法で解説しています。

Webスクレイピングツール(420行・★★★)

Webスクレイピングツールの起動直後の画面(Windows)。URL欄に当サイトのlibraries.htmlが入り、右に「robots.txt を確認する」のチェックがオンになっている。その下にタイトル・リンク・見出しなど7つの抽出モード、左に抽出結果、右にHTMLソースの欄が並ぶ

上の3つをできる範囲でコードに組み込んだツールです。取得したHTMLから7通りの方法で抜き出し、CSVかJSONで保存できます。取得前にはrobots.txtを読み、禁止なら中止します(_check_robots()の後半の抜粋)。

    parser = urllib.robotparser.RobotFileParser()
    parser.set_url(robots_url)
    try:
        parser.read()
    except Exception as e:
        # 読めなかったときは「許可された」とみなさない
        return False, None, f"robots.txt を確認できませんでした({e})"
    if not parser.can_fetch(USER_AGENT, url):
        return False, None, "robots.txt が Disallow のため中止しました"
    delay = parser.crawl_delay(USER_AGENT)
    return True, delay, "robots.txt: 許可"

robots.txtを取りに行けなかったときに「取得しない」側へ倒しているのがポイントです。間隔は最低3秒で、Crawl-delayの指定があれば長いほうを待ちます。名乗りに使うUSER_AGENTは仮の値なので、自分のツール名と連絡先に書き換えてください。完成コード(app068.py)

Webスクレイパー UI(327行・★★☆)

BeautifulSoupが無くても動くスクレイパーです。importに失敗したら正規表現の簡易抽出に切り替わり、あれば6種類の抽出モードが使えます。完成コード(app034.py)

このアプリにはrobots.txtの確認もアクセス間隔の制御もありません。サンプルボタンのquotes.toscrape.comとbooks.toscrape.comはスクレイピング練習用に公開されているサイトなので、まずここで試し、ほかのサイトに向けるなら前述の3つを自分で確認してください。

Webページ監視ツール(239行・★★★)

登録したURLを決めた間隔で取りに行き、中身が変わったら通知します。判定は、取得した内容全体をhashlib.md5()で短い文字列(ハッシュ値)に変えて前回と比べるだけです。URLごとにafter()で次の確認を予約するので、複数のURLを同時に見張れます。完成コード(app063.py)

ページ全体を比べるため、表示時刻や広告がアクセスごとに変わるページでは毎回「変化あり」になります。間隔の下限は10秒ですが、他人のサイトなら分単位以上にしてください。最初は手元のフォルダでpython -m http.server 8000を実行し、既定のURL(http://127.0.0.1:8000/)を監視すれば外部に負荷をかけずに試せます。RSSがあるサイトならニュースフィードリーダーの方式が軽く済みます。

6. 通信の決まりを自分で作る:ソケットのチャット

チャットアプリの接続設定画面(Windows)。ニックネームに「ユーザー1」、ポートに55555が入り、「サーバーとして起動」ボタンがある。その下に接続先IPの欄(127.0.0.1)と「接続」ボタン

チャットアプリ(332行・★★★)は、HTTPなら規格が決めている送受信の決まりを自分で作る1本です。サーバーは受け取った発言を他の参加者に配ります。

TCPはデータを「バイトの流れ」として届けるので、2回の発言がまとめて届くことも、途中で切れて届くこともあります。そこでこのアプリは、発言をJSONのバイト列にし、先頭に「この後に何バイト続くか」を4バイトで付けて送ります。受け取る側は長さを読み、その分がそろうまで読み続けます(抜粋)。

def _send_raw(self, sock, data):
    raw = json.dumps(data, ensure_ascii=False).encode("utf-8")
    length = len(raw).to_bytes(4, "big")
    sock.sendall(length + raw)

def _recv_exactly(self, sock, n):
    data = b""
    while len(data) < n:
        chunk = sock.recv(n - len(data))
        if not chunk:
            return None
        data += chunk
    return data

recv()が空のバイト列を返したら、相手が切断した合図です。試すときは同じPCでアプリを2つ起動し、片方で「サーバーとして起動」、もう片方で127.0.0.1のまま「接続」します。通信は暗号化されず相手を確認する仕組みもないので、別のPCとつなぐのは信頼できるLANの中だけにしてください。

7. ログインが要る通信:メールとFTP

どちらのアプリも、パスワードは伏せ字の入力欄から受け取り、ファイルには保存しません。改造するときも、パスワードをコードやテキストファイルに書かないでください。

メールクライアント(496行・★★★)

IMAPでメールを読み、SMTPで送信します。一覧では差出人・件名などの見出しだけを取り、本文は選んだときに取りに行くので、件数が多くても一覧がすぐ出ます。完成コード(app040.py)

このアプリはパスワードでログインする作りです。Googleのヘルプ(2026年11月4日確認)によると、Gmailはユーザー名とパスワードを渡す方式の外部アプリをサポートしなくなっており、使うには「アプリパスワード」が要ります。これは2段階認証を有効にしたアカウントでしか作れず、職場や学校のアカウントなどでは作れない場合があります。Googleが案内する「Googleでログイン」(OAuth)には対応していません。

本文を表示したメールは、IMAPの仕様(RFC 3501)により既読になります。「削除」はexpunge()まで実行するのでサーバーから完全に消え、戻せません。試すのは自分宛てのテストメールだけにしてください。

FTPクライアント(452行・★★★)

左にローカル、右にサーバー側のファイル一覧を並べ、矢印ボタンでアップロード・ダウンロードします。サーバー側の一覧はLISTの結果を空白で区切って読んでおり、UNIX形式以外の一覧を返すサーバーではファイル名が並びません。完成コード(app039.py)

使っているftplib.FTPは、パスワードもファイルも暗号化せずに送るので、自分で用意した検証用サーバーで試してください。実際のサーバーへつなぐならftplib.FTP_TLSを使い、ログイン後にprot_p()を呼んでデータの通信も暗号化します。

8. LANを調べる:2つのスキャナー

⚠️
使ってよいのは自分が管理する機器・ネットワークだけ

不正アクセス禁止法が禁じる「不正アクセス行為」は、他人のIDやパスワードの無断入力や、ぜい弱性を突いてアクセス制限をすり抜ける行為です(不正アクセス行為の禁止等に関する法律第2条第4項)。ポートが開いているかを調べるだけの行為が、ただちにこれに当たるとは限りません。

ただし、ポートスキャンは攻撃の下調べに使われる手法でもあり、許可なく他人の機器に向ければ攻撃の準備とみなされたり、会社・学校・回線事業者の規約違反になったりしえます。相手の機器の動作を妨げれば、刑法の業務妨害の罪が問題になる可能性もあり、判断は状況で変わります。自宅のLANや自分のPC・サーバーにだけ使い、会社・学校・公共Wi-Fiでは管理者の許可なしに実行しないでください。本記事は法的助言ではありません。

ネットワークスキャナー(335行・★★☆)

指定した範囲(例:192.168.1.0/24)の各アドレスにpingを送り、応答した機器のIP・MACアドレス・ホスト名を一覧にします。範囲の展開はipaddress.ip_network()、pingはOSごとに引数を変えてsubprocessで実行し、MACアドレスはarp -aなどの出力から読み取ります。完成コード(app013.py)

範囲は起動時に自分のIPから自動で入り、そのまま押すと254台分を調べます。試すなら/29(6台分)のような狭い範囲からにしてください。「ポートスキャン」にチェックを入れると、見つかった機器ごとに15個のポートへの接続も試みます。MACアドレスは機器固有の値なので、結果を人に見せるときは伏せてください。

ポートスキャナー(246行・★★★)

ポートスキャナーの起動直後の画面(Windows)。ホスト欄は127.0.0.1、開始ポート1・終了ポート1024、タイムアウト200ミリ秒、並列数100。上部に「ローカルホストや自分が管理するサーバーのみにスキャンしてください」という注意書きがある

1台の機器について、指定した範囲のポートが開いているかを調べます。判定はsocket.connect_ex()の戻り値が0かどうかで、例外を使わずに成否が分かります。同時接続はthreading.Semaphoreで既定100に抑えています。完成コード(app066.py)

開いていたポートにはHEAD / HTTP/1.0という文字列を送り、返ってきた先頭128バイトの1行目を「バナー」として表示します。まずは127.0.0.1で、自分が起動したサービス(§5のhttp.serverなど)を見つけるところから試してください。なお、プリセットの「よく使うポート(Top20)」は、コード上は21個のポートを調べます。

9. 外部サービスの条件(2026年11月4日確認)

公式ページでの確認結果です(アプリの再実行はしていません)。使う前にリンク先で最新の条件を確かめてください。

サービス使うアプリキー確認結果
Frankfurter為替不要新アドレスへ転送。v1は非推奨だが提供継続と明記
MyMemory翻訳不要匿名1日5,000文字・1回500バイト
GitHub REST APIGitHub任意トークンなし60回/時
JSONPlaceholderAPIテスター不要書き込みは反映されない
httpbin.orgAPIテスター・スクレイパー不要1IPあたり約17回/秒(/postなど送信内容を返すものは2回/秒)。超えると429
toscrape.comスクレイパー不要練習用として公開中
Gmailメールアプリパスワード2段階認証が前提

10. まとめ

  • 13本の土台は共通で、待つ処理はスレッドへ、表示はafter()でメインへ
  • スクレイピングとスキャナーは、コードが動くことと、使ってよいことは別

次はAPIキーを使う天気予報アプリ、Pythonの無いPCで使うならEXE化のガイドへ。

11. よくある質問(FAQ)

Q. 追加でインストールするものはありますか?

11本は標準ライブラリだけで起動します。GitHub APIビューアはpip install requests、Webスクレイピングツールはpip install requests beautifulsoup4が必要です。任意で、Webスクレイパー UIはBeautifulSoup、Webページ監視ツールはplyer(OSの通知)を使えます。

Q. 通信を始めるとウィンドウが「応答なし」になります。

通信をボタンの処理の中で直接実行しているのが原因です。別スレッドで通信してください(§3・詳しい直し方)。

Q. ポートスキャナーを会社や学校のネットワークで使ってもよいですか?

管理者の許可なしには使わないでください。自分のPCだけに向けるつもりでも、組織のネットワークでスキャンの通信が流れれば、規約違反や攻撃の疑いとして扱われることがあります。試すなら自分のPCの127.0.0.1か自宅のLANにしてください(§8)。

本記事は、生成AIを活用して下書きし、運営者が内容を確認・編集したうえで公開しています。AIの利用方針は免責事項をご覧ください。