Я хочу, щоб програма командного рядка друкувала заголовок веб-сайту. Наприклад:
Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc
повинен дати:
Why Are Bad Words Bad?
Ви надаєте йому URL-адресу, і вона виводить заголовок.
Я хочу, щоб програма командного рядка друкувала заголовок веб-сайту. Наприклад:
Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc
повинен дати:
Why Are Bad Words Bad?
Ви надаєте йому URL-адресу, і вона виводить заголовок.
Відповіді:
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'
Ви можете передавати його GNU, recodeякщо в ньому є такі речі <:
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). Інші досить портативні пристрої включають GETкоманду, яка постачається з perl's libwww, яка часто встановлюється lynx -source, і в меншій мірі curl. Інші поширені з них включають в себе links -source, elinks -source, w3m -dump_source, lftp -c cat...
wgetможе не отримати ту саму сторінку, що та, firefoxяка відображатиметься, наприклад. Причина полягає в тому, що сервери HTTP можуть вирішити надіслати іншу сторінку на основі інформації, наданої у запиті, надісланому клієнтом.
Запит, надісланий wget / w3m / GET ..., відрізнятиметься від запиту, надісланого Firefox. Якщо це проблема, ви можете змінити wgetповедінку, щоб змінити спосіб надсилання запиту, хоча і за допомогою параметрів.
Найважливішими з цього приводу є:
Acceptі Accept-language: це вказує серверу, якою мовою та діаграмою клієнт хотів би отримати відповідь. wgetЗа замовчуванням не надсилає жодних, тому сервер зазвичай надсилає свої налаштування за замовчуванням. firefoxз іншого боку, ймовірно, налаштовано на запит вашої мови.User-Agent: що ідентифікує клієнтську програму на сервері. Деякі сайти відправити інший зміст , засноване на клієнті (хоча це в основному відмінність між яваскрипт мовних інтерпретаціями) і може відмовитися служити вам , якщо ви використовуєте робот -типу агент користувача як wget.Cookie: якщо ви раніше відвідували цей сайт, у вашому веб-переглядачі можуть бути постійні файли cookie. wgetне буде.wgetбуде виконувати переадресації, коли вони будуть виконані на рівні протоколу HTTP, але оскільки він не розглядає зміст сторінки, а не ті, які виконуються через JavaScript або подібні речі <meta http-equiv="refresh" content="0; url=http://example.com/">.
Тут із ліні ми 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до припинення завантаження.
Тут wgetпише сторінка під час її завантаження. У той же час, perlSururs його вихід ( -0777 -n) ціле в пам'яті, а потім друкує HTML-код, який знаходиться між першими входженнями <title...>та </title.
Це буде працювати для більшості HTML-сторінок, на яких є <title>тег, але є випадки, коли він не працює.
На противагу цьому рішення CoffeeMug розбере HTML сторінку як XML та поверне відповідне значення для title. Це правильніше, якщо сторінка гарантує дійсність XML . Однак HTML не обов'язковий, щоб він був дійсним XML (старіші версії мови не були), а оскільки більшість браузерів там поблажливіші і приймають неправильний HTML-код, там навіть багато неправильного HTML-коду.
Як моє рішення, так і кава-Маг не вдасться в різних кутових випадках, іноді одних і тих же, іноді ні.
Наприклад, у мене не вдасться:
<html><head foo="<title>"><title>blah</title></head></html>
або:
<!-- <title>old</title> --><title>new</title>
Поки його не вдасться:
<TITLE>foo</TITLE>
(дійсний html, не xml) або:
або:
<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 & 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
Але веб-клієнт також має на увазі зробити більше перетворень цього коду під час відображення заголовка (наприклад, ущільнити деякі пробіли, видалити провідні та зворотні). Однак навряд чи буде в цьому потреба. Отже, як і в інших випадках, вирішувати, чи варто докладати зусиль, вирішувати.
До UTF-8 переважним шаблоном в Інтернеті для символів, що не належать до ASCII, був iso8859-1, хоча строго кажучи, їх потрібно було писати як é. Більш новітні версії HTTP та мови HTML додали можливість задавати набір символів у заголовках HTTP або в заголовках HTML, і клієнт може вказати схеми, які він приймає. На сьогодні UTF-8, як правило, є набором даних за замовчуванням.
Отже, це означає, що там ви знайдете éнаписані як é, як éUTF-8 é, (0xc3 0xa9), як iso-8859-1 (0xe9), з двома останніми, іноді інформацією на графіці у заголовках HTTP або заголовках HTML (у різних форматах), іноді немає.
wget отримує лише неочищені байти, він не дбає про їх значення як символи, і не повідомляє веб-серверу про бажану схему.
recode html..подбає про перетворення éабо éв належну послідовність байтів для набору символів, використовуваних у вашій системі, але для решти, це складніше.
Якщо ваш системний набір - 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'appartement - YouTube
Це éбуло UTF-8 é.
Але якщо ви хочете прикрити інші шаблони, про це слід подбати ще раз.
Слід також зазначити, що це рішення взагалі не працюватиме на кодованих сторінках UTF-16 або UTF-32.
В ідеалі, що вам тут потрібно, це справжній веб-браузер, який дає вам інформацію. Тобто вам потрібно щось зробити для HTTP-запиту з належними параметрами, правильно інтерпретувати відповідь HTTP, повністю інтерпретувати HTML-код як браузер і повернути заголовок.
Оскільки я не думаю, що це можна зробити в командному рядку з відомими мені браузерами (хоча дивіться зараз цей трюкlynx ), ви повинні вдатися до евристики та наближень, і те, що вище, так само добре, як і будь-яке.
Ви також можете взяти до уваги продуктивність, безпеку ... Наприклад, щоб охопити всі випадки (наприклад, веб-сторінку, яка має деякий javascript, витягнутий із стороннього сайту, який встановлює заголовок або перенаправляє на іншу сторінку в при завантаженні гачка), можливо, вам доведеться реалізувати браузер у реальному житті зі своїми системами dom та javascript, які, можливо, повинні робити сотні запитів для однієї сторінки HTML, деякі з яких намагаються використовувати вразливості ...
У той час як використання регулярних выражень для розбору HTML часто піддається нахабству , ось типовий випадок, коли він достатньо хороший для виконання завдання (IMO).
<оскільки в заголовках не гарантується наявність кінцевих тегів, а будь-який інший тег повинен змусити його припинити. Можливо, ви також хочете зняти нові лінії.
Ви також можете спробувати hxselect(з HTML-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)}'.
sudo apt-get install html-xml-utils
hxselect.
Ви також можете використовувати 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
Якщо значення <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-аналізатор. Одним з таких аналізаторів є Nokogiri . Він доступний в Ruby як дорогоцінний камінь і може використовуватися так:
$ 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
Вище описано аналіз даних, що надходять через curlHTML ( Nokogiri::HTML). Потім метод xpathшукає у HTML вузлах (тегах), які є вузлами листя, ( //) з назвою title. Для кожного знайденого ми хочемо повернути його вміст ( e.content). putsПотім друкує їх.
Ви також можете зробити щось подібне за допомогою 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
<title>Unix\nLinux</title>покликаний бути Unix Linux, ні UnixLinux.
Використання простого регулярного вираження для розбору HTML наївно. Наприклад, з новими рядками та ігноруванням спеціального кодування символів, зазначеного у файлі. Зробіть правильно і дійсно проаналізуйте сторінку, використовуючи будь-який з інших реальних аналізаторів, згаданих в інших відповідях, або скористайтеся наступним вкладишем:
python -c "import bs4, urllib2; print bs4.BeautifulSoup(urllib2.urlopen('http://www.crummy.com/software/BeautifulSoup/bs4/doc/')).title.text"
(Сказане вище включає символ Unicode).
BeautifulSoup також обробляє безліч невірних HTML (наприклад, відсутні теги закриття), які б повністю кинули спрощене повторне вирівнювання. Ви можете встановити його в стандартний пітон, використовуючи:
pip install beautifulsoup4
або якщо у вас немає pip, с
easy_install beautifulsoup4
Деякі операційні системи, такі як Debian / Ubuntu, також мають її в упаковці ( python-bs4пакет на Debian / Ubuntu).
bs4відсутня в стандартній бібліотеці пітона. Ви повинні встановити його за допомогою easy_install beautfulsoup4(не easyinstall bs4).
Можливо, це "обман", але одним із варіантів є " pup", аналізатор командного рядка HTML .
Ось два способи зробити це:
Використання 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?
--plainпараметром pup .
Здається, це можливо за lynxдопомогою цього фокусу ( zsh, bashсинтаксису):
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'
Оскільки це веб-браузер у реальному житті, він не зазнає багатьох обмежень, про які я згадую в своїй іншій відповіді .
Тут ми використовуємо той факт, що lynxвстановлює $LYNX_PRINT_TITLEзмінну середовища на заголовок поточної сторінки при друку сторінки.
Вище ми надаємо файл конфігурації (як трубу), який визначає рись "принтер", який називається, Pщо просто виводить вміст цієї змінної в дескриптор файлу 3( дескриптор цього файлу перенаправляється на lynxstdout з 's, 3>&1поки lydx stdout сам перенаправляється до / dev / null).
Тоді ми використовуємо інструмент lynxсценаріїв для імітації натискання користувача p, а також End(виберіть) і Enter( ^J).
-accept_all_cookies оскільки в іншому випадку рись попросить у користувача підтвердження для кожного файлу cookie.
Простий спосіб:
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'
Мені сподобалася ідея Стефана Шазеласа використовувати Lynx та LYNX_PRINT_TITLE, але цей сценарій не працював для мене під 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 із заголовком вашої сторінки.
Коротше кажучи, ось функція PHP, яка повертає заголовок сторінки на основі вказаної URL-адреси або помилковий у випадку помилки.
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, ви можете отримати простий запит на основі 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?