コマンドラインを使用してWebサイトのタイトルを取得するにはどうすればよいですか?


50

Webサイトのタイトルを印刷するコマンドラインプログラムが必要です。例えば:

Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc

与える必要があります:

Why Are Bad Words Bad? 

URLを指定すると、タイトルが出力されます。


2
そのタイトルをダウンロードすると、「なぜ悪い言葉は悪いのですか?-Youtube」と表示されますが、「-Youtube」も切り捨てられますか?
slm

回答:


44
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
  perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'

次のrecodeようなものがある場合は、GNUにパイプすることができます&lt;

wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
  perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si' |
  recode html..

- youtubeパーツを削除するには:

wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
 perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)(?: - youtube)?\s*<\/title/si'

いくつかの制限を指摘するには:

携帯性

HTTPクエリを実行するための標準/ポータブルコマンドはありません。数十年前には、lynx -sourceここで代わりに推奨していたでしょう。しかし、今日でwgetは、ほとんどのGNUシステム(ほとんどのLinuxベースのデスクトップ/ラップトップオペレーティングシステムを含む)でデフォルトで見つかるため、よりポータブルです。他のかなり移植性の高いものには、しばしばインストールされるlibwwwにGET付属するコマンドが含まれますが、perlこれはlynx -sourceそれほどではありませんcurl。その他の一般的なものが含まれlinks -sourceelinks -sourcew3m -dump_sourcelftp -c cat...

HTTPプロトコルとリダイレクト処理

wgetたとえばfirefox表示されるページと同じページを取得できない場合があります。その理由は、HTTPサーバーが、クライアントから送信された要求で提供された情報に基づいて異なるページを送信することを選択する可能性があるためです。

wget / w3m / GET ...によって送信されるリクエストは、firefoxによって送信されるリクエストとは異なります。問題がある場合はwget、オプションを使用してリクエストの送信方法を変更するように動作を変更できます。

この点で最も重要なものは次のとおりです。

  • AcceptおよびAccept-language:これは、クライアントが応答を取得する言語と文字セットをサーバーに指示します。wgetデフォルトではサーバーが送信しないため、サーバーは通常、デフォルト設定で送信します。firefoxもう一方の端は、おそらくあなたの言語を要求するように設定されています。
  • User-Agent:サーバーに対してクライアントアプリケーションを識別します。(それにはJavaScript言語の解釈の違いをほとんどだが)、あなたが使用している場合はあなたを提供することを拒否して一部のサイトでは、クライアントに基づいて異なるコンテンツを送信するロボットのような型のユーザーエージェントをwget
  • Cookie:以前にこのサイトにアクセスしたことがある場合、ブラウザには永続的なCookieが含まれている可能性があります。wgetしない。

wgetHTTPプロトコルレベルで行われた場合、リダイレクトに従いますが、ページのコンテンツは参照しないため、javascriptなどの方法ではリダイレクトされません<meta http-equiv="refresh" content="0; url=http://example.com/">

パフォーマンス/効率

ここでは、怠ofな状況からperl<title>タグの検索を開始する前にメモリ内のコンテンツ全体を読み取りました。<head>ファイルの最初の数バイトにあるセクションでタイトルが見つかった場合、最適ではありません。GNU awkがシステムで利用可能な場合、より良いアプローチは次のとおりです。

wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
  gawk -v IGNORECASE=1 -v RS='</title' 'RT{gsub(/.*<title[^>]*>/,"");print;exit}'

この方法では、awkは最初のの後に読み取りを停止し</title、終了wgetすることでダウンロードを停止します。

HTMLの解析

ここでwgetは、ダウンロードするページを書き込みます。同時にperl、その出力(slurps -0777 -nメモリに)全体を、その後の最初の発生との間に発見されたHTMLコード印刷<title...>とを</title

これは、<title>タグを持つほとんどのHTMLページで機能しますが、機能しない場合があります。

対照的に、coffeeMugのソリューションはHTMLページをXMLとして解析し、対応する値を返しますtitleページが有効なXMLであることが保証されている場合は、より正確です。ただし、HTMLは有効なXMLである必要はありません(古いバージョンの言語はそうではありませんでした)。世の中のほとんどのブラウザーは寛大であり、誤ったHTMLコードを受け入れるため、そこには多くの誤ったHTMLコードさえあります。

私のソリューションとcoffeeMugの両方は、さまざまなコーナーケースで失敗しますが、同じ場合もそうでない場合もあります。

たとえば、私のものは失敗します:

<html><head foo="<title>"><title>blah</title></head></html>

または:

<!-- <title>old</title> --><title>new</title>

彼が失敗する間:

<TITLE>foo</TITLE>

(xmlではなく有効なhtml)または:

または:

<title>...</title>
...
<script>a='<title>'; b='</title>';</script>

(再び、有効なhtml、欠落している<![CDATA[部分を有効なXMLにします)。

<title>foo <<<bar>>> baz</title>

(不正なhtmlですが、まだ見つかっており、ほとんどのブラウザーでサポートされています)

タグ内のコードの解釈。

このソリューションは<title>、との間の生テキストを出力します</title>。通常、そこにHTMLタグはありません。コメントがある可能性があります(firefoxのような一部のブラウザではあまり処理されませんが)。HTMLエンコードがまだ残っている可能性があります。

$ wget -qO- 'http://www.youtube.com/watch?v=CJDhmlMQT60' |
  perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'
Wallace &amp; Gromit - The Cheesesnatcher Part 1 (claymation) - YouTube

これはGNUによって処理されますrecode

$ wget -qO- 'http://www.youtube.com/watch?v=CJDhmlMQT60' |
  perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si' |
   recode html..
Wallace & Gromit - The Cheesesnatcher Part 1 (claymation) - YouTube

ただし、Webクライアントは、タイトルを表示するときにそのコードをさらに変換することも意図しています(一部の空白を圧縮し、先頭と末尾の空白を削除するなど)。ただし、その必要があるとは考えられません。そのため、他の場合と同様に、努力する価値があるかどうかはあなた次第です。

キャラクターセット

UTF-8より前は、厳密に言えばiso8859-1 が非ASCII文字のWeb上の優先文字セットでしたが、厳密に言うと、として記述する必要がありました&eacute;。HTTPおよびHTML言語の最新バージョンでは、HTTPヘッダーまたはHTMLヘッダーで文字セットを指定する可能性が追加されており、クライアントは受け入れる文字セットを指定できます。UTF-8は最近ではデフォルトの文字セットになる傾向があります。

だから、そこから、あなたが見つけることをその手段éとして書かれた&eacute;として、&#233;UTF-8として、é文字セットに、2つの最後のもののために、ISO-8859-1(0xe9)として、(0xc3 0xa9)時々の情報をHTTPヘッダーまたはHTMLヘッダー(異なる形式)で、場合によってはそうではありません。

wget 生のバイトのみを取得し、文字としての意味を気にしません。また、優先文字セットについてWebサーバーに通知しません。

recode html..は、システムで使用されている文字セットに合わせて、&eacute;または&#233;を適切なバイトシーケンスに変換するように注意しますが、それ以外の場合は、より複雑です。

システムの文字セットがutf-8である場合、ほとんどの場合、それが現在使用されているデフォルトの文字セットである傾向があるため、大丈夫になる可能性があります。

$ wget -qO- 'http://www.youtube.com/watch?v=if82MGPJEEQ' |
 perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'
Noir Désir - L&#39;appartement - YouTube

これは、é上記のUTF-8でしたé

しかし、他の文字セットをカバーしたい場合は、もう一度注意する必要があります。

また、このソリューションはUTF-16またはUTF-32でエンコードされたページではまったく機能しないことに注意してください。

総括する

ここで必要なのは、情報を提供するための実際のWebブラウザであることが理想です。つまり、適切なパラメーターを使用してHTTP要求を実行し、HTTP応答を正しく解釈し、ブラウザーが行うようにHTMLコードを完全に解釈し、タイトルを返すために何かが必要です。

私が知っているブラウザでコマンドラインでそれを行うことはできないと思うので(今ではこのトリックをlynx参照してください)、ヒューリスティックと近似に頼らなければならず、上記のものはどれも優れています。

また、パフォーマンス、セキュリティなどを考慮することもできます。たとえば、すべてのケースをカバーするために(たとえば、タイトルを設定したり、別のページにリダイレクトしたりするサードパーティのサイトからいくつかのJavaScriptを取得したWebページonload hook)、実際のブラウザにdomとjavascriptエンジンを実装する必要があります。これは、単一のHTMLページに対して何百ものクエリを実行する必要があり、その一部は脆弱性を悪用しようとします...

一方でパースHTMLに正規表現を使用したが、多くの場合、眉をひそめるされ、ここでは、タスク(IMO)のために良い十分だ典型的なケースです。


ページから画像もダウンロードしますか?また、ジャンクHTMLファイルを残しますか?
Ufoguy

2
<タイトルには終了タグがあることが保証されておらず、他のタグは強制的に終了する必要があるため、おそらく最初のインスタンスでタイトルを終了する必要があります。新しい行を削除することもできます。
ブライアンニッケル

1
HTMLの解析に正規表現を使用することはお勧めしません。今まで。この場合でもそうではありません。それは悪い習慣です。代わりに実際のパーサーを使用してください。この程度の有名なユーモラスなStackOverflowの答えは...ある
ロビン・グリーン

4
@RobinGreenこの投稿は、正規表現を使用して非正規言語を解析することに関するものでした。警告がありますが、これは通常の言語に簡単に縮小できる問題です。正規表現を使用してHTMLを解析することをお勧めします。時々。この場合。
ブライアンニッケル

2
そして、正規表現の数は、ほぼすべての作業はほぼ0であること
ロビン・グリーン

27

次のようにしてhxselectHTML-XML-Utilsから)試すこともできwgetます。

wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' | hxselect -s '\n' -c  'title' 2>/dev/null

以下hxselectを使用して、Debianベースのディストリビューションにインストールできます
sudo apt-get install html-xml-utils

STDERRリダイレクトは、Input is not well-formed. (Maybe try normalize?)メッセージを回避することです。

「-YouTube」を取り除くには、上記のコマンドの出力をにパイプしますawk '{print substr($0, 0, length($0)-10)}'


「hxselect」はデフォルトでUbuntuにインストールされていないようです。既存のリポジトリで見つけることさえできません。どうすればインストールできますか?
Ufoguy

7
sudo apt-get install html-xml-utils
coffeMug

Ubuntu 12.10でこのエラーが発生します。「入力の形式が正しくありません。(正規化を試みますか?)」
slm

1
メッセージの処理方法が見つかりません。出力の正規化について。そのようなスイッチはありませんhxselect
slm

1
Mac OS Xの場合、Homebrewにはhxselectを含む式があります。でインストールしbrew install html-xml-utilsます。
スキマ14

18

使用することもできますcurlし、grepこれを実行します。タグを見つけることができるように、PCRE(Perl Compatible Regular Expressions)の使用を登録grepして、後ろを見て先読み機能を取得する<title>...</title>必要があります。

$ curl 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' -so - | \
    grep -iPo '(?<=<title>)(.*)(?=</title>)'
Why Are Bad Words Bad? - YouTube

詳細

curlスイッチ:

  • -s =サイレント
  • -o - =出力をSTDOUTに送信

grepスイッチ:

  • -i =大文字と小文字を区別しない
  • -o =一致する部分のみを返す
  • -P = PCREモード

次のパターンgrep

  • (?<=<title>) =左からこれで始まる文字列を探します
  • (?=</title>) =右でこれで終わる文字列を探します
  • (.*)=その間のすべて<title>..</title>

より複雑な状況

<title>...</titie>複数の行にまたがる場合、上記はそれを見つけません。trを使用して\n文字を削除することにより、この状況を緩和できますtr -d '\n'

サンプルファイル。

$ cat multi-line.html 
<html>
<title>
this is a \n title
</TITLE>
<body>
<p>this is a \n title</p>
</body>
</html>

サンプルの実行:

$ curl 'http://www.jake8us.org/~sam/multi-line.html' -so - | \
     tr -d '\n' | \
     grep -iPo '(?<=<title>)(.*)(?=</title>)'
this is a \n title

lang = ...

<title>このように設定されている場合、<title lang="en">実行grepする前にこれを削除する必要があります。このツールsedを使用してこれを行うことができます。

$ curl 'http://www.jake8us.org/~sam/multi-line.html' -so - | \
     tr -d '\n' | \
     sed 's/ lang="\w+"//gi' | \
     grep -iPo '(?<=<title>)(.*)(?=</title>)'
this is a \n title

上記では、大文字と小文字を区別しない文字列のlang=後に単語シーケンス(\w+)が続きます。その後、削除されます。

実際のHTML / XMLパーサー-Rubyを使用

ある時点で、正規表現はこのタイプの問題の解決に失敗します。その場合は、おそらく実際のHTML / XMLパーサーを使用する必要があります。そのようなパーサーの1つがNokogiriです。RubyでGemとして使用でき、次のように使用できます。

$ curl 'http://www.jake8us.org/~sam/multi-line.html' -so - | \
    ruby -rnokogiri -e \
     'puts Nokogiri::HTML(readlines.join).xpath("//title").map { |e| e.content }'

this is a \n title

上記は、curlas HTML(Nokogiri::HTML)を介して送信されるデータを解析しています。次に、メソッドxpath//、名前がであるリーフノード()であるHTML内のノード(タグ)を探しますtitle。見つかったそれぞれについて、そのコンテンツを返します(e.content)。putsそして、それらを出力します。

実際のHTML / XMLパーサー-Perlを使用

PerlとHTML :: TreeBuilder :: XPathモジュールでも同様のことができます。

$ cat title_getter.pl
#!/usr/bin/perl

use HTML::TreeBuilder::XPath;

$tree = HTML::TreeBuilder::XPath->new_from_url($ARGV[0]); 
($title = $tree->findvalue('//title')) =~ s/^\s+//;
print $title . "\n";

その後、このスクリプトを次のように実行できます。

$ ./title_getter.pl http://www.jake8us.org/~sam/multi-line.html
this is a \n title 

1
きちんとしたソリューション!:)
coffeMug

3
正規表現を使用したHTMLの解析はそれほど単純ではありません。「<TITLE>」、「<title lang = en>」、「<title \ n>」として記述されたタグは、表現と一致しません。さらに大きな問題は、「<title> \ noops \ n </ title>」のどちらでもありません。
マナトワーク

4
正規表現を使用してhtmlを解析しようとすると、ここでのラウンドでをしかめる傾向があります。
user3490

1
@slm <title>Unix\nLinux</title>Unix Linux、ではなくを意味しますUnixLinux
ステファンシャゼル

1
+1ルビー+のこぎり。あらゆる種類のウェブスクレイピングに使用しましたが、すごいです!
ロブ

7

単純な正規表現を使用してHTMLを解析するのは簡単です。たとえば、改行を使用し、ファイルで指定された特殊文字エンコーディングを無視します。正しいことをして、他の回答に記載されている他の実際のパーサーを使用してページを実際に解析するか、次のライナーを使用します。

python -c "import bs4, urllib2; print bs4.BeautifulSoup(urllib2.urlopen('http://www.crummy.com/software/BeautifulSoup/bs4/doc/')).title.text"

(上記にはUnicode文字が含まれます)。

BeautifulSoupは、多くの不正なHTML(終了タグの欠落など)も処理します。これにより、単純な正規表現が完全にスローされます。以下を使用して、標準のPythonにインストールできます。

pip install beautifulsoup4

または、持っていない場合はpip

easy_install beautifulsoup4

Debian / Ubuntuなどの一部のオペレーティングシステムでもパッケージ化されていpython-bs4ます(Debian / Ubuntuのパッケージ)。


2
bs4Python標準ライブラリにはありません。easy_install beautfulsoup4(ではなくeasyinstall bs4)を使用してインストールする必要があります。
アントン

@アンソンはあなたの情報を含んでいた
ゼルダ

5

多分それは「不正行為」ですが、1つのオプションはコマンドラインHTMLパーサーであるpupです。

以下に2つの方法を示します。

属性を持つmetaフィールドを 使用するproperty="og:title

$ wget -q 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' -O - | \
> pup 'meta[property=og:title] attr{content}'
Why Are Bad Words Bad?

titleフィールドを直接使用する別の方法(そして- YouTube最後に文字列を削除する)。

$ wget -q 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' -O - | \
> pup 'title text{}' | sed 's/ - YouTube$//'
Why Are Bad Words Bad?

キャラクターエンティティを回避するために、ユーザーはpupの--plainオプションを使用できます。
ピーク

3

lynxこのトリック(zshbash構文)を使用することで可能になるようです:

lynx -cfg=<(printf '%s\n' 'PRINTER:P:printf "%0s\\n" "$LYNX_PRINT_TITLE">&3:TRUE'
  ) lynx 3>&1 > /dev/null -nopause -noprint -accept_all_cookies -cmd_script <(
    printf '%s\n' "key p" "key Select key" "key ^J" exit
  ) 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc'

これは実際のWebブラウザーであるため、他の回答で述べた制限の多くに悩まされていません。

ここでは、ページを印刷するときに環境変数を現在のページのタイトルにlynx設定するという事実を使用して$LYNX_PRINT_TITLEいます。

上記ではP、その変数の内容をファイル記述子に出力するだけのlynx「プリンター」を定義する構成ファイルを(パイプとして)提供しています3(そのファイル記述子はlynx stdoutがリダイレクトされlynxている3>&1間にのstdoutにリダイレクトされます) / dev / null)。

次に、lynxスクリプト機能を使用して、ユーザーがp、およびEnd(別名select)、およびEnter^J)を押すのをシミュレートします。

-accept_all_cookies それ以外の場合、lynxはすべてのCookieの確認をユーザーに要求します。


3

簡単な方法:

curl -s example.com | grep -o "<title>[^<]*" | tail -c+8

いくつかの選択肢:

curl -s example.com | grep -o "<title>[^<]*" | cut -d'>' -f2-
wget -qO- example.com | grep -o "<title>[^<]*" | sed -e 's/<[^>]*>//g'

1
これらは私のために働いた唯一のものです!
アフマドアワイス16

1

私はLénxとLYNX_PRINT_TITLEを使用するStéphaneChazelasのアイデアが好きでしたが、そのスクリプトはUbuntu 14.04.5では機能しませんでした。

Lynxを実行し、事前に構成されたファイルを使用することで、簡易バージョンを作成しました。

/etc/lynx-cur/lynx.cfg(またはlynx.cfgが存在する場所)に次の行を追加します。

PRINTER:P:printenv LYNX_PRINT_TITLE>/home/account/title.txt:TRUE:1000

この行は、印刷中にタイトルを「/home/account/title.txt」に保存するように指示します-任意のファイル名を選択できます。非常に大きなページを要求し、上記の値を「1000」から必要なページごとの行数に増やすと、Lynxは「非常に多くのページを含むドキュメントを印刷するときに」追加のプロンプトを表示します。

次に、次の内容の/home/account/lynx-script.txtファイルを作成します。

key p
key Select key
key ^J
exit

次に、次のコマンドラインオプションを使用してLynxを実行します。

lynx -term=vt100 -display_charset=utf-8 -nopause -noprint -accept_all_cookies -cmd_script=/home/account/lynx-script.txt "http://www.youtube.com/watch?v=Dd7dQh8u4Hc" >/dev/nul

このコマンドが完了すると、ページのタイトルを含むファイル/home/account/title.txtが作成されます。

簡単に言えば、ここに指定されたURLに基​​づいてページタイトルを返すPHP関数があります。エラーの場合はfalseです。

function GetUrlTitle($url)
{
  $title_file_name = "/home/account/title.txt";
  if (file_exists($title_file_name)) unlink($title_file_name); // delete the file if exists
  $cmd = '/usr/bin/lynx -cfg=/etc/lynx-cur/lynx.cfg -term=vt100 -display_charset=utf-8 -nopause -noprint -accept_all_cookies -cmd_script=/home/account/lynx-script.txt "'.$url.'"';
  exec($cmd, $output, $retval);
  if (file_exists($title_file_name))
  {
    $title = file_get_contents($title_file_name);
    unlink($title_file_name); // delete the file after reading
    return $title;
  } else
  {
    return false;
  }
}

print GetUrlTitle("http://www.youtube.com/watch?v=Dd7dQh8u4Hc");

0

nokogiriを使用すると、簡単なCSSベースのクエリを使用して、タグの内部テキストを抽出できます。

 $ nokogiri -e 'puts $_.at_css("title").content'
 Why Are Bad Words Bad? - YouTube

同様に、タグの「content」属性の値を抽出するには:

$ nokogiri -e 'puts $_.at_css("meta[name=title]").attr("content")'
Why Are Bad Words Bad?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.