Chcę program wiersza polecenia, który wypisuje tytuł strony internetowej. Na przykład:
Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc
powinien dać:
Why Are Bad Words Bad?
Dajesz mu adres URL i wypisuje tytuł.
command-line
web
http
Ufoguy
źródło
źródło
Odpowiedzi:
Możesz przesłać go do GNU,
recode
jeśli są<
w nim takie rzeczy :Aby usunąć
- youtube
część:Aby wskazać niektóre ograniczenia:
ruchliwość
Nie ma standardowego / przenośnego polecenia do wykonywania zapytań HTTP. Kilka dekad temu poleciłbym
lynx -source
zamiast tego tutaj. Ale obecniewget
jest bardziej przenośny, ponieważ można go domyślnie znaleźć w większości systemów GNU (w tym w większości systemów operacyjnych Linux / stacjonarnych / laptopów). Inne dość przenośne obejmująGET
polecenie, które jest dostarczane zperl
libwww, które jest często instalowanelynx -source
, i w mniejszym stopniucurl
. Inne popularne z nich tolinks -source
,elinks -source
,w3m -dump_source
,lftp -c cat
...Protokół HTTP i obsługa przekierowań
wget
może nie uzyskać tej samej strony, co na przykładfirefox
wyświetlana strona. Powodem jest to, że serwery HTTP mogą wybrać wysłanie innej strony na podstawie informacji podanych w żądaniu przesłanym przez klienta.Żądanie wysłane przez wget / w3m / GET ... będzie inne niż żądanie wysłane przez firefox. Jeśli to jest problem, możesz zmienić
wget
zachowanie, aby zmienić sposób, w jaki wysyła żądanie, z opcjami.Najważniejszymi tutaj w tym zakresie są:
Accept
iAccept-language
: informuje serwer, w którym języku i zestawie znaków klient chce uzyskać odpowiedź.wget
Domyślnie nie wysyła żadnego, więc serwer zwykle wysyła ustawienia z domyślnymi ustawieniami.firefox
na drugim końcu jest prawdopodobnie skonfigurowany do żądania twojego języka.User-Agent
: która identyfikuje aplikację kliencką na serwerze. Niektóre witryny wysyłają różne treści w zależności od klienta (chociaż są to głównie różnice między interpretacjami języka javascript) i mogą odmówić obsługi, jeśli używasz agenta użytkownika typu robotwget
.Cookie
: jeśli odwiedziłeś tę stronę wcześniej, Twoja przeglądarka może mieć do niej trwałe pliki cookie.wget
nie będzie.wget
będzie podążał za przekierowaniami, gdy zostaną wykonane na poziomie protokołu HTTP, ale ponieważ nie patrzy on na zawartość strony, nie na te wykonane przez javascript lub coś podobnego<meta http-equiv="refresh" content="0; url=http://example.com/">
.Wydajność / wydajność
Tutaj, z lenistwa,
perl
przeczytaliśmy całą zawartość w pamięci, zanim zaczęliśmy szukać<title>
tagu. Biorąc pod uwagę, że tytuł znajduje się w<head>
sekcji znajdującej się w pierwszych kilku bajtach pliku, nie jest to optymalne. Lepszym podejściem, jeśli GNUawk
jest dostępny w twoim systemie, może być:W ten sposób awk przestaje czytać po pierwszym
</title
, a po wyjściu powodujewget
zatrzymanie pobierania.Analiza kodu HTML
Tutaj
wget
zapisuje stronę podczas jej pobierania. W tym samym czasieperl
slurps swoje wyjście (-0777 -n
) w całości, a następnie drukuje kod HTML znaleziony między pierwszymi wystąpieniami<title...>
i</title
.Będzie to działać na większości stron HTML z
<title>
tagiem, ale są przypadki, w których nie będzie działać.Dla kontrastu rozwiązanie coffeeMug parsuje stronę HTML jako XML i zwraca odpowiednią wartość dla
title
. Bardziej poprawne jest, jeśli strona ma gwarancję poprawności XML . Jednak HTML nie musi być poprawnym XML (starsze wersje języka nie były), a ponieważ większość przeglądarek jest łagodna i akceptuje niepoprawny kod HTML, istnieje nawet wiele niepoprawnych kodów HTML.Zarówno moje rozwiązanie, jak i CoffeeMug's zawiodą w różnych przypadkach narożnych, czasem takich samych, a czasem nie.
Na przykład mój nie powiedzie się:
lub:
Podczas gdy jego zawiedzie:
(ważny HTML, nie XML) lub:
lub:
(ponownie, poprawne
html
, brakujące<![CDATA[
części, aby uczynić go prawidłowym XML).(niepoprawny HTML, ale nadal się tam znajduje i obsługiwany przez większość przeglądarek)
interpretacja kodu wewnątrz tagów.
To rozwiązanie generuje nieprzetworzony tekst pomiędzy
<title>
i</title>
. Zwykle nie powinno być tam żadnych tagów HTML, mogą być tam komentarze (choć nie są obsługiwane przez niektóre przeglądarki, takie jak Firefox, więc jest to bardzo mało prawdopodobne). Nadal może być trochę kodowania HTML:Tym zajmuje się GNU
recode
:Ale klient WWW ma również na celu wykonanie większej liczby transformacji tego kodu podczas wyświetlania tytułu (np. Zagęszczenie niektórych odstępów, usunięcie wiodących i końcowych). Jest jednak mało prawdopodobne, że będzie to potrzebne. Tak jak w innych przypadkach, to Ty decydujesz, czy warto.
Zestaw znaków
Przed UTF-8, iso8859-1 był preferowanym zestawem znaków w sieci dla znaków spoza ASCII, choć ściśle mówiąc, musiały być napisane jako
é
. Nowsze wersje HTTP i języka HTML dodają możliwość określenia zestawu znaków w nagłówkach HTTP lub w nagłówkach HTML, a klient może określić akceptowane przez siebie zestawy znaków. UTF-8 jest obecnie domyślnym zestawem znaków.Oznacza to, że na zewnątrz znajdziesz
é
zapisany jakoé
, jakoé
, jako UTF-8é
, (0xc3 0xa9), jako iso-8859-1 (0xe9), dla dwóch ostatnich, czasem informacje o zestawie znaków w nagłówkach HTTP lub HTML (w różnych formatach), czasem nie.wget
pobiera tylko nieprzetworzone bajty, nie dba o ich znaczenie jako znaków i nie informuje serwera WWW o preferowanym zestawie znaków.recode html..
zadba o konwersjęé
lubé
na odpowiednią sekwencję bajtów dla zestawu znaków używanego w systemie, ale dla reszty jest to trudniejsze.Jeśli twój systemowy zestaw znaków to utf-8, są szanse, że będzie w porządku przez większość czasu, ponieważ zwykle jest to domyślny zestaw znaków używany obecnie.
Że
é
wyżej był UTF-8é
.Ale jeśli chcesz ukryć inne zestawy znaków, po raz kolejny trzeba będzie się tym zająć.
Należy również zauważyć, że to rozwiązanie w ogóle nie będzie działać na stronach kodowanych w UTF-16 lub UTF-32.
Podsumowując
Idealnie, czego potrzebujesz tutaj, jest prawdziwa przeglądarka internetowa zapewniająca informacje. Oznacza to, że potrzebujesz czegoś, aby wykonać żądanie HTTP z odpowiednimi parametrami, poprawnie zinterpretować odpowiedź HTTP, w pełni zinterpretować kod HTML tak jak przeglądarka i zwrócić tytuł.
Ponieważ nie sądzę, że można tego dokonać w wierszu poleceń za pomocą przeglądarek, które znam (choć teraz widzę tę sztuczkę
lynx
), musisz uciekać się do heurystyki i przybliżeń, a powyższa jest równie dobra jak każda inna.Możesz również wziąć pod uwagę wydajność, bezpieczeństwo ... Na przykład, aby objąć wszystkie przypadki (na przykład stronę internetową, na której pobierany jest skrypt javascript z witryny innej firmy, która ustawia tytuł lub przekierowuje na inną stronę w onload hook), być może będziesz musiał wdrożyć prawdziwą przeglądarkę z jej silnikami dom i javascript, które mogą wymagać setek zapytań dla pojedynczej strony HTML, z których niektóre próbują wykorzystać luki ...
Podczas gdy używanie wyrażeń regularnych do analizowania HTML jest często odrzucane , tutaj jest typowy przypadek, w którym jest wystarczająco dobry do zadania (IMO).
źródło
<
ponieważ nie ma gwarancji, że tytuły zawierają znaczniki końcowe, a jakikolwiek inny znacznik powinien wymusić jego zakończenie. Możesz także chcieć usunąć nowe linie.Możesz także spróbować
hxselect
(z HTML-XML-Utils )wget
w następujący sposób:Można zainstalować
hxselect
w Debianie dystrybucjach opartych przy użyciu:sudo apt-get install html-xml-utils
.Przekierowanie STDERR ma na celu uniknięcie
Input is not well-formed. (Maybe try normalize?)
wiadomości.Aby pozbyć się „- YouTube”, potokuj wyjście powyższego polecenia do
awk '{print substr($0, 0, length($0)-10)}'
.źródło
sudo apt-get install html-xml-utils
hxselect
.brew install html-xml-utils
.Możesz także użyć
curl
igrep
do tego. Trzeba zaciągnąć użycie PCRE (pcre) wgrep
celu uzyskania wyglądu tyłu i patrzeć w przyszłość obiektów tak, że możemy znaleźć<title>...</title>
tagi.Przykład
Detale
Te
curl
przełączniki:-s
= cichy-o -
= wyślij wyjście do STDOUTTe
grep
przełączniki:-i
= niewrażliwość na wielkość liter-o
= Zwróć tylko część pasującą-P
= Tryb PCREWzór do
grep
:(?<=<title>)
= poszukaj łańcucha rozpoczynającego się od tego po jego lewej stronie(?=</title>)
= poszukaj łańcucha, który kończy się tym po prawej stronie(.*)
= wszystko pomiędzy<title>..</title>
.Bardziej złożone sytuacje
Jeśli
<title>...</titie>
obejmuje wiele linii, powyższe go nie znajdzie. Możesz zaradzić tej sytuacji za pomocątr
, aby usunąć dowolne\n
znaki, tjtr -d '\n'
.Przykład
Przykładowy plik.
I przykładowy przebieg:
lang = ...
Jeśli
<title>
jest ustawiony w ten sposób,<title lang="en">
musisz go usunąć przedgrep
opublikowaniem. Do tegosed
celu można użyć narzędzia :Powyżej znajduje ciąg bez rozróżniania wielkości liter,
lang=
po którym następuje sekwencja słów (\w+
). Następnie jest usuwany.Prawdziwy parser HTML / XML - używając Ruby
W pewnym momencie wyrażenie regularne nie powiedzie się w rozwiązaniu tego rodzaju problemu. Jeśli tak się stanie, prawdopodobnie będziesz chciał użyć prawdziwego parsera HTML / XML. Jednym z takich parserów jest Nokogiri . Jest dostępny w Ruby jako klejnot i może być używany w następujący sposób:
Powyżej analizowane są dane przychodzące przez
curl
as HTML (Nokogiri::HTML
). Następnie metodaxpath
szuka węzłów (znaczników) w kodzie HTML, które są węzłami liści (//
) o nazwietitle
. Dla każdego znalezionego chcemy zwrócić jego zawartość (e.content
).puts
Następnie drukuje je.Prawdziwy parser HTML / XML - używając Perla
Możesz także zrobić coś podobnego z Perlem i modułem HTML :: TreeBuilder :: XPath .
Następnie możesz uruchomić ten skrypt w następujący sposób:
źródło
<title>Unix\nLinux</title>
ma byćUnix Linux
, nieUnixLinux
.Używanie prostego wyrażenia regularnego do analizowania HTML jest naiwne. Np. Z nowymi liniami i ignorowaniem kodowania znaków specjalnych określonych w pliku. Postępuj właściwie i naprawdę parsuj stronę, używając jednego z innych prawdziwych parserów wymienionych w innych odpowiedziach lub użyj następującego linera:
(Powyższe obejmuje znak Unicode).
BeautifulSoup obsługuje również wiele niepoprawnych plików HTML (np. Brakujących tagów zamykających), co całkowicie uprościłoby proste wyrażenia regularne. Możesz zainstalować go w standardowym pythonie, używając:
lub jeśli nie masz
pip
, zNiektóre systemy operacyjne, takie jak Debian / Ubuntu, również mają to w pakiecie (
python-bs4
pakiet na Debian / Ubuntu).źródło
bs4
nie ma w standardowej bibliotece Pythona. Musisz go zainstalować przy użyciueasy_install beautfulsoup4
(nieeasyinstall bs4
).Może to „oszukiwanie”, ale jedną z opcji jest pup, parser HTML wiersza poleceń .
Oto dwa sposoby, aby to zrobić:
Używanie
meta
pola zproperty="og:title
atrybutemi inny sposób, używając
title
pola bezpośrednio (a następnie odciąć- YouTube
ciąg na końcu).źródło
--plain
opcji pup .To wydaje się być możliwe z
lynx
użyciem tego triku (zsh
,bash
składni):Ponieważ jest to prawdziwa przeglądarka internetowa, nie ma wielu ograniczeń, o których wspominam w innej odpowiedzi .
Korzystamy z faktu, że podczas drukowania strony
lynx
ustawia$LYNX_PRINT_TITLE
zmienną środowiskową na tytuł bieżącej strony.Powyżej podajemy plik konfiguracyjny (jako potok), który definiuje wywoływaną „drukarkę” rysia,
P
która po prostu przekazuje zawartość tej zmiennej do deskryptora pliku3
(ten deskryptor pliku jest przekierowywany na standardowelynx
wyjście,3>&1
podczas gdy sam Lynx jest przekierowywany na / dev / null).Następnie używamy narzędzia
lynx
skryptowego do symulacji naciskania użytkownikap
orazEnd
(aka select) iEnter
(^J
).-accept_all_cookies
w przeciwnym razie ryś poprosiłby użytkownika o potwierdzenie każdego pliku cookie.źródło
Prosta droga:
Kilka alternatyw:
źródło
Podobał mi się pomysł Stéphane'a Chazelasa na używanie Lynxa i LYNX_PRINT_TITLE, ale ten skrypt nie działał dla mnie w Ubuntu 14.04.5.
Stworzyłem uproszczoną wersję, używając programu Lynx i plików wstępnie skonfigurowanych.
Dodaj następujący wiersz do /etc/lynx-cur/lynx.cfg (lub gdziekolwiek znajduje się plik lynx.cfg):
Ten wiersz nakazuje zapisanie tytułu podczas drukowania do „/home/account/title.txt” - możesz wybrać dowolną nazwę pliku. Żądasz BARDZO dużych stron, zwiększ powyższą wartość z „1000” do dowolnej liczby wierszy na żądanej stronie, w przeciwnym razie Lynx wyświetli dodatkowy monit „podczas drukowania dokumentu zawierającego bardzo dużą liczbę stron”.
Następnie utwórz plik /home/account/lynx-script.txt z następującą zawartością:
Następnie uruchom Lynx, używając następujących opcji wiersza polecenia:
Po zakończeniu tego polecenia zostanie utworzony plik /home/account/title.txt z tytułem strony.
Krótko mówiąc, tutaj jest funkcja PHP, która zwraca tytuł strony na podstawie podanego adresu URL lub fałsz w przypadku błędu.
źródło
Używając nokogiri, można użyć prostego zapytania opartego na CSS, aby wyodrębnić wewnętrzny tekst znacznika:
Podobnie, aby wyodrębnić wartość atrybutu „content” tagu:
źródło