Pythonタグ一覧

Pythonでwhois情報を検索できるpython-whoisを使う


Linuxだとwhoisコマンドでwhois情報を取得できるけれど私のパソコンはWindowsなのでそんな器用なことはできない。

そこでPythonでWhois検索できるpython-whoisライブラリがあったので使ってみたいと思う。

https://pypi.org/project/python-whois/

Whois検索する

ライブラリのバージョンは0.9.5。

検索するには

from whois import whois

print(whois("google.com"))

こんな感じで書く。

上記のgoogle.comだとこんな感じ。

{
"domain_name": "GOOGLE.COM",
"registrar": "MarkMonitor, Inc.",
"registrar_url": "http://www.markmonitor.com",
"reseller": null,
"whois_server": "whois.markmonitor.com",
"referral_url": null,
"updated_date": [
"2019-09-09 15:39:04",
"2024-08-02 02:17:33+00:00"
],
"creation_date": [
"1997-09-15 04:00:00",
"1997-09-15 07:00:00+00:00"
],
"expiration_date": [
"2028-09-14 04:00:00",
"2028-09-13 07:00:00+00:00"
],
"name_servers": [
"NS1.GOOGLE.COM",
"NS2.GOOGLE.COM",
"NS3.GOOGLE.COM",
"NS4.GOOGLE.COM"
],
"status": [
"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited",
"clientTransferProhibited https://icann.org/epp#clientTransferProhibited",
"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited",
"serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited",
"serverTransferProhibited https://icann.org/epp#serverTransferProhibited",
"serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited",
"clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)",
"clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)",
"clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)",
"serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)",
"serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)",
"serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)"
],
"emails": [
"abusecomplaints@markmonitor.com",
"whoisrequest@markmonitor.com"
],
"dnssec": "unsigned",
"name": null,
"org": "Google LLC",
"address": null,
"city": null,
"state": "CA",
"registrant_postal_code": null,
"country": "US"
}

ちゃんとレジストラやネームサーバーも取得できている。

前まではjpドメインはそのままでは使えなかったけど、最新バージョンで使えるようになっていた。

docomo.jpだとこんな感じ↓

{
"domain_name": "DOCOMO.JP",
"registrant_org": "NTT DOCOMO, INC.",
"organization_type": null,
"creation_date": "2001-03-26 00:00:00",
"technical_contact_name": null,
"administrative_contact_name": "NTT DOCOMO, INC.",
"administrative_contact_email": "domain-admin@nttdocomo.com",
"administrative_contact_phone": "03-5156-3721",
"administrative_contact_fax": null,
"administrative_contact_post_code": "100-6150",
"administrative_contact_postal_address": "Sanno Park Tower, 2-11-1, Nagata-cho, Chiyoda-ku, Tokyo",
"expiration_date": "2025-03-31 00:00:00",
"name_servers": "[Signing Key]",
"updated_date": "2024/07/01 17:41:41 (JST)",
"signing_key": null,
"status": "Active"
}

ネームサーバーが取得できてないけど一応、まともなデータは返ってくる。

docomo.ne.jpだと

{
"domain_name": "DOCOMO.NE.JP",
"registrant_org": null,
"organization_type": "Network Service",
"creation_date": null,
"technical_contact_name": "AG3600JP",
"administrative_contact_name": "AY30606JP",
"administrative_contact_email": null,
"administrative_contact_phone": null,
"administrative_contact_fax": null,
"administrative_contact_post_code": null,
"administrative_contact_postal_address": null,
"expiration_date": null,
"name_servers": [
"ns001.docomo.ne.jp",
"ns002.docomo.ne.jp"
],
"updated_date": "2024/12/05 16:48:55 (JST)",
"signing_key": null,
"status": "Connected (2025/07/31)"
}

こんな感じでネームサーバーは取得できるけどadministrative_contactがNullになっている。これはたぶんドメインによると思う。

あとne.jpやco.jpはちゃんと取得できたけど、or.jpやgo.jpなんかはエラーが出たのでそういったドメインの情報が欲しければライブラリを直すか別のライブラリを使った方がいい。

その他、netやxyz、今流行りのioやaiドメインもWhois検索することができた。

使われていないドメインの場合

検索したドメインが使われていない場合No match!みたいなエラー文が返ってくるので、使われていないドメインを探している人はtryでエラー処理をした方がいい。

でもエラーが返ってくるのはcomやnetやjpの昔からあるドメインで、appやdevみたいな最近できたドメインだと普通にNullが返ってくるんだよなあ。

参考:https://qiita.com/hirachan/items/6787cb146838aade2d56

PythonでGoogle financeから株価を取得するコード【スクレイピング】


現在の株価を取得をしたかったのでPythonでスクレイピングすることにした。

主に米国株の情報が欲しかったのでリアルタイムで更新されているGoogleファイナンスにすることにした。

そのサイトがスクレイピングが許可されているかどうかはrobots.txtを見ればわかる。

https://www.google.com/robots.txt

投稿時点でAllow: /financeと記載されているので多分大丈夫だと思う。

株価を取得するPythonコード

必要なパッケージはBeautifulSoup4とrequestsなので環境になければインストールする。

pip install BeautifulSoup4 requests

完成コードはこんな感じ。

from bs4 import BeautifulSoup
import requests

def data_get(symbol, lang="ja"):
    url = f"https://www.google.com/finance/quote/{symbol}?hl={lang}"
    res = requests.get(url)
    soup = BeautifulSoup(res.text, "html.parser")
    
    name = soup.find(class_="zzDege").text # 会社名
    
    prices = soup.find_all(class_="YMlKec fxKbKc") # 株価
    p_lis = []
    for i in prices:
        p_lis.append(i.get_text())
    try:
        after = p_lis[1]
    except IndexError:
        after = None

    others = soup.find_all(class_="P6K39c") #その他データ
    o_lis = []
    for i in others:
        o_lis.append(i.get_text())

    return {
        "会社名": name,
        "価格": p_lis[0],
        "時間外取引": after,
        "前日終値": o_lis[0],
        "日次変動幅": o_lis[1],
        "年間変動幅": o_lis[2],
        "時価総額": o_lis[3],
        "平均取引高": o_lis[4],
        "株価収益率": o_lis[5],
        "配当利回り": o_lis[6],
        "優先市場": o_lis[7],
    }

print(data_get("NVDA:NASDAQ"))

# 実行結果
{
    '会社名': 'NVIDIA',
    '価格': '$135.91', 
    '時間外取引': '$135.61', 
    '前日終値': '$140.11', 
    '日次変動幅': '$134.22 - $139.92', 
    '年間変動幅': '$53.49 - $153.13', 
    '時価総額': '3.33兆 USD', 
    '平均取引高': '2.09億', 
    '株価収益率': '53.55', 
    '配当利回り': '0.03%', 
    '優先市場': 'NASDAQ'
}

コード解説

Googleファイナンスは"銘柄コード(シンボル):取引市場"で株情報を管理しているので、そこのURLを変数にして使いやすくした。言語についてはヘッダーやURLになにもつけずにリクエストすると英語で返ってくるので?hl={lang}で言語を指定する。日本語ならja。

URLからhtmlを取得してBeautifulSoupを使ってクラス名でその要素を取得する。クラス名が変わってしまうと使えなくなるので、もし変更があればその都度変更しなければならない。

class_="YMlKec fxKbKc"で株価を取得していて時間外取引の値も取得できるけど、日本株は時間外取引の記載がないのでIndexErrorで処理している。

コードを書いてみての所感

前日比のデータも取りたかったけどその部分はJavascriptで表示させてるっぽいのでレンダリングさせなきゃならない。seleniumを使えばいけるだろうけど、そこまでするのだったら素直にGoogleスプレッドシート使う方が簡単だと思う。

あと日本株は20分ぐらい遅延があるそうなのでPythonならyfinance使った方がいい。米国株ならリアルタイムで取得できるので便利。

Pythonのよく使うpipコマンド一覧


いつも忘れるため、ここにメモ。

# パッケージのインストール
pip install パッケージ名==バージョン

# パッケージのアンインストール
pip uninstall パッケージ名

# パッケージ一覧表示
pip list

# アップデートがあるパッケージを全て表示
pip list -o
or
pip list --outdated

# 最新(アップデートのない)のパッケージの表示
pip list -u

# 特定のパッケージの詳細情報の表示
pip show パッケージ名

# 特定のパッケージをアップデート
pip install -U パッケージ名
or
pip install --upgrade パッケージ名

# パッケージを全てアップデート
pip list --outdated --format=freeze > outdated.txt
pip install -r outdated.txt --upgrade

# 現在の環境にあるパッケージをテキストファイルに書きだす
pip freeze > ファイル名.txt

# テキストファイルにあるパッケージを全てインストールする
pip install -r ファイル名.txt

# テキストファイルにあるパッケージを全て削除する
pip uninstall -r packages.txt -y

condaは一括アップデートがあるのにpipはないのは不便だなあ。

Pythonでリストの特定の値の両隣の値を取得する関数


リストの特定の値の両隣の値を取得したいときがあったのでメモ。

def get_neighbor(target, lis):
    try:
        target_index = lis.index(target)
        before_value = lis[target_index-1] if target_index > 0 else False
        after_value = lis[target_index+1]
    except IndexError:
        after_value = False
    except ValueError:
        before_value = False
        after_value = False
    return before_value, after_value

引数に特定の値とそのリストを渡す。

特定の値のインデックスが0の場合、リストの一番最後の値を指定してしまうのでif文でFalseを入れる。

特定の値がリストの最後の場合、IndexErrorでFalseを入れる。

多分もっといい書き方があると思うけど自分しか使わないしこれでいい。

Flaskのrender_templateで常に特定の変数を渡したい


PythonのFlaskのrender_templateで引数に変数と変数名を渡すとJinja2テンプレートで使用することができる。

しかし、特定のデータをすべてのrender_templateで使いたいときいちいち書くのも面倒なので、一括で渡せる設定方法がFlaskには用意されている。

hoge = "hoge"
common_data = {"hoge": hoge}

@app.context_processor
def inject_data():
    return common_data

@app.context_processorの中の関数のReturnに辞書型の変数を渡してやるとキーの値を使用してJinjaテンプレートで使うことができる。

PythonのFlaskでappコンテキストのエラーの解決方法


PythonのFlaskを触っているとrender_templateの関数でRuntimeError: Working outside of application context.というエラーが出た。プログラミング初心者なので始めは何のことやらわからかったが、調べるとFlaskの関数はFlaskのアプリケーションコンテキストの中でしか実行できないらしい。

つまり、

@main.route('/test')
def test():
    index_html = render_template("index.html")
    return index_html

上記のコードは実行できるが

index_html = render_template("index.html")
@main.route('/test')
def test():
    return index_html

このコードはrender_templateがコンテキストの外にあるのでエラーとなる。

どうしてもルーティングや他のコンテキスト内で実行したいときは

with app.app_context():
# ここに書く

このwithの中に書くとエラーが出ずに実行できる。

vscodeでPythonの複数行コメントアウトの色を変更する


VscodeでPythonの1行のコメントアウトはeditor.tokenColorCustomizationsのcommentsで変更できる。

けどなぜかクォーテーション3つで囲む複数行のコメントアウトの色が適用されなかったのでここにメモする。

"editor.tokenColorCustomizations": {
    "textMateRules":[{
        "scope": "string.quoted.docstring.multi.python",
        "settings":{ "foreground": "#b0c4de" }
    }],
},

setting.jsonに上記のコードを書いてforegroundの部分に好きな色を設定する。

ScopeはコマンドパレットにInspect Editor Tokens and Scopesと打ってエディタートークンとスコープの検査を選択して確認できる。