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 recodegibi ş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 -sourceburada 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 GETile gelen komutu içerir . Diğer yaygın olanları şunlardır , , , ...perllynx -sourcecurllinks -sourceelinks -sourcew3m -dump_sourcelftp -c cat
wgetÖrneğin firefoxgö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 wgetgöndermesine rağmen isteği gönderme biçimini değiştirme davranışını değiştirebilirsiniz.
Bu konuda en önemlileri:
Acceptve Accept-language: sunucuya, istemcinin yanıtı almak istediği dil ve karakter grubunun. wgetvarsayılan olarak herhangi bir yol göndermediğini, bu nedenle de sunucu varsayılan ayarlarıyla birlikte göndereceğini bildirir. firefoxDiğ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. wgetolmaz.wgetYö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. awkSisteminizde 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 </titleve çıkıldığında wgetindirme işleminin durmasına neden olur .
Burada, wgetsayfayı 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 htmleksik , 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 ) wgetaşağıdaki gibi deneyebilirsiniz :
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' | hxselect -s '\n' -c 'title' 2>/dev/null
Sen yükleyebilirsiniz hxselectkullanarak 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 curlve grepbunun için. Sen kullanımını askere gerekir PCRE (Perl Uyumlu Normal İfadeler) içinde grepbulduğ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
curlanahtarlar:
-s = sessiz-o - = STDOUT'a çıktı göndergrepanahtarlar:
-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 \nkarakteri 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 grepgerekir. Araç sedbunu 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, curlHTML ( Nokogiri::HTML) aracılığıyla gelen verileri ayrıştırmadır . Yöntem xpathdaha 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 . putsSonra 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 pipile,
easy_install beautifulsoup4
Debian / Ubuntu gibi bazı işletim sistemleri de paketlenmiştir ( python-bs4Debian / Ubuntu'daki paket).
bs4python 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:
metaAlanı property="og:titlenitelik 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 titledoğrudan alanı kullanan başka bir yol (ve daha sonra sondaki - YouTubedizgiyi işaretleyerek).
$ wget -q 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' -O - | \
> pup 'title text{}' | sed 's/ - YouTube$//'
Why Are Bad Words Bad?
--plainseçeneğini kullanmak isteyebilirler .
lynxBu hile ( zsh, bashsö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 lynxayarlayan 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 Psadece tanımlayıcı dosya o değişkenin içeriğini verir 3(yani dosya tanıtıcı yönlendirilir lynxile 'ın stdout'u 3>&1vaşak stdout'u kendisi yönlendirildi iken ile / dev / null).
Sonra lynxkullanıcı basmayı pve 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?