このガイドでは、次の内容を説明します:
wget
とは何か。- なぜrequestsライブラリよりも優れているのか。
- Pythonで
wget
を使用するのがいかに簡単か。 - Pythonスクリプトにwgetを導入するメリットとデメリット。
さっそく始めましょう!
wgetとは何か?
wget
は、HTTP、HTTPS、FTP、FTPS、およびその他のインターネットプロトコルを使用してWebからファイルをダウンロードするためのコマンドラインユーティリティです。ほとんどのUnix系OSにネイティブでインストールされていますが、Windowsでも使用できます。
なぜrequestsのようなPythonパッケージではなくwgetを使うべきなのですか?
確かにwget
はクールなコマンドラインツールですが、Pythonでのファイルのダウンロードにrequestsのような人気のあるライブラリではなく、wgetを使うべきなのはなぜでしょうか?
以下に挙げる通り、requestsよりもwget
を使用するべき理由はたくさんあります:
- requestsよりも多くのプロトコルをサポートしているから。
- 中止または中断されたダウンロードを再開できるから。
- ネットワーク帯域幅を使い切らないように、ダウンロード速度を制限する仕様をサポートしているから。
- ワイルドカードを使用したファイル名とネットワークロケーションをサポートしているから。
- 多言語に対応したNLSベースのメッセージファイル。
- ダウンロードしたドキュメント内の絶対リンクを相対リンクに変換できるから。
- HTTP/Sプロキシをサポートしているから。
- 持続的HTTP接続をサポートしているから。
- 無人ダウンロード/バックグラウンドダウンロード操作を実行できるから。
- ローカルファイルのタイムスタンプを使用して、ミラーリング時にドキュメントを再ダウンロードする必要があるかどうかを判断するから。
- 特定のウェブページにリンクされたファイルを再帰的にダウンロードすることや、ユーザーが指定した再帰の深さに達するまでダウンロードすることができるから。
- robots.txtで定義されたロボット除外ルールを自動的に尊重するから。ウェブスクレイピングについては、robots.txtのガイドで詳細をご覧ください。
これらはwget
の機能のほんの一部で、どのPython HTTPクライアントライブラリよりも強力で特別です。詳細は公式マニュアルをご覧ください。
特に、wget
はHTMLページのリンクをたどって、そのページで引用されているファイルをダウンロードできることに注意してください。これによりWebサイト全体を取得することも可能になるため、wget
はWebクローリングに最適です。
簡単に言うと、wgetはWebからファイルやWebページをダウンロードする必要があるスクリプトを書く場合に最適なオプションです。Pythonでwget
を使用する方法を学びましょう!
PythonでのCLIコマンドの実行
以下の手順に従い、wget
コマンドを実行できるPythonスクリプトを作成してください。
前提条件
始める前に、マシンにwget
がインストールされていることを確認します。セットアッププロセスはOSによって異なります:
- Linuxではすでにプリインストールされているはずです。それ以外の場合は、ディストリビューションのパッケージマネージャーを使用してインストールしてください。
- Macでは、ホームブリューで
wget
をインストールします。 - Windowsでは、Windows用
wget
バイナリをダウンロードし、フォルダに配置してください。次に、wget
バイナリパス(例:C:\Program Files (x86)\ wget)をPATH環境変数に追加します。
マシンにはPython 3+もインストールされている必要があります。セットアップするには、インストーラーをダウンロードし、アイコンをダブルクリックした後、プロンプトの指示に従ってください。
PyCharm Community EditionなどのPython IDEか、Python拡張機能を入れたVisual Studio Codeがおすすめです。
Pythonプロジェクトのセットアップ
以下のコマンドを使用することで、仮想環境でwget
Pythonプロジェクトを作成できます:
mkdir wget-python-demo
cd wget-python-demo
python -m venv env
上記で作成したwget-python-demo
ディレクトリは、プロジェクトのフォルダを表しています。
これをPython IDEで読み込み、script.pyファイルを作成し、次のように初期化します:
print('Hello, World!')
今のところ、これはターミナルに「Hello, World!」と表示するだけのサンプルスクリプトです。近い将来、wget
統合ロジックが含まれる予定です。
IDEの実行(Run)ボタンを押すか、次のコマンドを実行して、スクリプトが機能することを確認してください:
python script.py
ターミナルには次のように表示されているはずです:
Hello, World!
素晴らしい!これでPythonプロジェクトが作成されました。
次のセクションでwget
の使用方法を参照してください!
サブプロセスモジュールを介してCLIコマンドを実行する関数の作成
PythonスクリプトでCLIコマンドを実行する最も簡単な方法は、サブプロセスモジュールを使用することです。
Python標準ライブラリの該当ライブラリを使用すると、新しいプロセスの生成や、その入出力/エラーパイプへの接続、リターンコードの取得ができます。言い換えると、Pythonからターミナルでコマンドを実行するために必要な要素をすべて揃えられるということです。
これは、サブプロセスからPopen()メソッドを使用してPythonでwget
のようなCLIコマンドを実行する方法です:
import subprocess
def execute_command(command):
"""
Execute a CLI command and return the output and error messages.
Parameters:
- command (str): The CLI command to execute.
Returns:
- output (str): The output generated by the command.
- error (str): The error message generated by the command, if any.
"""
try:
# execute the command and capture the output and error messages
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = process.communicate()
output = output.decode("utf-8")
error = error.decode("utf-8")
# return the output and error messages
return output, error
except Exception as e:
# if an exception occurs, return the exception message as an error
return None, str(e)
popen()は、文字列として渡されたコマンドをOSの新しいプロセスで実行します。shell=Trueオプションは、このメソッドがOSで設定されているデフォルトのシェルを使用することを保証します。
上記のスニペットをscript.pyファイルに貼り付けます。これで、次の例のようにPythonでCLIコマンドを呼び出すことができます:
output, error = execute_command("
if error:
print("An error occurred while running the CLI command:", error)
else:
print("CLI command output:", output)
Pythonでwgetを使用する:ユースケース
これはwget
コマンドの構文です:
wget [options] [url]
場所:
- [options]はCLIツールの動作をカスタマイズするためにサポートされているオプションとフラグのリストです。
- 「url」はダウンロードするファイルのURLです。これは、ファイルへの直接リンクでも、複数のファイルへのリンクを含むWebページのURLでもかまいません。
注:Windowsでは、「wget
」の代わりに「wget.exe
」と書いてください。
一般的なユースケースをカバーするPythonスニペットでwget
が実際に動作するのを見てみましょう!
ファイルのダウンロード
wget
でhttp://lumtest.com/myip.jsonをダウンロードしたいとします。これを実現するコマンドは次のようになります:
wget http://lumtest.com/myip.json
Pythonでは、次のコード行になります:
output, error = execute_command("wget http://lumtest.com/myip.json")
出力を印刷すると、次のようになります:
--2024-04-18 15:20:59-- http://lumtest.com/myip.json
Resolving lumtest.com (lumtest.com)... 3.94.72.89, 3.94.40.55
Connecting to lumtest.com (lumtest.com)|3.94.72.89|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 266 [application/json]
Saving to: 'myip.json.1'
myip.json.1 100%[=================================================>] 266 --.-KB/s in 0s
2024-04-18 15:20:59 (5.41 MB/s) - 'myip.json.1' saved [266/266]
コマンドの出力から、次の結果が表示されます:
- URLはサーバーのIPアドレスに解決されます。
wget
は、指定されたリソースへのHTTPリクエストを介してサーバーに接続します。- サーバーが受信したHTTP応答ステータスコードは200です。
wget
はファイルをダウンロードし、現在のディレクトリに保存します。
これでPythonプロジェクトディレクトリにmyip.jsonファイルが含まれるようになりました。
ダウンロードするファイルの保存先フォルダを変更する場合は、以下のように–directory-prefixまたは-Pフラグを使用してください:
output, error = execute_command("wget --directory-prefix=./download http://lumtest.com/myip.json")
これで、myip.jsonファイルがプロジェクトのディレクトリ内のダウンロードフォルダに保存されるようになりました。宛先フォルダが存在しない場合、wget
により自動的に作成されることに注意してください。
ダウンロードリソースのファイル名を変更するには、–output-documentまたは-Oフラグを使用してください:
output, error = execute_command("wget --output-document=custom-name.json http://lumtest.com/myip.json")
今回は、wget
Pythonスクリプトはmyip.jsonの代わりにcustom-name.jsonという名前のファイルを作成します。
Webページのダウンロード
wget
コマンドは以前と同じですが、主な違いは今回の「url」がWebページを指すことです:
output, error = execute_command("wget https://brightdata.com/")
これで、プロジェクトのディレクトリに、Webページ(https://brightdata.com/)のHTMLコンテンツを備えたindex.htmlファイルが含まれるようになります
前回のダウンロード以降に変更がある場合にのみファイルをダウンロードする
ディスク容量とネットワークリソースを節約するために、前回のダウンロードから変更されていないファイルはダウンロードしたくないと思うかもしれません。wget
がファイルタイムスタンプ機能を提供している理由はここにあります。
詳しく説明すると、–timestampingオプションはwget
に、ローカルファイルのタイムスタンプをサーバー上のタイムスタンプと比較するように指示します。ローカルファイルのタイムスタンプがサーバー上のタイムスタンプと同じか新しい場合、wget
はファイルを再度ダウンロードしません。それ以外の場合は、ダウンロードされます。
これがタイムスタンプメカニズムの仕組みです:
- –timestampまたは-Nオプションを使用してファイルをダウンロードすると、
wget
はリモートファイルのタイムスタンプを取得します。 - ローカルファイルのタイムスタンプ(存在する場合)をチェックし、リモートファイルのタイムスタンプと比較します。
- ローカルファイルが存在しない場合や、そのタイムスタンプがサーバー上のタイムスタンプよりも古い場合、
wget
はファイルをダウンロードします。ローカルファイルが存在し、そのタイムスタンプがサーバー上のタイムスタンプと同じか新しい場合、wget
はファイルをダウンロードしません。
HTTPのタイムスタンプは、HEADリクエストの後にサーバーから返されるLast-Modifiedヘッダーをチェックすることで実装されます。wget
はContent-Lengthヘッダーも調べてファイルサイズを比較します。それらが同じでない場合は、Last-Modifiedヘッダーの内容に関係なくリモートファイルがダウンロードされます。Last-Modifiedはオプションのレスポンスヘッダーであることに注意してください。ファイルが存在しない場合、wget
はいずれにしてもファイルをダウンロードします。
Pythonの–timestampオプションを次のコード行で使用してください:
output, error = execute_command("wget --timestamping https://brightdata.com")
index.hmlを既にダウンロードしている場合、ファイルが再びダウンロードされないことを示す以下のメッセージが表示されます:
--2024-04-18 15:55:06-- https://brightdata.com
Resolving brightdata.com (brightdata.com)... 104.18.25.60, 104.18.24.60
Connecting to brightdata.com (brightdata.com)|104.18.25.60|:443... connected.
HTTP request sent, awaiting response... 304 Not Modified
File 'index.html' not modified on server. Omitting download.
FTP経由でファイルをダウンロードする場合も、同じメカニズムが機能します。
中断されたダウンロードの完了
デフォルトでは、処理中に接続が失われた場合、wget
はファイルのダウンロードを自動的に最大20回再試行します。部分的にダウンロードされたファイルを手動で続行する場合は、次のように–continueまたは-cオプションを使用してください:
output, error = execute_command("wget --continue http://lumtest.com/myip.json")
サイト全体をダウンロード
再帰的ダウンロードは、1つのコマンドでサイト全体をダウンロードするwget
機能です。
指定されたURLから始めて、wget
はHTMLページを解析し、srcおよびhref HTML属性またはurl() CSS属性で見つかった他のドキュメントに従います。次のファイルもテキスト/HTMLファイルである場合は、目的の深さに達するまでそれを解析し、そのドキュメントも追跡します。再帰的ダウンロードは幅優先検索アルゴリズムに従い、深度1でファイルを取得し、次に深度2という順序でファイルを取得します。
このダウンロードモードを使用する際に覚えておくべきwget
オプションは次のとおりです。
- –recursiveまたは-r:ファイルを再帰的にダウンロードするように、
wget
に指示します。つまり、Webページ上のリンクをたどります。これにより、画像、スタイルシート、スクリプトなど、リンクされたすべてのリソースを含むWebサイト全体のローカルコピーを作成できます。このオプションを指定すると、wget
はダウンロードされたすべてのファイルをターゲットサイトのドメイン名と同じ名前のフォルダに保存します。 - –level=
または-l= :リンクされたページをダウンロードするときに従う再帰の最大深度を指定します。たとえば、–level=1に設定した場合、 wget
は開始URLから直接リンクされているページのみをダウンロードします。これらのページのリンクをたどって他のページをダウンロードすることはありません。巨大サイトのクロールを防ぐため、デフォルトの深度値は5です。このオプションを0に設定するか、’inf’に設定すると深度が無限になります。指定した深さに関係なく、ページを正しく表示するために必要なすべてのリソースがダウンロードされるようにするには、-pまたは–page-requisitesオプションを追加してください。 - –convert-linksまたは-k:ダウンロードされたHTMLファイル内のリンクを、元のURLではなくローカルにダウンロードされたファイルを指すように変更します。このオプションは、サイトのローカルミラーを作成し、ダウンロードしたページ内のすべてのリンクがオフラインで正しく機能するようにしたい場合に便利です。
すべてのリンクをローカルファイルを指すように変換しながら、Bright Dataサイトを最大深度1で再帰的にダウンロードしたいとします。以下があなたが書くべきPython wget
コマンドです:
output, error = execute_command("wget --recursive --level=1 --convert-links https://brightdata.com")
注:このコマンドはインターネット接続の速度によっては時間がかかる場合がありますので、しばらくお待ちください。
これで、brightdata.comフォルダに、Bright Dataサイトファイルのローカルコピーが1レベルの深さで再帰的に格納されます。
wgetとPythonを併用することの長所と短所
Pythonでwget
を使用するメリットとデメリットを見てみましょう。
メリット
- サブプロセスモジュールによりPythonを簡単に統合できます。
- 再帰的ダウンロード、自動再試行、ファイルスタンプなど、多数の機能とオプション。
- 1つのコマンドでサイト全体のローカルコピーを作成できます。
- FTPサポート。
- プロキシ統合のサポート。
- 中断されたダウンロードを回復できます。
デメリット
- 出力はダウンロードされたファイルであり、Pythonスクリプトで直接使用できる文字列変数ではありません。
- ダウンロードしたHTMLファイルから特定のDOM要素にアクセスするには、Beautiful Soupのようなパーサーが必要です。
[追加]プロキシでのwgetの使用
wget
を使用してファイルまたはサイト全体をダウンロードする際の主な課題は、リクエストがブロックされる可能性があることです。これは、wget
リクエストが送信先サーバーにボットからのリクエストとして表示されるためです。一部のWebサイトでは、ボットからのリクエストを防ぐため、ページやリソースに制限や上限を設けています。これらの制限には、地理的制限、律速ポリシー、またはスクレイピング対策が含まれる場合があります。
プロキシサーバーのwget
への統合は、こうした制限を回避するための現実的なソリューションです。プロキシは、コンピューターとインターネットの間の中間サーバーとして機能します。wget
トラフィックをプロキシサーバー経由で転送することで、IPの公開を回避し、サイトが課すほとんどの制限を回避できます。
さらに詳細なチュートリアルについては、wgetでプロキシを使用する方法
に関するガイドを参照してください。
まとめ
この記事では、wget
とは何か、なぜこれがrequestsライブラリよりも優れているのか、そしてPythonでの使い方を理解しました。これで、wget
がHTTP、HTTPS、FTP経由でファイルやWebページをダウンロードするための強力なツールであることがお分かりいただけたかと思います。ここで学んだことのおかげで、Pythonでwget
を使用する方法の知識を獲得できました。
このガイドで見てきたように、wget
のようなユーティリティによるコンテンツのダウンロードを防ぐためにWebサイトが講じているボット対策をすべて回避するには、プロキシが非常に役立ちます。問題なのは、オンラインには数十種類のプロバイダーがあり、最適なプロバイダーを選択するのが簡単ではないことです。業界最高のオプションであるBright Dataに迷わず決めれば、プロキシプロバイダーを選ぶ時間を省くことができます。
Bright Dataは世界最高レベルのプロキシサーバーを保有しており、フォーチュン500企業を含む20,000社以上の顧客にサービスを提供しています。Bright Dataは次のような様々な種類のプロキシを提供しています:
- データセンタープロキシ — 770,000を超えるデータセンターIP
- 住宅用プロキシ — 195か国以上で7,200万件を超える住宅用IP
- ISPプロキシ — 70万を超えるISP用IP
- モバイルプロキシ — 700万を超えるモバイル用IP
無料トライアルを開始するか、当社のデータ専門家に当社のプロキシおよびスクレイピングソリューションについてご相談ください。
クレジットカードは必要ありません