爬取网站并仅返回URL

71

我正在寻找一种伪蜘蛛爬取网站的方法,关键是我实际上不需要内容,而只需要一个URI列表。我可以使用Wget--spider选项来接近这个想法,但当将输出通过grep进行管道处理时,我似乎无法找到正确的方法让它工作:

wget --spider --force-html -r -l1 http://somesite.com | grep 'Saving to:'

grep 过滤器似乎对 wget 输出没有任何影响。我是弄错了还是应该尝试另一个更适合提供这种有限结果集的工具?

更新

所以我刚刚离线发现,wget 默认写入到 stderr。我在手册页中错过了这一点(事实上,如果它在那里的话,我仍然没有找到)。一旦我将返回内容导向 stdout,我就更接近我需要的结果了:

wget --spider --force-html -r -l1 http://somesite.com 2>&1 | grep 'Saving to:'

如果存在其他更好的方法来完成这种事情,我仍然很感兴趣。


请参考以下问题/答案,使用Python脚本的另一种方法:https://dev59.com/8Wkw5IYBdhLWcg3w6ewb - Adam F
可能是重复的问题:从网站获取URL列表 - Ciro Santilli OurBigBook.com
3个回答

67

我最不想做的事情是下载并解析所有的内容(即创建自己的爬虫)。当我了解到Wget默认会将输出写入stderr时,我就可以将其重定向到stdout并适当地过滤输出。

wget --spider --force-html -r -l2 $url 2>&1 \
  | grep '^--' | awk '{ print $3 }' \
  | grep -v '\.\(css\|js\|png\|gif\|jpg\)$' \
  > urls.m3u

这个命令会给我一个内容资源列表的URI(不包括图片、CSS或JS源文件),这些URI是爬虫程序抓取到的。从那里,我可以将这些URI发送给第三方工具进行处理以满足我的需求。

输出结果仍需要进行一些简单的优化(如上所示,它会产生重复项),但它已经接近完成了,我不需要自己进行任何解析。


5
wget -r --spider -l1 -A mp3 http://example.com/page-with-mp3s 2>&1 | grep -Eio http.+mp3 对我真的很有帮助,谢谢!它可以爬取网页上所有的mp3文件链接。 - AKX
4
我通常将该输出传递给 sort | uniq 来去除重复项,供你参考。 - AL the X
2
我知道这个答案已经过去了5年,但你能加快这个过程吗?对于有200个URL的网站来说,它需要几秒钟甚至几分钟的时间。 - erdomester
如果您使用单个egrep -o 'https?://[^ ]+'替换第一个grepawk命令,可以大大缩短时间。我也建议将其传输到sort | uniq,因为这可以减少第三方工具在重复URL上的工作量。 - Volomike

25
创建一些正则表达式以从所有地址中提取地址。
<a href="(ADDRESS_IS_HERE)">.

以下是我会使用的解决方案:

wget -q http://example.com -O - | \
    tr "\t\r\n'" '   "' | \
    grep -i -o '<a[^>]\+href[ ]*=[ \t]*"\(ht\|f\)tps\?:[^"]\+"' | \
    sed -e 's/^.*"\([^"]\+\)".*$/\1/g'

这将输出网页中所有的http、https、ftp和ftps链接。它只会给出完整的url,不会给出相对url。
以下是一系列管道命令中使用的选项的说明:
wget -q使其没有过多的输出(安静模式)。 wget -O -使得下载的文件被回显到标准输出,而不是保存到磁盘。
tr是unix字符转换器,在本例中用于将换行符和制表符转换为空格,并将单引号转换为双引号,以便简化我们的正则表达式。
grep -i使搜索不区分大小写 grep -o使其只输出匹配部分。
sed是流编辑器unix实用程序,允许进行过滤和转换操作。
sed -e只是让您提供一个表达式。
在"http://craigslist.org"上运行这个小脚本产生了一个相当长的链接列表:
http://blog.craigslist.org/
http://24hoursoncraigslist.com/subs/nowplaying.html
http://craigslistfoundation.org/
http://atlanta.craigslist.org/
http://austin.craigslist.org/
http://boston.craigslist.org/
http://chicago.craigslist.org/
http://cleveland.craigslist.org/
...

非常酷。但是工具的Win32版本出了问题...在某个地方。你能说一下如何修改它们以适用于Cygwin或纯Windows吗? - Snowy
@Snowy,我不确定你所说的“choking”是什么意思。Cygwin应该可以正常工作。您也可以尝试使用curl而不是wget - Jay Taylor
2
我想指出@Rob想要从一个网站获取所有的URL而不是从一个网页。 - erdomester
好的,没关系,我把grep命令改成了这样:grep -i -o '<a[^>]\+href[ ]*=[ \t]*"[^"]\+">[^<]*</a>',并且去掉了sed,现在看起来它能够完成任务了。现在我只需要想办法解析这些A标签。 - BarbaraKwarc

8

我使用过一个叫做 xidel 的工具。

xidel http://server -e '//a/@href' | 
grep -v "http" | 
sort -u | 
xargs -L1 -I {}  xidel http://server/{} -e '//a/@href' | 
grep -v "http" | sort -u

这种方法有点hackish,但可以让你更接近目标!这只是第一层。想象将其打包成一个自递归脚本!


谢谢……这看起来很适合为我的wget问题编写脚本解决方法(http://opendata.stackexchange.com/q/4851/263) - Joe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接