Answers:
wget -qO- 'http://www.youtube.com/watch?v=Dd7dQh8u4Hc' |
perl -l -0777 -ne 'print $1 if /<title.*?>\s*(.*?)\s*<\/title/si'
recode
如果其中包含类似内容<
,则可以将其通过管道传输到GNU :
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
经常安装的libwww 附带的命令lynx -source
,并且程度较小curl
。其他常见的包括links -source
,elinks -source
,w3m -dump_source
,lftp -c cat
...
wget
可能无法获得与例如firefox
将显示的页面相同的页面。原因是HTTP服务器可以根据客户端发送的请求中提供的信息选择发送其他页面。
wget / w3m / GET ...发送的请求将与firefox发送的请求不同。如果这是一个问题,则可以wget
通过选项更改行为,以更改其发送请求的方式。
在这方面最重要的是:
Accept
and 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>
文件前几个字节中的部分中,因此并非最佳选择。如果awk
您的系统上有GNU,则更好的方法是:
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
下载页面时将其写入。同时perl
,,将其输出(-0777 -n
)整体粘贴到内存中,然后打印在第一次出现的<title...>
和之间找到的HTML代码</title
。
这对于具有<title>
标签的大多数HTML页面均适用,但在某些情况下将不起作用。
相比之下,coffeeMug的解决方案会将HTML页面解析为XML,并返回的对应值title
。如果保证页面是有效的XML,则更为正确。但是,HTML并非必须是有效的XML(不是该语言的旧版本),并且由于那里的大多数浏览器都比较宽松,并且会接受不正确的HTML代码,因此那里甚至还有很多不正确的HTML代码。
我的解决方案和coffeeMug的解决方案都会因各种极端情况而失败,有时是相同的,有时不是。
例如,我的将失败:
<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
但是,Web客户端还应在显示标题时对该代码进行更多转换(例如,压缩一些空格,删除前导和尾随的空格)。但是,不太可能需要这样做。因此,与其他情况一样,由您决定是否值得付出努力。
在UTF-8之前,iso8859-1曾经是Web上非ASCII字符的首选字符集,尽管严格说来,它们必须写为é
。HTTP和HTML语言的最新版本增加了在HTTP标头或HTML标头中指定字符集的可能性,并且客户端可以指定其接受的字符集。如今,UTF-8往往是默认的字符集。
因此,这意味着在那里,您会发现é
写为é
,as é
,UTF-8 é
,(0xc3 0xa9),iso-8859-1(0xe9),最后两个是,有时是字符集上的信息在HTTP标头或HTML标头(以不同的格式)中,有时不是。
wget
仅获取原始字节,不关心它们作为字符的含义,也不向Web服务器告知首选字符集。
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编码的页面根本不起作用。
理想情况下,这里您需要的是真正的Web浏览器来为您提供信息。也就是说,您需要执行一些操作以使用适当的参数执行HTTP请求,正确解释HTTP响应,像浏览器一样完全解释HTML代码并返回标题。
由于我认为无法使用已知的浏览器在命令行上完成此操作lynx
(尽管现在可以使用来找到此技巧),因此您必须求助于启发式和近似式,并且上面的方法和其他方法一样好。
您可能还需要考虑性能,安全性...例如,要涵盖所有情况(例如,从第三方网站提取具有某些javascript的网页的网页,该网页设置了标题或将其重定向到onload hook),您可能必须使用dom和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
。
brew install html-xml-utils
。
您也可以使用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+
)。然后将其剥离。
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
随后打印出来。
您还可以使用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(例如,缺少结束标记),这将完全导致简化的正则表达式。您可以使用以下命令将其安装在标准python中:
pip install beautifulsoup4
或者如果你没有pip
,有
easy_install beautifulsoup4
诸如Debian / Ubuntu之类的某些操作系统也对其进行了打包(python-bs4
Debian / Ubuntu上的软件包)。
bs4
不在python标准库中。您必须使用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
选项。
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'
因为这是一个现实生活中的Web浏览器,所以它不受我在其他答案中提到的许多限制的困扰。
在这里,我们使用的事实是在打印页面时lynx
将$LYNX_PRINT_TITLE
环境变量设置为当前页面的标题。
上面,我们提供了一个配置文件(作为管道),该文件定义了一个lynx“打印机” P
,该打印机仅将变量的内容输出到文件描述符3
(该文件描述符lynx
通过3>&1
lynx stdout自身重定向到的stdout。到/ dev / null)。
然后,我们使用lynx
脚本编制工具来模拟用户按下p
,End
(aka select)和Enter
(^J
)。
-accept_all_cookies
否则,lynx会要求用户确认每个cookie。
我喜欢StéphaneChazelas使用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");