Bir web sitesinin başlığını yazdıran bir komut satırı programı istiyorum. Örneğin:
Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc
vermelisin:
Why Are Bad Words Bad?
URL'yi girin ve Başlığı yazdırır.
Bir web sitesinin başlığını yazdıran bir komut satırı programı istiyorum. Örneğin:
Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc
vermelisin:
Why Are Bad Words Bad?
URL'yi girin ve Başlığı yazdırır.
Yanıtlar:
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'
Eğer onun recode
gibi şeyler varsa, bunu GNU'ya aktarabilirsiniz <
:
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si' |
recode html..
Parçayı çıkarmak için - youtube
:
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)(?: - youtube)?\s*<\/title/si'
Bazı kısıtlamaları belirtmek için:
HTTP sorguları yapmak için standart / taşınabilir bir komut yoktur. Birkaç yıl önce, lynx -source
burada bunun yerine tavsiye ederdim . Ancak günümüzde, wget
çoğu GNU sistemlerinde (çoğu Linux tabanlı masaüstü / dizüstü bilgisayar işletim sistemi dahil) varsayılan olarak bulunabileceğinden daha taşınabilir. Oldukça portatif olanlara başkaları, sık sık yüklenen ve daha az oranda libwww GET
ile gelen komutu içerir . Diğer yaygın olanları şunlardır , , , ...perl
lynx -source
curl
links -source
elinks -source
w3m -dump_source
lftp -c cat
wget
Örneğin firefox
görüntüleyeceğiniz sayfanın aynısını alamayabilir . Bunun nedeni, HTTP sunucularının, müşteri tarafından gönderilen talepte verilen bilgilere dayanarak farklı bir sayfa göndermeyi seçebilmeleridir.
Wget / w3m / GET ... tarafından gönderilen istek, firefox tarafından gönderilenlerden farklı olacaktır. Bu bir sorunsa, seçeneği wget
göndermesine rağmen isteği gönderme biçimini değiştirme davranışını değiştirebilirsiniz.
Bu konuda en önemlileri:
Accept
ve Accept-language
: sunucuya, istemcinin yanıtı almak istediği dil ve karakter grubunun. wget
varsayılan olarak herhangi bir yol göndermediğini, bu nedenle de sunucu varsayılan ayarlarıyla birlikte göndereceğini bildirir. firefox
Diğer taraftan, muhtemelen dilinizi istemek için yapılandırılmıştır.User-Agent
: sunucuya istemci uygulamasını tanımlar. Bazı siteler müşteriye göre farklı içerikler gönderir (çoğunlukla javascript dili yorumlamaları arasındaki farklar içindir) ve bunun gibi bir robot tipi kullanıcı aracısı kullanıyorsanız size hizmet vermeyi reddedebilir wget
.Cookie
: bu siteyi daha önce ziyaret ettiyseniz, tarayıcınız bunun için kalıcı çerezlere sahip olabilir. wget
olmaz.wget
Yönlendirmeleri HTTP protokol düzeyinde yaptıklarında, ancak javascript tarafından yapılanlara değil, sayfa içeriğine bakmadığı için yönlendirmeleri izleyecektir <meta http-equiv="refresh" content="0; url=http://example.com/">
.
Burada, tembelliğin dışında perl
, <title>
etiketi aramaya başlamadan önce tüm içeriği bellekte okuduk . Başlığın, <head>
dosyanın ilk birkaç baytlık bölümünde bulunduğu göz önüne alındığında , bu uygun değildir. awk
Sisteminizde GNU varsa daha iyi bir yaklaşım olabilir:
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
gawk -v IGNORECASE=1 -v RS='</title' 'RT{gsub(/.*<title[^>]*>/,"");print;exit}'
Bu şekilde, awk birinciden sonra okumayı keser </title
ve çıkıldığında wget
indirme işleminin durmasına neden olur .
Burada, wget
sayfayı indirdiği sırada yazar. Aynı zamanda, perl
çıktısını ( -0777 -n
) tam olarak bellekte sıkıştırır ve sonra ilk <title...>
ve arasındakiler arasında bulunan HTML kodunu yazdırır </title
.
Bu, <title>
etiketi olan çoğu HTML sayfası için işe yarar, ancak çalışmadığı durumlar vardır.
Bunun aksine, coffeeMug'un çözümü HTML sayfasını XML olarak ayrıştırır ve karşılık gelen değeri döndürür title
. Sayfanın geçerli XML olacağı garanti edilirse daha doğrudur . Bununla birlikte, HTML'nin geçerli bir XML olması gerekmez (dilin eski sürümleri yoktu) ve çoğu tarayıcı esnek ve hatalı HTML kodunu kabul edeceğinden, orada pek çok yanlış HTML kodu da var.
Hem çözümüm hem de coffeeMug'larım bazen aynı, bazen değil, çeşitli köşe davaları için başarısız olacak.
Mesela, mayın başarısız olacak:
<html><head foo="<title>"><title>blah</title></head></html>
veya:
<!-- <title>old</title> --><title>new</title>
Onun başarısız olurken:
<TITLE>foo</TITLE>
(geçerli html, xml değil) veya:
veya:
<title>...</title>
...
<script>a='<title>'; b='</title>';</script>
(yine geçerli XML yapmak için html
eksik , geçerli <![CDATA[
parçalar).
<title>foo <<<bar>>> baz</title>
(yanlış html, ancak yine de orada bulundu ve çoğu tarayıcı tarafından desteklendi)
Bu çözüm, <title>
ve arasındaki ham metni çıkarır </title>
. Normalde, orada herhangi bir HTML etiketi olmamalıdır, muhtemelen yorumlar olabilir (ancak firefox gibi bazı tarayıcılar tarafından pek kullanılmaz). Hala bazı HTML kodlamaları olabilir:
$ wget -qO- 'http://www.youtube.com/watch?v=CJDhmlMQT60' |
perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'
Wallace & Gromit - The Cheesesnatcher Part 1 (claymation) - YouTube
GNU tarafından halledilir 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
Ancak bir web istemcisi aynı zamanda başlığı görüntülerken bu kod üzerinde daha fazla dönüşüm yapmak anlamına da gelir (boşluklardan bazılarını yoğunlaştırmak, önde gelenleri ve sondakileri kaldırmak gibi). Ancak bunun için bir ihtiyaç olması muhtemel değildir. Yani, diğer durumlarda olduğu gibi, çabaya değip değmeyeceğine siz karar verin.
UTF-8'den önce iso8859-1, ASCII olmayan karakterler için web'de tercih edilen karakter kümesiydi, ancak kesinlikle yazmaları gerekiyordu é
. HTTP'nin ve HTML dilinin daha yeni sürümleri, HTTP başlıklarında veya HTML başlıklarında karakter belirleme olanağını ekledi ve bir istemci kabul ettiği karakter kümelerini belirleyebilir. UTF-8, bugünlerde varsayılan karakter kümesi olma eğilimindedir.
Yani bu, göreceğiniz, orada ortaya demektir é
olarak yazılır é
gibi é
UTF-8 olarak, é
2 son olanlar için olan iso-8859-1 (0xe9) gibi, (0xc3 0xa9) charset bazen bilgi HTTP başlıklarında veya HTML başlıklarında (farklı biçimlerde), bazen değil.
wget
sadece ham baytları alır, karakter olarak anlamlarını önemsemez ve web sunucusuna tercih edilen karakter grubunu anlatmaz.
recode html..
dönüştürmek için ilgilenir é
veya é
sisteminizde kullanılan karakter seti için bayt doğru süresine içine, ama geri kalanı için, bu yanıltıcıdır.
Eğer sistem karakter diziniz utf-8 ise, bugünlerde kullanılan standart karakter dizisi olma eğiliminde olduğu için çoğu zaman yolunda gitme şansı yoktur.
$ 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'appartement - YouTube
Bu é
yukarıda bir UTF-8 oldu é
.
Ancak, diğer karakter setlerini ele almak istiyorsanız, bir kez daha yapılması gerekir.
Ayrıca bu çözümün UTF-16 veya UTF-32 kodlu sayfalar için hiçbir zaman işe yaramayacağına da dikkat edilmelidir.
İdeal olarak, burada ihtiyacınız olan şey, size bilgi veren gerçek bir web tarayıcısıdır. Diğer bir deyişle, HTTP isteğini uygun parametrelerle yapmak, HTTP yanıtını doğru bir şekilde anlamak, HTML kodunu bir tarayıcı gibi tam olarak yorumlamak ve başlığı döndürmek için bir şeye ihtiyacınız var.
Bildiğim tarayıcılarla komut satırında yapılabileceğini sanmıyorum (şu anda bu numarayılynx
görüyorsunuz ), sezgisel ve yaklaşımlara başvurmak zorundasınız ve yukarıdakilerden biri en az sizin kadar iyi.
Ayrıca performansı, güvenliği de göz önünde bulundurmak isteyebilirsiniz ... Örneğin, tüm vakaları ele almak için (örneğin, başlığı ayarlayan veya bir sayfadaki başka bir sayfaya yönlendirme yapan bir üçüncü taraf sitesinden bir javascript çekilmiş bir web sayfası). (load load hook), dom ve javascript motorlarıyla tek bir HTML sayfası için yüzlerce sorgu yapmak zorunda kalabilecek, bazıları güvenlik açıklarından yararlanmaya çalışan gerçek bir tarayıcı uygulamanız gerekebilir ...
İken genellikle hoş karşılanmaz HTML Ayrıştırma İfadelerinin kullanarak , işte burada görev (IMO) için yeterince iyi tipik bir durumdur.
<
çünkü başlıkların son etiketlerinin olması garanti edilmez ve başka bir etiketin sonlandırılmasını zorlaması gerekir. Ayrıca yeni çizgiler de çıkarmak isteyebilirsiniz.
Ayrıca hxselect
( HTML-XML-Utils'ten ) wget
aşağıdaki gibi deneyebilirsiniz :
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' | hxselect -s '\n' -c 'title' 2>/dev/null
Sen yükleyebilirsiniz hxselect
kullanarak Debian tabanlı dağıtımlar içinde:
sudo apt-get install html-xml-utils
.
STDERR yönlendirmesi Input is not well-formed. (Maybe try normalize?)
mesajı engellemektir .
"- YouTube" dan kurtulmak için yukarıdaki komutun çıktısını alın awk '{print substr($0, 0, length($0)-10)}'
.
sudo apt-get install html-xml-utils
hxselect
.
Ayrıca kullanabilirsiniz curl
ve grep
bunun için. Sen kullanımını askere gerekir PCRE (Perl Uyumlu Normal İfadeler) içinde grep
bulduğumuz böylece tesisleri arkasında görünümü elde ve ileriye bakma <title>...</title>
etiketleri.
$ curl 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' -so - | \
grep -iPo '(?<=<title>)(.*)(?=</title>)'
Why Are Bad Words Bad? - YouTube
curl
anahtarlar:
-s
= sessiz-o -
= STDOUT'a çıktı göndergrep
anahtarlar:
-i
= büyük küçük harfe duyarsızlık-o
= Sadece eşleşen kısmı döndür-P
= PCRE moduİçin desen grep
:
(?<=<title>)
= bununla başlayan solda bir dize ara(?=</title>)
= bununla biten bir dize ara(.*)
= aradaki herşey <title>..</title>
.Birden <title>...</titie>
fazla satır içeriyorsa, yukarıdaki satır bulamaz. Bu durumu tr
, herhangi bir \n
karakteri silmek için , yani kullanarak azaltabilirsiniz tr -d '\n'
.
Örnek dosya
$ cat multi-line.html
<html>
<title>
this is a \n title
</TITLE>
<body>
<p>this is a \n title</p>
</body>
</html>
Ve bir örnek çalışması:
$ curl 'http://www.jake8us.org/~sam/multi-line.html' -so - | \
tr -d '\n' | \
grep -iPo '(?<=<title>)(.*)(?=</title>)'
this is a \n title
Eğer <title>
böyle ayarlanmışsa, eklemeden <title lang="en">
önce bunu kaldırmanız grep
gerekir. Araç sed
bunu yapmak için kullanılabilir:
$ 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
Yukarıdaki, büyük / küçük harf duyarsız dizgeyi, lang=
ardından bir sözcük dizisini ( \w+
) bulur . Daha sonra çıkarıldı.
Bir noktada regex bu tür bir problemi çözmede başarısız olacaktır. Bu durumda, büyük olasılıkla gerçek bir HTML / XML ayrıştırıcı kullanmak isteyeceksiniz. Böyle bir ayrıştırıcı Nokogiri'dir . Ruby'de Gem olarak bulunur ve şu şekilde kullanılabilir:
$ 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
Yukarıdaki, curl
HTML ( Nokogiri::HTML
) aracılığıyla gelen verileri ayrıştırmadır . Yöntem xpath
daha sonra HTML'deki yaprak düğümleri olan düğümleri (etiketleri) //
, adında arar title
. Her bulunan için içeriğini ( e.content
) döndürmek istiyoruz . puts
Sonra onları dışarı yazdırır.
Perl ve HTML :: TreeBuilder :: XPath modülüne benzer bir şey de yapabilirsiniz .
$ 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";
Daha sonra bu betiği şöyle çalıştırabilirsiniz:
$ ./title_getter.pl http://www.jake8us.org/~sam/multi-line.html
this is a \n title
<title>Unix\nLinux</title>
olması gerekiyordu Unix Linux
, değil UnixLinux
.
HTML'yi ayrıştırmak için basit regex kullanmak saftır. Örn. Yeni satırlar ve dosyada belirtilen özel karakter kodlamasını dikkate almamak. Doğru olanı yapın ve diğer cevaplarda belirtilen diğer gerçek ayrıştırıcılardan herhangi birini kullanarak sayfayı gerçekten ayrıştırın veya aşağıdaki astarı kullanın:
python -c "import bs4, urllib2; print bs4.BeautifulSoup(urllib2.urlopen('http://www.crummy.com/software/BeautifulSoup/bs4/doc/')).title.text"
(Yukarıdaki bir Unicode karakteri içerir).
BeautifulSoup, tamamen basitleştirilmiş regexing işlemine neden olacak bir sürü hatalı HTML'yi (örneğin eksik kapanış etiketlerini) yönetir. Aşağıdakileri kullanarak standart bir pitona kurabilirsiniz:
pip install beautifulsoup4
yoksa yoksa pip
ile,
easy_install beautifulsoup4
Debian / Ubuntu gibi bazı işletim sistemleri de paketlenmiştir ( python-bs4
Debian / Ubuntu'daki paket).
bs4
python standart kütüphanesinde değil. easy_install beautfulsoup4
(Değil easyinstall bs4
) kullanarak yüklemelisiniz .
Belki "hile yapıyor" ama bir seçenek pup, komut satırı HTML ayrıştırıcısı .
İşte bunu yapmanın iki yolu:
meta
Alanı property="og:title
nitelik ile kullanma
$ wget -q 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' -O - | \
> pup 'meta[property=og:title] attr{content}'
Why Are Bad Words Bad?
ve title
doğrudan alanı kullanan başka bir yol (ve daha sonra sondaki - YouTube
dizgiyi işaretleyerek).
$ wget -q 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' -O - | \
> pup 'title text{}' | sed 's/ - YouTube$//'
Why Are Bad Words Bad?
--plain
seçeneğini kullanmak isteyebilirler .
lynx
Bu hile ( zsh
, bash
sözdizimi) kullanarak mümkün gibi görünüyor :
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'
Çünkü bu gerçek hayattan bir web tarayıcısı, diğer cevabımda bahsettiğim sınırlamaların birçoğundan muzdarip değil .
Burada, sayfayı yazdırırken ortam değişkenini geçerli sayfanın başlığına lynx
ayarlayan gerçeği kullanıyoruz $LYNX_PRINT_TITLE
.
Yukarıda, biz denilen bir vaşak "yazıcı" tanımlar (bir boru gibi) bir yapılandırma dosyası veriyoruz P
sadece tanımlayıcı dosya o değişkenin içeriğini verir 3
(yani dosya tanıtıcı yönlendirilir lynx
ile 'ın stdout'u 3>&1
vaşak stdout'u kendisi yönlendirildi iken ile / dev / null).
Sonra lynx
kullanıcı basmayı p
ve End
(aka select) ve Enter
( ^J
) tuşlarını simüle etmek için komut dosyası özelliğini kullanırız .
-accept_all_cookies
Aksi gibi, lynx kullanıcıdan her çerez için onay isteyecektir.
Basit yol:
curl -s example.com | grep -o "<title>[^<]*" | tail -c+8
Birkaç alternatif:
curl -s example.com | grep -o "<title>[^<]*" | cut -d'>' -f2-
wget -qO- example.com | grep -o "<title>[^<]*" | sed -e 's/<[^>]*>//g'
Stéphane Chazelas'ı Lynx ve LYNX_PRINT_TITLE kullanma fikri hoşuma gitti, ancak bu senaryo benim için Ubuntu 14.04.5 altında işe yaramadı.
Lynx'i kullanarak ve önceden yapılandırılmış dosyaları kullanarak basitleştirilmiş bir versiyonunu yaptım.
Aşağıdaki satırı /etc/lynx-cur/lynx.cfg dosyasına (veya lynx.cfg'in bulunduğu yere) ekleyin:
PRINTER:P:printenv LYNX_PRINT_TITLE>/home/account/title.txt:TRUE:1000
Bu satır, başlık yazarken "/home/account/title.txt" dizinine kaydedilmesini ister - istediğiniz herhangi bir dosya adını seçebilirsiniz. ÇOK büyük sayfalar talep edersiniz, yukarıdaki değeri "1000" den istediğiniz sayfa başına istediğiniz sayıda satıra yükseltin, aksi takdirde Lynx "çok fazla sayıda sayfa içeren bir belge yazdırırken" sorusunu ekleyecektir.
Ardından /home/account/lynx-script.txt dosyasını aşağıdaki içeriklerle oluşturun:
key p
key Select key
key ^J
exit
Ardından, aşağıdaki komut satırı seçeneklerini kullanarak Lynx'i çalıştırın:
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
Bu komutun tamamlanmasından sonra /home/account/title.txt dosyası sayfanızın başlığı ile oluşturulacaktır.
Uzun lafın kısası, burada verilen URL'ye dayalı bir sayfa başlığı döndüren veya hata durumunda yanlış veren bir PHP işlevidir.
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");
Nokogiri kullanarak, etiketin iç metnini çıkarmak için basit bir CSS tabanlı sorgu kullanabilirsiniz:
$ nokogiri -e 'puts $_.at_css("title").content'
Why Are Bad Words Bad? - YouTube
Benzer şekilde, etiketin "content" özniteliğinin değerini çıkarmak için:
$ nokogiri -e 'puts $_.at_css("meta[name=title]").attr("content")'
Why Are Bad Words Bad?