PythonのRequestsとSQLAlchemyを使用し指定したURLのタイトルを取得しデータベースに書き込む

スポンサーリンク

PythonのRequestsとSQLAlchemyを使用し指定したURLのタイトルを取得しデータベースに書き込んでみます。

今回はRequests、BeautifulSoup、SQLAlchemyを用います。これらのライブラリ・モジュールが事前にインストールされているかを確認し実行する場合は実行してください。

■Python

今回のPythonのバージョンは、「3.8.5」を使用しています。(Windows11)

■RequestsとSQLAlchemyを使用し指定したURLのタイトルを取得しデータベースに書き込む

では、早速RequestsとSQLAlchemyを使用し指定したURLのタイトルを取得しデータベースに書き込むスクリプトを書いていきます。

■コード

import requests
from bs4 import BeautifulSoup
from sqlalchemy import create_engine, Column, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# URLからタイトルを抽出する関数
def extract_title(html):
    soup = BeautifulSoup(html, 'html.parser')
    title = soup.title.string
    return title

# データベースモデル
Base = declarative_base()

class Title(Base):
    __tablename__ = 'titles'
    url = Column(String, primary_key=True)
    title = Column(String)

# データベースの設定
engine = create_engine('')
Session = sessionmaker(bind=engine)
session = Session()

# データベースの初期化
Base.metadata.create_all(engine)

# URLからタイトルを取得してデータベースに保存する関数
def save_title(url):
    response = requests.get(url)
    title = extract_title(response.text)

    existing_title = session.query(Title).filter_by(url=url).first()
    if existing_title:
        existing_title.title = title
    else:
        new_title = Title(url=url, title=title)
        session.add(new_title)
    session.commit()

# 使用例
save_title('https://www.yahoo.co.jp/')

まず、extract_title(html)関数では、引数としてHTMLのテキストを受け取ります。BeautifulSoupを使用してHTMLをパースし、title要素の文字列を取得します。取得したタイトルを返します。

そして、Titleモデルでは、SQLAlchemyのBaseクラスを継承しています。’titles’という名前のテーブルを定義します。
urlとtitleの2つのカラムを持ち、urlカラムを主キーに設定します。

次にデータベースの設定を行います。create_engine関数を使用して、データベースに接続するためのエンジンを作成します。今回はオンラインDBサービスである「ElephantSQL(https://www.elephantsql.com/)」を用います。ElephantSQLは予め「test_db」という名前でインスタンスを作り、インスタンスのDetailsから「URL」の情報をコピーします。

コピーするとURLは「postgres://dsppyfom:***@heffalump.db.elephantsql.com/dsppyfom」のようなものとなっていますが、「postgresql://dsppyfom:***@heffalump.db.elephantsql.com/dsppyfom」と先頭の部分を変更します。変更しないと「sqlalchemy.exc.NoSuchModuleError: Can’t load plugin: sqlalchemy.dialects:postgressql」というエラーが出力されます。

接続先のデータベースの情報を引数に指定します。sessionmakerを使用してセッションを作成し、エンジンにバインドします。sessionオブジェクトを作成します。

設定語、データベースの初期化します。Base.metadata.create_all(engine)を呼び出すことで、データベース内にモデルに対応するテーブルを作成します。

テーブルを作成後、save_title(url)関数を定義します。引数としてURLを受け取ります。requests.get(url)を使用して指定したURLからHTMLを取得します。取得したHTMLをextract_title関数に渡してタイトルを抽出します。session.query(Title).filter_by(url=url).first()を使用して、データベース内に同じURLのデータが既に存在するか確認します。存在する場合は、既存のタイトルを更新します。存在しない場合は、新しいデータとしてタイトルを追加します。変更をデータベースにコミットします。

最後に、save_title(‘https://www.yahoo.co.jp/’)で関数を呼び出します。使用例として「’https://www.yahoo.co.jp/’」のURLからタイトルを取得し、データベースに保存します。

■検証・実行

今回書いたスクリプトを「web_url.py」という名前でPythonが実行されている作業ディレクトリ(カレントディレクトリ)に保存し、コマンドプロンプトから実行してみます。

web_url.py:14: MovedIn20Warning: The ``declarative_base()`` function is now available as sqlalchemy.orm.declarative_base(). (deprecated since: 2.0) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
  Base = declarative_base()

実行してみると「MovedIn20Warning」という警告は表示されましたがデータベースへの書き込みは完了しました。

完了後、ElephantSQL上からテーブルを確認すると、テーブル内にデータが書き込まれていることが確認できました。

web_url.py:14: MovedIn20Warning: The ``declarative_base()`` function is now available as sqlalchemy.orm.declarative_base(). (deprecated since: 2.0) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9) Base = declarative_base()

なお、上記の警告ですが、下記のように変更すると問題を解決できます。

■修正前

import requests
from bs4 import BeautifulSoup
from sqlalchemy import create_engine, Column, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

■修正後

import requests
from bs4 import BeautifulSoup
from sqlalchemy import create_engine, Column, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import declarative_base

コメント

タイトルとURLをコピーしました