Ich möchte ein Befehlszeilenprogramm, das den Titel einer Website druckt. Zum Beispiel:
Alan:~ titlefetcher http://www.youtube.com/watch?v=Dd7dQh8u4Hc
sollte geben:
Why Are Bad Words Bad?
Sie geben ihm die URL und es druckt den Titel aus.
command-line
web
http
Ufoguy
quelle
quelle
Antworten:
Sie können es an GNU weiterleiten,
recode
wenn es Dinge wie<
diese gibt:So entfernen Sie das
- youtube
Teil:Um auf einige der Einschränkungen hinzuweisen:
Portabilität
Es gibt keinen Standardbefehl für HTTP-Abfragen. Vor ein paar Jahrzehnten hätte ich
lynx -source
stattdessen hier empfohlen . Aber heutzutagewget
ist es portabler, da es standardmäßig auf den meisten GNU-Systemen (einschließlich der meisten Linux-basierten Desktop- / Laptop-Betriebssysteme) zu finden ist. Andere ziemlich portable sind derGET
Befehlperl
libwww, der häufiglynx -source
und in geringerem Umfang installiert wirdcurl
. Andere gemeinsam diejenigen umfassenlinks -source
,elinks -source
,w3m -dump_source
,lftp -c cat
...HTTP-Protokoll und Umleitungsbehandlung
wget
erhält möglicherweise nicht die gleiche Seite wie die, die zum Beispielfirefox
angezeigt werden würde. Der Grund dafür ist, dass HTTP-Server basierend auf den Informationen in der vom Client gesendeten Anforderung möglicherweise eine andere Seite senden.Die von wget / w3m / GET ... gesendete Anfrage unterscheidet sich von der von firefox. Wenn dies ein Problem ist, können Sie das
wget
Verhalten ändern, um die Art und Weise zu ändern, in der die Anforderung mit Optionen gesendet wird.Die wichtigsten in dieser Hinsicht sind:
Accept
undAccept-language
: Hiermit wird dem Server mitgeteilt, in welcher Sprache und in welchem Zeichensatz der Client die Antwort erhalten möchte.wget
Standardmäßig wird keine Antwort gesendet, sodass der Server normalerweise mit den Standardeinstellungen sendet.firefox
am anderen Ende ist wahrscheinlich konfiguriert, um Ihre Sprache anzufordern.User-Agent
: Gibt die Clientanwendung gegenüber dem Server an. Einige Websites senden unterschiedliche Inhalte basierend auf dem Client (obwohl dies hauptsächlich auf Unterschiede zwischen den Interpretationen der Javascript-Sprache zurückzuführen ist) und lehnen es möglicherweise ab, Sie zu bedienen, wenn Sie einen Benutzeragenten vom Robotertyp wie verwendenwget
.Cookie
: Wenn Sie diese Seite schon einmal besucht haben, verfügt Ihr Browser möglicherweise über permanente Cookies.wget
wird nicht.wget
wird den Weiterleitungen folgen, wenn sie auf der HTTP-Protokollebene durchgeführt werden, aber da es nicht um den Inhalt der Seite geht, nicht um die von Javascript oder ähnlichen Dingen<meta http-equiv="refresh" content="0; url=http://example.com/">
.Leistungsfähigkeit
Hier haben wir aus Faulheit
perl
den gesamten Inhalt im Speicher gelesen, bevor wir nach dem<title>
Tag gesucht haben. Da sich der Titel in dem<head>
Abschnitt befindet, der sich in den ersten Bytes der Datei befindet, ist dies nicht optimal. Ein besserer Ansatz, wenn GNUawk
auf Ihrem System verfügbar ist, könnte sein:Auf diese Weise hört awk nach dem ersten Lesen auf
</title
und führt beim Verlassen dazu, dasswget
der Download abgebrochen wird.Analyse des HTML
Hier wird
wget
die Seite beim Herunterladen geschrieben. Gleichzeitigperl
schlürft output (-0777 -n
) als Ganzes in den Speicher und druckt dann den HTML-Code, der zwischen den ersten Vorkommen von<title...>
und gefunden wird</title
.Das funktioniert für die meisten HTML-Seiten mit einem
<title>
Tag, aber es gibt Fälle, in denen es nicht funktioniert.Im Gegensatz dazu analysiert die Lösung von coffeeMug die HTML-Seite als XML und gibt den entsprechenden Wert für zurück
title
. Richtiger ist es, wenn garantiert wird, dass die Seite gültiges XML ist . HTML muss jedoch kein gültiges XML sein (ältere Sprachversionen waren dies nicht), und da die meisten Browser mild sind und falschen HTML-Code akzeptieren, gibt es sogar viele falsche HTML-Codes.Sowohl meine Lösung als auch die von coffeeMug scheitern bei einer Vielzahl von Eckfällen , manchmal gleich, manchmal nicht.
Zum Beispiel wird meine am scheitern:
oder:
Während sein wird scheitern:
(gültiges HTML, nicht XML) oder:
oder:
(wieder gültige
html
, fehlende<![CDATA[
Teile, um es als gültiges XML zu kennzeichnen).(Falsches HTML, aber immer noch bekannt und von den meisten Browsern unterstützt)
Interpretation des Codes innerhalb der Tags.
Diese Lösung gibt den Rohtext zwischen
<title>
und aus</title>
. Normalerweise sollten keine HTML-Tags enthalten sein, möglicherweise sind Kommentare vorhanden (obwohl dies von einigen Browsern wie Firefox nicht so wahrscheinlich ist). Möglicherweise ist noch eine HTML-Codierung vorhanden:Um was kümmert sich GNU
recode
:Ein Web-Client ist jedoch auch dazu gedacht, den Code beim Anzeigen des Titels stärker zu transformieren (z. B. einige der Leerzeichen zu komprimieren, die führenden und nachfolgenden zu entfernen). Es ist jedoch unwahrscheinlich, dass dies erforderlich sein wird. Wie in den anderen Fällen müssen Sie entscheiden, ob sich die Mühe lohnt.
Zeichensatz
Vor UTF-8 war iso8859-1 der bevorzugte Zeichensatz im Web für Nicht-ASCII-Zeichen, obwohl genau genommen geschrieben werden musste
é
. Neuere Versionen von HTTP und der HTML-Sprache haben die Möglichkeit hinzugefügt, den Zeichensatz in den HTTP-Headern oder in den HTML-Headern anzugeben, und ein Client kann die Zeichensätze angeben, die er akzeptiert. UTF-8 ist heutzutage der Standardzeichensatz.Das bedeutet also, dass Sie dort draußen
é
alsé
, alsé
, als UTF-8é
, (0xc3 0xa9), als iso-8859-1 (0xe9), mit den 2 letzten, manchmal die Informationen auf dem Zeichensatz finden in den HTTP-Headern oder den HTML-Headern (in verschiedenen Formaten) manchmal nicht.wget
Erhält nur die Rohbytes, kümmert sich nicht um deren Bedeutung als Zeichen und informiert den Webserver nicht über den bevorzugten Zeichensatz.recode html..
kümmert sich darum, dasé
oderé
in die richtige Folge von Bytes für den auf Ihrem System verwendeten Zeichensatz umzuwandeln , aber im übrigen ist das schwieriger.Wenn Ihr Systemzeichensatz utf-8 ist, ist dies wahrscheinlich die meiste Zeit in Ordnung, da dies in der Regel der Standardzeichensatz ist, der heutzutage verwendet wird.
Das
é
oben war ein UTF-8é
.Aber wenn Sie noch einmal andere Zeichensätze abdecken möchten, müssten Sie sich darum kümmern.
Es sollte auch beachtet werden, dass diese Lösung für UTF-16- oder UTF-32-codierte Seiten überhaupt nicht funktioniert.
Um zusammenzufassen
Idealerweise benötigen Sie hier einen echten Webbrowser, der Ihnen die Informationen liefert. Das heißt, Sie müssen die HTTP-Anforderung mit den richtigen Parametern ausführen, die HTTP-Antwort richtig interpretieren, den HTML-Code vollständig interpretieren, wie es ein Browser tun würde, und den Titel zurückgeben.
Da ich glaube, dass dies mit den Browsern, die ich kenne, auf der Kommandozeile nicht möglich ist (obwohl ich diesen Trick
lynx
jetzt sehe ), muss man auf Heuristiken und Annäherungen zurückgreifen, und die obige ist so gut wie jede andere.Vielleicht möchten Sie auch Leistung, Sicherheit usw. berücksichtigen, um alle Fälle abzudecken (z. B. eine Webseite, auf der Javascript von einer Website eines Drittanbieters abgerufen wurde, auf der der Titel oder die Weiterleitung zu einer anderen Seite in einer Website festgelegt ist) onload hook) müssen Sie möglicherweise einen realen Browser mit dom- und javascript-Modulen implementieren, der möglicherweise Hunderte von Abfragen für eine einzelne HTML-Seite ausführen muss, von denen einige versuchen, Schwachstellen auszunutzen ...
Während die Verwendung von regulären Ausdrücken zum Parsen von HTML häufig verpönt ist , ist hier ein typischer Fall, in dem es für die Aufgabe (IMO) gut genug ist.
quelle
<
da für Titel keine End-Tags garantiert sind und jedes andere Tag die Beendigung erzwingen sollte. Möglicherweise möchten Sie auch neue Leitungen entfernen.Sie können
hxselect
(aus HTML-XML-Utils )wget
auch Folgendes versuchen :Sie können installieren
hxselect
Verwendung in Debian - basierten Distributionen:sudo apt-get install html-xml-utils
.Die STDERR-Umleitung dient zum Vermeiden der
Input is not well-formed. (Maybe try normalize?)
Nachricht.Um "- YouTube" loszuwerden, leiten Sie die Ausgabe des obigen Befehls an
awk '{print substr($0, 0, length($0)-10)}'
.quelle
sudo apt-get install html-xml-utils
hxselect
.brew install html-xml-utils
.Sie können dazu auch
curl
undgrep
verwenden. Sie benötigen die Verwendung von gewinnen PCRE (Perl Compatible Regular Expressions) ingrep
erhalten den Blick hinter und Vorgriff Einrichtungen , so dass wir die finden<title>...</title>
Tags.Beispiel
Einzelheiten
Die
curl
Schalter:-s
= leise-o -
= Ausgabe an STDOUT sendenDie
grep
Schalter:-i
= Groß- / Kleinschreibung-o
= Nur den Teil zurückgeben, der passt-P
= PCRE-ModusDas Muster zu
grep
:(?<=<title>)
= suche nach einer Zeichenkette, die links davon beginnt(?=</title>)
= suche nach einer Zeichenkette, die rechts davon endet(.*)
= alles dazwischen<title>..</title>
.Komplexere Situationen
Wenn es sich
<title>...</titie>
über mehrere Zeilen erstreckt, wird es von den oben genannten nicht gefunden. Sie können diese Situation abmildern, indem Sietr
beliebige\n
Zeichen löschen , ztr -d '\n'
.Beispiel
Beispieldatei.
Und ein Probelauf:
lang = ...
Wenn der
<title>
so eingestellt ist, müssen<title lang="en">
Sie ihn entfernen, bevorgrep
Sie ihn verwenden können. Das Toolsed
kann dazu verwendet werden:Oben wird die Zeichenfolge ohne Berücksichtigung der Groß- und Kleinschreibung
lang=
gefolgt von einer Wortfolge (\w+
) gefunden. Es wird dann ausgezogen.Ein echter HTML / XML-Parser - mit Ruby
Irgendwann gelingt es regex nicht mehr, diese Art von Problem zu lösen. In diesem Fall möchten Sie wahrscheinlich einen echten HTML / XML-Parser verwenden. Ein solcher Parser ist Nokogiri . Es ist in Ruby als Gem verfügbar und kann folgendermaßen verwendet werden:
Das obige analysiert die Daten, die über
curl
as HTML (Nokogiri::HTML
) kommen. Die Methodexpath
sucht dann im HTML nach Knoten (Tags), die Blattknoten (//
) mit dem Namen sindtitle
. Für jedes gefundene Objekt möchten wir dessen Inhalt zurückgeben (e.content
). Dasputs
druckt sie dann aus.Ein echter HTML / XML-Parser - mit Perl
Ähnliches können Sie auch mit Perl und dem HTML :: TreeBuilder :: XPath- Modul tun .
Sie können dieses Skript dann folgendermaßen ausführen:
quelle
<title>Unix\nLinux</title>
soll seinUnix Linux
, nichtUnixLinux
.Die Verwendung von einfachem Regex zum Parsen von HTML ist naiv. ZB mit Zeilenumbrüchen und Ignorieren der in der Datei angegebenen Sonderzeichencodierung. Tun Sie das Richtige und analysieren Sie die Seite wirklich mit einem der anderen echten Parser, die in den anderen Antworten aufgeführt sind, oder verwenden Sie den folgenden Zeilenumbruch:
(Das Obige enthält ein Unicode-Zeichen).
BeautifulSoup handhabt auch eine Menge von falschem HTML (z. B. fehlende schließende Tags), was eine völlig vereinfachte Regex-Darstellung zur Folge hätte. Sie können es in einem Standard-Python installieren, indem Sie Folgendes verwenden:
oder wenn nicht
pip
, mitEinige Betriebssysteme wie Debian / Ubuntu haben es auch gepackt (
python-bs4
Paket unter Debian / Ubuntu).quelle
bs4
ist nicht in der Python-Standardbibliothek. Sie müssen es miteasy_install beautfulsoup4
(nichteasyinstall bs4
) installieren .Vielleicht ist es "Betrug", aber eine Option ist pup, ein HTML-Parser für die Befehlszeile .
Hier sind zwei Möglichkeiten:
Verwendung des
meta
Feldes mitproperty="og:title
Attributund eine andere Möglichkeit, das
title
Feld direkt zu verwenden (und dann die- YouTube
Zeichenfolge am Ende zu entfernen ).quelle
--plain
Option pup verwenden .lynx
Mit diesem Trick (zsh
,bash
Syntax) scheint es möglich zu sein :Da es sich um einen echten Webbrowser handelt, leidet er nicht unter den Einschränkungen, die ich in meiner anderen Antwort erwähne .
Hier verwenden wir die Tatsache, dass
lynx
die$LYNX_PRINT_TITLE
Umgebungsvariable beim Drucken der Seite auf den Titel der aktuellen Seite gesetzt wird.Oben sehen Sie eine Konfigurationsdatei (als Pipe), die einen Lynx - "Drucker" definiert
P
, der nur den Inhalt dieser Variablen an den Dateideskriptor ausgibt3
(dieser Dateideskriptor wird mit anlynx
die Standardausgabe umgeleitet,3>&1
während lynx stdout selbst umgeleitet wird nach / dev / null).Dann verwenden wir die
lynx
Scripting-Funktion, um das Drücken des Benutzersp
und dieEnd
Tasten (aka select) undEnter
(^J
) zu simulieren .-accept_all_cookies
da ansonsten lynx den benutzer für jedes cookie um bestätigung bitten würde.quelle
Einfacher Weg:
Einige Alternativen:
quelle
Ich mochte die Idee von Stéphane Chazelas, Lynx und LYNX_PRINT_TITLE zu verwenden, aber dieses Skript funktionierte unter Ubuntu 14.04.5 nicht für mich.
Ich habe eine vereinfachte Version davon erstellt, indem ich Lynx ausgeführt und im Voraus vorkonfigurierte Dateien verwendet habe.
Fügen Sie die folgende Zeile zu /etc/lynx-cur/lynx.cfg hinzu (oder wo immer sich Ihre lynx.cfg befindet):
Diese Zeile weist Sie an, den Titel während des Druckvorgangs unter "/home/account/title.txt" zu speichern. Sie können einen beliebigen Dateinamen auswählen. Sie fordern SEHR große Seiten an. Erhöhen Sie den obigen Wert von "1000" auf eine beliebige Anzahl von Zeilen pro Seite. Andernfalls gibt Lynx eine zusätzliche Aufforderung aus, "wenn Sie ein Dokument drucken, das eine sehr große Anzahl von Seiten enthält".
Erstellen Sie dann die Datei /home/account/lynx-script.txt mit folgendem Inhalt:
Führen Sie dann Lynx mit den folgenden Befehlszeilenoptionen aus:
Nach Abschluss dieses Befehls wird die Datei /home/account/title.txt mit dem Titel Ihrer Seite erstellt.
Kurz gesagt, hier ist eine PHP-Funktion, die einen Seitentitel basierend auf der angegebenen URL zurückgibt oder im Fehlerfall false.
quelle
Mit nokogiri kann man eine einfache CSS-basierte Abfrage verwenden, um den inneren Text des Tags zu extrahieren:
So extrahieren Sie den Wert des Attributs "content" des Tags:
quelle