Как я получаю заголовок веб-сайтов с помощью командной строки?

Можно сделать поиск из командной строки:

less -ppattern filename

Или, однажды внутри less, использовать / сопровождаемый Вашим шаблоном, чтобы сделать интерактивный поиск (вперед). n и N повторите поиск во вперед и обратное направление, соответственно. Это - абсолютный минимум, который необходимо знать; существует намного больше команд для более сложных или определенных поисков.

Править: Для ответа на обновленный вопрос в настоящее время нет никакого способа сделать непосредственный возрастающий поиск с less. Вы рассмотрели использование view вместо этого (открывает Vim в режиме только для чтения, использование Ваш - также incsearch установка)? Vim может быть сделан еще более подобным пейджеру с vimpager сценарием.

Некоторая дополнительная информация: существует открытая ошибка на средстве отслеживания ошибки Ubuntu для возрастающей поисковой поддержки, но не похоже, что это идет куда угодно скоро. Кто-то реализовал возрастающую поддержку на ветвлении GitHub, но очевидно Вы оказываетесь перед необходимостью компилировать пользовательское less использовать это.

(И кроме запроса улучшения Ubuntu в настоящее время существует (с 17.05.2016) такой запрос улучшения на чиновнике less bugtracker.)

54
01.12.2013, 13:32
11 ответов
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
  perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'

Можно передать его по каналу к GNU recode если существуют вещи как &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 операционных систем рабочего стола/ноутбука). Другой справедливо переносимые включают GET команда, которая идет perllibwww, который часто устанавливается, lynx -source, и до меньшей степени curl. Другие общие включают links -source, elinks -source, w3m -dump_source, lftp -c cat...

Протокол HTTP и обработка перенаправления

wget может не получить ту же страницу как та это, например, firefox отобразился бы. Причем причина состоит в том, что серверы HTTP могут принять решение отправить другую страницу на основе информации, предоставленной в запросе, отправленном клиентом.

Запрос, отправленный wget/w3m/GET..., будет отличающимся от того, отправленного Firefox. Если это - проблема, можно измениться wget поведение изменить путь это отправляет запрос хотя с опциями.

Самые важные здесь в этом отношении:

  • Accept и Accept-language: это говорит сервер, в котором языке и наборе символов клиент хотел бы вложить ответ. wget не отправляет никого по умолчанию, таким образом, сервер будет обычно отправлять с его настройками по умолчанию. firefox на другом конце, вероятно, настроен для запроса языка.
  • User-Agent: это определяет клиентское приложение к серверу. Некоторые сайты отправляют отличающийся на основе содержимого на клиенте (хотя это главным образом для различий между интерпретациями языка сценариев JavaScript), и может отказаться служить Вам, если Вы используете агент пользователя типа робота как 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 прекратить загружать.

Парсинг HTML

Здесь, wget пишет страница, поскольку она загружает его. В то же время, perl, хлебает его вывод (-0777 -n) целый в памяти и затем печатает HTML-код, который найден между первыми вхождениями <title...> и </title.

Это будет работать на большинство страниц HTML, которые имеют a <title> тег, но существуют случаи, где он не будет работать.

В отличие от этого, решение coffeeMug проанализирует страницу HTML как XML и возвратит соответствующее значение для title. Это более корректно, если страница, как гарантируют, будет допустимым XML. Однако HTML не требуется, чтобы быть допустимым XML (более старые версии языка не были), и потому что большинство браузеров там снисходительно и примет неправильный HTML-код, существует даже много неправильного HTML-кода там.

И мое решение и coffeeMug's перестанет работать для множества угловых случаев, иногда то же, иногда нет.

Например, мой перестанет работать на:

<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 &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

Но веб-клиент также предназначен, чтобы сделать больше преобразований на том коде при отображении заголовка (как, уплотняют некоторые пробелы, удаляют продвижение и запаздывающие). Однако маловероятно, что была бы потребность в этом. Так, как в других случаях, Вам решать решите, стоит ли это усилия.

Набор символов

Перед UTF-8 iso8859-1 раньше был предпочтительным набором символов в сети для символов неASCII, хотя строго говоря они должны были быть записаны как &eacute;. Более поздние версии HTTP и языка HTML добавили возможность указать набор символов в HTTP-заголовках или в заголовках HTML, и клиент может указать наборы символов, которые это принимает. UTF-8 имеет тенденцию быть набором символов по умолчанию в наше время.

Так, это означает, что там, Вы найдете é записанный как &eacute;, как &#233;, как UTF-8 é, (0xc3 0xa9), как iso-8859-1 (0xe9), с для 2 последних, иногда информация о наборе символов в HTTP-заголовках или заголовках HTML (в различных форматах), иногда нет.

wget только получает необработанные байты, это не заботится об их значении как символы, и это не говорит веб-сервер о предпочтительном наборе символов.

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 закодировал страницы.

Подводя итоги

Идеально, то, в чем Вы нуждаетесь здесь, является реальным веб-браузером, чтобы дать Вам информацию. Таким образом, Вам нужно что-то, чтобы сделать Запрос HTTP с надлежащими параметрами, intepret ответ HTTP правильно, полностью интерпретировать HTML-код, как браузер был бы, и возвращать заголовок.

Поскольку я не думаю, что это может быть сделано на командной строке с браузерами, которые я знаю (хотя посмотрите теперь этот прием с lynx), необходимо обратиться к эвристике и приближениям, и тот выше так же хорош как любой.

Можно также хотеть учесть производительность, безопасность... Например, для покрытия всех случаев (например, веб-страница, которая имеет некоторый JavaScript, который вытягивают от стороннего сайта, который устанавливает заголовок или перенаправление к другой странице в рычаге onload), Вам, вероятно, придется реализовать реальный браузер с его dom и механизмами JavaScript, которым, вероятно, придется сделать сотни запросов для единственной страницы HTML, часть из который, пытаясь использовать уязвимости...

В то время как использование regexps для парсинга HTML часто осуждается, вот типичный случай, где это достаточно хорошо для задачи (IMO).

47
27.01.2020, 19:33
  • 1
    Вы, вероятно, хотите завершить заголовок в первой инстанции < так как заголовки, как гарантируют, не будут иметь конечные тэги, и любой другой тег должен вызвать свое завершение. Можно также хотеть разделить новые строки. –  Brian Nickel♦ 01.12.2013, 18:53
  • 2
    не рекомендуется использовать регулярные выражения для парсинга HTML. Когда-либо. Даже в этом случае. Это - дурная привычка. Используйте реальный синтаксический анализатор вместо этого. Существует известный юмористический ответ Stackoverflow об этом... исправление –  Robin Green 01.12.2013, 21:38
  • 3
    @RobinGreen, Что сообщение было об использовании regex для парсинга нерегулярного языка. Существуют протесты, но это - проблема, которая легко уменьшается до регулярного языка. Я рекомендую использовать regex для парсинга HTML. Иногда. В этом случае. –  Brian Nickel♦ 01.12.2013, 22:40
  • 4
    @BrianNickel, даже Firefox не поддерживает заголовок без конечного тэга, таким образом, я не потрудился бы покрывать для этого. –  Stéphane Chazelas 02.12.2013, 12:23
  • 5
    И количество регулярных выражений, которые работают почти на все, является приблизительно 0. –  Robin Green 02.12.2013, 17:20

Можно также попробовать 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)}'.

28
27.01.2020, 19:33
  • 1
    sudo apt-get install html-xml-utils –  coffeMug 01.12.2013, 16:06
  • 2
    Вы, вероятно, захотите добавить -i кому: hxselect также по тем же причинам, что manatwork упомянул в моем A, иначе он не будет соответствовать <TITLE>. –  slm♦ 01.12.2013, 20:09
  • 3
    , который я не нашел, что сделать с сообщением. о нормализации вывода. Нет такой включить hxselect. –  slm♦ 01.12.2013, 20:10
  • 4
    Для Mac OS X народное Домашнее пиво имеет формулу с hxselect в нем. Установка с brew install html-xml-utils. –  Sukima 02.07.2014, 05:15

Можно также использовать curl и grep сделать это. Необходимо будет включить в список использование PCRE (Perl Совместимые Регулярные выражения) в 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 - использование Ruby

В какой-то момент regex перестанет работать в решении этого типа проблемы. Если это произойдет затем, то Вы, вероятно, захотите использовать реальный синтаксический анализатор 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

Вышеупомянутое анализирует данные, которые прибывают через curl как 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 
18
27.01.2020, 19:33
  • 1
    Аккуратное решение! :) –  coffeMug 01.12.2013, 19:44
  • 2
    Парсинг HTML с регулярными выражениями не так прост. Теги, записанные как “<ЗАГОЛОВОК>”, “<заголовок lang=en>”, “<title\n>” не будет подобран Вашим выражением. Еще большая проблема, никакой “<заголовок> \noops\n </заголовок>” не будет. –  manatwork 01.12.2013, 20:00
  • 3
    Попытка проанализировать HTML с помощью regex имеет тенденцию быть осужденной здесь. –  user3490 01.12.2013, 23:50
  • 4
    @slm, <title>Unix\nLinux</title> предназначен, чтобы быть Unix Linux, нет UnixLinux. –  Stéphane Chazelas 02.12.2013, 15:10
  • 5
    +1 Для рубина + nokogiri. Я использовал его для всех видов веб-очистки, это удивительно! –  Rob 02.12.2013, 16:22

Используя простой regex для парсинга HTML наивно. Например, с новыми строками и игнорирующий кодирование специального символа указан в файле. Сделайте правильную вещь и действительно проанализируйте страницу с помощью любого из других реальных синтаксических анализаторов, упомянутых в других ответах, или используйте следующий один лайнер:

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

(Вышеупомянутое включает символ Unicode).

BeautifulSoup обрабатывает много неправильного HTML (например, пропускающий закрывающие тэги) также, который полностью бросил бы упрощенного regexing. Можно установить его в стандартном использовании Python:

pip install beautifulsoup4

или если Вы не имеете pip, с

easy_install beautifulsoup4

Некоторые операционные системы как Debian/Ubuntu также имеют упакованный (python-bs4 пакет на Debian/Ubuntu).

7
27.01.2020, 19:33
  • 1
    bs4 не находится в библиотеке стандарта Python. Необходимо установить его использование easy_install beautfulsoup4 (нет easyinstall bs4). –  Anthon 02.12.2013, 10:07
  • 2
    @Anthon включал Вашу информацию –  Zelda 02.12.2013, 10:20

Это, кажется, возможно с lynx использование этого приема:

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

Поскольку это - реальный веб-браузер, он не страдает от многих ограничений, которые я упоминаю в своем другом ответе.

Здесь, мы используем факт это lynx наборы $LYNX_PRINT_TITLE переменная среды к заголовку текущей страницы при печати страницы.

Выше, мы используем lynx сценарии средства (со сценарием, переданным stdin через heredocument) к:

  1. определите рысь названный "принтер" P это просто производит содержание той переменной к дескриптору файла 3 (что дескриптор файла перенаправляется к lynxstdout с 3>&1 в то время как рысь stdout самостоятельно перенаправляется к/dev/null).
  2. моделируйте пользователя, нажимающего p и Конец (иначе Выбор), и Войдите (^J).
4
27.01.2020, 19:33

Простой способ:

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'
3
27.01.2020, 19:33

Может это и "обман", но один из вариантов - щенок, парсер HTML командной строки .

Вот два способа сделать это:

Используя поле meta со свойством property="og:title attribute

$ 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?
6
27.01.2020, 19:33

Используя 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?
1
27.01.2020, 19:33

Мне понравилась идея Stéphane Chazelas использовать 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-адреса или 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");
1
27.01.2020, 19:33

Примером python3 + beautifulsoup может быть

python3 -c "import bs4, requests; print(bs4.BeautifulSoup(requests.get('http://www.crummy.com/software/BeautifulSoup/bs4/doc/').content).title.text)"
0
27.01.2020, 19:33

Использование ксиделя:

$ xidel -s http://www.youtube.com/watch?v=Dd7dQh8u4Hc --css title
Why Are Bad Words Bad? - YouTube

Если необходимо, apt install xidelили аналогичный.

0
27.01.2020, 19:33

Теги

Похожие вопросы