简而言之,没有简单的解决方案。依赖很少会导致代码难看,反之亦然:代码健壮性会导致更高的依赖要求。
考虑到这一点,下面我描述了一些解决方案,并通过提供每个解决方案的优缺点来总结它们。
方法一
您可以将wget
'-k
选项与一些正则表达式一起使用(阅读有关以这种方式解析 HTML 的更多信息)。
来自 Linux 手册:
-k
--convert-links
After the download is complete, convert the links in the document to
make them suitable for local viewing.
(...)
The links to files that have not been downloaded by Wget will be
changed to include host name and absolute path of the location they
point to.
Example: if the downloaded file /foo/doc.html links to /bar/img.gif
(or to ../bar/img.gif), then the link in doc.html will be modified to
point to http://hostname/bar/img.gif.
一个示例脚本:
#wget needs a file in order for -k to work
tmpfil=$(mktemp);
#-k - convert links
#-q - suppress output
#-O - redirect output to given file
wget http://example.com -k -q -O "$tmpfil";
#-o - print only matching parts
#you could use any other popular regex here
grep -o "http://[^'\"<>]*" "$tmpfil"
#remove unnecessary file
rm "$tmpfil"
优点:
wget
假设您已经安装,在大多数系统上开箱即用。
- 在大多数情况下,这将是足够的解决方案。
缺点:
- 具有正则表达式,由于 HTML 层次模型位于Chomsky 层次结构中的正则表达式之下,因此必然会在一些奇异的页面上中断。
- 您不能传递本地文件系统中的位置;您必须传递工作 URL。
方法二
您可以将 Python 与 BeautifulSoup 一起使用。一个示例脚本:
#!/usr/bin/python
import sys
import urllib
import urlparse
import BeautifulSoup
if len(sys.argv) <= 1:
print >>sys.stderr, 'Missing URL argument'
sys.exit(1)
content = urllib.urlopen(sys.argv[1]).read()
soup = BeautifulSoup.BeautifulSoup(content)
for anchor in soup.findAll('a', href=True):
print urlparse.urljoin(sys.argv[1], anchor.get('href'))
进而:
dummy:~$ ./test.py http://example.com
优点:
- 这是处理 HTML 的正确方法,因为它正确使用了成熟的解析器。
- 异国情调的输出很可能会得到很好的处理。
- 稍加修改后,这种方法适用于文件,而不仅仅是 URL。
- 稍加修改,您甚至可以提供自己的基本 URL。
缺点:
- 它需要 Python。
- 它需要带有自定义包的 Python。
- 您需要手动处理标签和属性,如,
<img src>
等(上面的脚本中没有显示)。<link src>
<script src>
方法 3
您可以使用lynx
. (您在问题中提供的答案中提到了这一点。)示例:
lynx http://example.com/ -dump -listonly -nonumbers
优点:
- 非常简洁的用法。
- 适用于所有类型的 HTML。
缺点:
- 你需要猞猁。
- 尽管您也可以从文件中提取链接,但您无法控制基本 URL,最终会得到
file://localhost/
链接。您可以使用丑陋的技巧来解决此问题,例如手动将<base href="">
标签插入 HTML。