Saya ingin program baris perintah yang mencetak judul situs web. Untuk misalnya:
Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc
harus memberi:
Why Are Bad Words Bad?
Anda memberikan url dan mencetak Judul.
command-line
web
http
Ufoguy
sumber
sumber
Jawaban:
Anda dapat mengirimkannya ke GNU
recode
jika ada hal-hal seperti<
di dalamnya:Untuk menghapus
- youtube
bagian:Untuk menunjukkan beberapa batasan:
portabilitas
Tidak ada perintah standar / portabel untuk melakukan permintaan HTTP. Beberapa dekade yang lalu, saya akan merekomendasikan di
lynx -source
sini. Tetapi saat ini,wget
lebih portabel karena dapat ditemukan secara default pada sebagian besar sistem GNU (termasuk sebagian besar sistem operasi desktop / laptop berbasis Linux). Yang cukup portabel lainnya termasukGET
perintah yang datang denganperl
libwww yang sering diinstallynx -source
,, dan pada tingkat lebih rendahcurl
. Lainnya umum yang meliputilinks -source
,elinks -source
,w3m -dump_source
,lftp -c cat
...Protokol HTTP dan penanganan pengalihan
wget
mungkin tidak mendapatkan halaman yang sama dengan yang misalnyafirefox
akan ditampilkan. Alasannya adalah bahwa server HTTP dapat memilih untuk mengirim halaman yang berbeda berdasarkan informasi yang disediakan dalam permintaan yang dikirim oleh klien.Permintaan yang dikirim oleh wget / w3m / GET ... akan berbeda dari yang dikirim oleh firefox. Jika itu masalah, Anda bisa mengubah
wget
perilaku untuk mengubah cara mengirimkan permintaan melalui opsi.Yang paling penting dalam hal ini adalah:
Accept
danAccept-language
: yang memberi tahu server tempat bahasa dan rangkaian karakter yang diinginkan klien untuk mendapatkan respons.wget
tidak mengirim apa pun secara default sehingga server biasanya akan mengirim dengan pengaturan default.firefox
di sisi lain kemungkinan dikonfigurasi untuk meminta bahasa Anda.User-Agent
: yang mengidentifikasi aplikasi klien ke server. Beberapa situs mengirim konten berbeda berdasarkan klien (meskipun itu sebagian besar untuk perbedaan antara interpretasi bahasa javascript) dan mungkin menolak untuk melayani Anda jika Anda menggunakan robot seperti agen penggunawget
.Cookie
: jika Anda pernah mengunjungi situs ini sebelumnya, browser Anda mungkin memiliki cookie permanen untuk itu.wget
tidak akan.wget
akan mengikuti pengalihan ketika mereka dilakukan di tingkat protokol HTTP, tetapi karena tidak melihat konten halaman, bukan yang dilakukan oleh javascript atau hal-hal seperti<meta http-equiv="refresh" content="0; url=http://example.com/">
.Kinerja / Efisiensi
Di sini, karena malas, kami telah
perl
membaca seluruh konten dalam memori sebelum mulai mencari<title>
tag. Mengingat bahwa judul ditemukan di<head>
bagian yang ada di beberapa byte pertama file, itu tidak optimal. Pendekatan yang lebih baik, jika GNUawk
tersedia di sistem Anda bisa:Dengan begitu, awk berhenti membaca setelah yang pertama
</title
, dan dengan keluar, menyebabkanwget
berhenti mengunduh.Parsing HTML
Di sini,
wget
tulis halaman saat mengunduhnya. Pada saat yang samaperl
,, slurps output (-0777 -n
) seluruh dalam memori dan kemudian cetak kode HTML yang ditemukan antara kejadian pertama<title...>
dan</title
.Itu akan berfungsi untuk sebagian besar halaman HTML yang memiliki
<title>
tag, tetapi ada kasus di mana itu tidak akan berfungsi.Sebaliknya , solusi coffeeMug akan mem-parsing halaman HTML sebagai XML dan mengembalikan nilai yang sesuai untuk
title
. Lebih tepat jika halaman dijamin XML yang valid . Namun, HTML tidak harus merupakan XML yang valid (versi bahasa yang lebih lama tidak), dan karena sebagian besar peramban di luar sana lunak dan akan menerima kode HTML yang salah, bahkan ada banyak kode HTML yang salah di luar sana.Baik solusi saya dan coffeeMug akan gagal untuk berbagai kasus sudut, kadang-kadang sama, kadang tidak.
Misalnya, milik saya akan gagal pada:
atau:
Sementara itu akan gagal pada:
(html valid, bukan xml) atau:
atau:
(lagi, valid
html
,<![CDATA[
bagian yang hilang untuk menjadikannya XML yang valid).(html salah, tetapi masih ditemukan di sana dan didukung oleh sebagian besar browser)
interpretasi kode di dalam tag.
Solusi itu menampilkan teks mentah antara
<title>
dan</title>
. Biasanya, seharusnya tidak ada tag HTML di sana, mungkin ada komentar (meskipun tidak ditangani oleh beberapa browser seperti firefox jadi sangat tidak mungkin). Mungkin masih ada beberapa penyandian HTML:Yang diurus oleh GNU
recode
:Tetapi klien web juga dimaksudkan untuk melakukan lebih banyak transformasi pada kode itu ketika menampilkan judul (seperti menyingkat beberapa bagian yang kosong, menghapus yang utama dan yang tertinggal). Namun tidak mungkin ada kebutuhan untuk itu. Jadi, seperti dalam kasus lain, terserah Anda memutuskan apakah itu sepadan dengan usaha.
Set karakter
Sebelum UTF-8, iso8859-1 digunakan untuk menjadi charset pilihan di web untuk karakter non-ASCII meskipun secara tegas mereka harus dituliskan sebagai
é
. Versi HTTP dan bahasa HTML yang lebih baru telah menambahkan kemungkinan untuk menentukan karakter yang ditetapkan dalam header HTTP atau dalam header HTML, dan klien dapat menentukan charset yang diterimanya. UTF-8 cenderung menjadi charset default saat ini.Jadi, itu berarti bahwa di luar sana, Anda akan menemukan
é
ditulis sebagaié
, sepertié
, seperti UTF-8é
, (0xc3 0xa9), seperti iso-8859-1 (0xe9), dengan untuk 2 yang terakhir, kadang-kadang informasi di charset di header HTTP atau header HTML (dalam format berbeda), terkadang tidak.wget
hanya mendapatkan byte mentah, tidak peduli tentang artinya sebagai karakter, dan tidak memberi tahu server web tentang charset yang disukai.recode html..
akan berhati-hati untuk mengubahé
ataué
menjadi urutan byte yang tepat untuk set karakter yang digunakan pada sistem Anda, tetapi untuk sisanya, itu lebih sulit.Jika charset sistem Anda utf-8, kemungkinan itu akan baik-baik saja sebagian besar waktu karena cenderung menjadi charset default yang digunakan di luar sana saat ini.
Itu di
é
atas adalah UTF-8é
.Tetapi jika Anda ingin menutupi untuk rangkaian karakter lain, sekali lagi, itu harus diurus.
Perlu juga dicatat bahwa solusi ini tidak akan berfungsi sama sekali untuk halaman yang disandikan UTF-16 atau UTF-32.
Untuk menyimpulkan
Idealnya, yang Anda butuhkan di sini, adalah browser web asli untuk memberi Anda informasi. Artinya, Anda perlu melakukan sesuatu untuk melakukan permintaan HTTP dengan parameter yang tepat, mengintepret respons HTTP dengan benar, sepenuhnya menafsirkan kode HTML seperti yang dilakukan browser, dan mengembalikan judul.
Karena saya tidak berpikir itu dapat dilakukan pada baris perintah dengan browser yang saya tahu (meskipun lihat sekarang trik ini dengan
lynx
), Anda harus menggunakan heuristik dan perkiraan, dan yang di atas sama baiknya dengan yang ada.Anda mungkin juga ingin mempertimbangkan kinerja, keamanan ... Misalnya, untuk mencakup semua kasus (misalnya, halaman web yang memiliki beberapa javascript yang ditarik dari situs pihak ke-3 yang menetapkan judul atau mengalihkan ke halaman lain dalam suatu onload hook), Anda mungkin harus mengimplementasikan browser kehidupan nyata dengan mesin dom dan javascript yang mungkin harus melakukan ratusan pertanyaan untuk satu halaman HTML, beberapa di antaranya mencoba untuk mengeksploitasi kerentanan ...
Meskipun menggunakan regexps untuk mem-parsing HTML sering disukai , berikut ini adalah kasus khas di mana itu cukup baik untuk tugas (IMO).
sumber
<
karena judul tidak dijamin memiliki tag akhir dan tag lain apa pun harus memaksa terminasi tersebut. Anda mungkin juga ingin menghapus garis baru.Anda juga dapat mencoba
hxselect
(dari HTML-XML-Utils ) denganwget
sebagai berikut:Anda dapat menginstal
hxselect
di distro berbasis Debian menggunakan:sudo apt-get install html-xml-utils
.Pengalihan STDERR adalah untuk menghindari
Input is not well-formed. (Maybe try normalize?)
pesan.Untuk menyingkirkan "- YouTube", kirimkan output dari perintah di atas ke
awk '{print substr($0, 0, length($0)-10)}'
.sumber
sudo apt-get install html-xml-utils
hxselect
.brew install html-xml-utils
.Anda juga dapat menggunakan
curl
dangrep
melakukan ini. Anda harus meminta penggunaan PCRE (Perl Compatible Regular Expressions) digrep
untuk mendapatkan tampilan belakang dan fasilitas tampilan depan sehingga kita dapat menemukan<title>...</title>
tag.Contoh
Detail
The
curl
switch:-s
= diam-o -
= kirim output ke STDOUTThe
grep
switch:-i
= tidak sensitif huruf-o
= Hanya kembalikan bagian yang cocok-P
= Mode PCREPola untuk
grep
:(?<=<title>)
= cari string yang dimulai dengan ini di sebelah kiri itu(?=</title>)
= mencari string yang diakhiri dengan ini di sebelah kanannya(.*)
= semuanya di antaranya<title>..</title>
.Situasi yang lebih kompleks
Jika
<title>...</titie>
membentang beberapa baris, maka di atas tidak akan menemukannya. Anda dapat mengurangi situasi ini dengan menggunakantr
, untuk menghapus\n
karakter apa pun , yaitutr -d '\n'
.Contoh
File sampel.
Dan contoh dijalankan:
lang = ...
Jika
<title>
diset seperti ini,<title lang="en">
maka Anda harus menghapus ini sebelumgrep
memasukkannya. Alatsed
ini dapat digunakan untuk melakukan ini:Di atas menemukan string tidak peka huruf besar kecil
lang=
diikuti oleh urutan kata (\w+
). Ini kemudian dilucuti.Parser HTML / XML nyata - menggunakan Ruby
Pada titik tertentu regex akan gagal dalam memecahkan masalah jenis ini. Jika itu terjadi maka Anda mungkin ingin menggunakan parser HTML / XML nyata. Salah satu pengurai seperti itu adalah Nokogiri . Ini tersedia di Ruby sebagai Permata dan dapat digunakan seperti:
Di atas adalah parsing data yang datang melalui
curl
HTML (Nokogiri::HTML
). Metode inixpath
kemudian mencari node (tag) dalam HTML yang merupakan leaf node, (//
) dengan namanyatitle
. Untuk setiap yang ditemukan, kami ingin mengembalikan kontennya (e.content
). Theputs
kemudian mencetak mereka keluar.Parser HTML / XML nyata - menggunakan Perl
Anda juga dapat melakukan sesuatu yang serupa dengan Perl dan modul HTML :: TreeBuilder :: XPath .
Anda kemudian dapat menjalankan skrip ini seperti:
sumber
<title>Unix\nLinux</title>
seharusnyaUnix Linux
, bukanUnixLinux
.Menggunakan regex sederhana untuk mem-parsing HTML adalah naif. Misalnya dengan baris baru dan mengabaikan pengkodean karakter khusus yang ditentukan dalam file. Lakukan hal yang benar dan benar-benar mengurai halaman menggunakan salah satu parser nyata lainnya yang disebutkan dalam jawaban lain atau menggunakan liner berikut:
(Di atas termasuk karakter Unicode).
BeautifulSoup juga menangani banyak HTML yang salah (mis. Tag penutup yang hilang), yang akan membuang regexing sederhana. Anda dapat menginstalnya dalam python standar menggunakan:
atau jika Anda tidak punya
pip
, denganBeberapa sistem operasi seperti Debian / Ubuntu juga telah dikemas (
python-bs4
paket pada Debian / Ubuntu).sumber
bs4
tidak ada di pustaka standar python. Anda harus menginstalnya menggunakaneasy_install beautfulsoup4
(bukaneasyinstall bs4
).Mungkin itu "curang" tetapi satu opsi adalah pup, sebuah parser HTML baris perintah .
Berikut adalah dua cara untuk melakukannya:
Menggunakan
meta
bidang denganproperty="og:title
atributdan cara lain menggunakan
title
bidang secara langsung (dan kemudian memotong- YouTube
string di akhir).sumber
--plain
opsi pup .Tampaknya dimungkinkan dengan
lynx
menggunakan trik ini (zsh
,bash
sintaks):Karena itu adalah peramban web kehidupan nyata, itu tidak menderita dari banyak keterbatasan yang saya sebutkan dalam jawaban saya yang lain .
Di sini, kami menggunakan fakta yang
lynx
menetapkan$LYNX_PRINT_TITLE
variabel lingkungan ke judul halaman saat ini saat mencetak halaman.Di atas, kami memberikan file konfigurasi (sebagai pipa) yang mendefinisikan "printer" lynx yang disebut
P
yang hanya menampilkan konten variabel tersebut ke file descriptor3
(file deskriptor tersebut dialihkan kelynx
stdout dengan3>&1
sementara lynx stdout dengan sendirinya dialihkan ke / dev / null).Kemudian kami menggunakan
lynx
fasilitas scripting untuk mensimulasikan pengguna menekanp
, danEnd
(alias pilih), danEnter
(^J
).-accept_all_cookies
karena jika tidak, lynx akan meminta konfirmasi kepada pengguna untuk setiap cookie.sumber
Cara sederhana:
Beberapa alternatif:
sumber
Saya menyukai gagasan Stéphane Chazelas untuk menggunakan Lynx dan LYNX_PRINT_TITLE, tetapi skrip itu tidak berfungsi untuk saya di bawah Ubuntu 14.04.5.
Saya telah membuat versi yang disederhanakan dengan menggunakan Lynx dan menggunakan file yang sudah dikonfigurasikan sebelumnya.
Tambahkan baris berikut ke /etc/lynx-cur/lynx.cfg (atau di mana pun lynx.cfg Anda berada):
Baris ini menginstruksikan untuk menyimpan judul, saat mencetak, ke "/home/account/title.txt" - Anda dapat memilih nama file yang Anda inginkan. Anda meminta SANGAT halaman yang besar, tambahkan nilai di atas dari "1000" ke sejumlah baris per halaman yang Anda inginkan, jika tidak Lynx akan membuat prompt tambahan "saat mencetak dokumen yang berisi halaman yang sangat besar".
Kemudian buat file /home/account/lynx-script.txt dengan konten berikut:
Kemudian jalankan Lynx menggunakan opsi baris perintah berikut:
Setelah menyelesaikan perintah ini, file /home/account/title.txt akan dibuat dengan judul halaman Anda.
Singkatnya, berikut adalah fungsi PHP yang mengembalikan judul halaman berdasarkan URL yang diberikan, atau false jika terjadi kesalahan.
sumber
Menggunakan nokogiri, orang dapat menggunakan kueri berbasis CSS sederhana untuk mengekstrak teks bagian dalam tag:
Demikian pula, untuk mengekstrak nilai atribut "konten" dari tag:
sumber