如何使用grep和插入脚本从HTML文件获取网站URL


21

我正在尝试使用grep和cut从HTML文件中提取URL。链接如下所示:

<a href="http://examplewebsite.com/">

其他网站都有.net.gov但我认为我可以在截止点之前提出>。所以我知道我可以使用grep并以某种方式剪切掉http和.com之前的所有内容,但是我已经坚持了一段时间。


我编辑了 对于某些忽略<和a之间的空格的人,没有它就不会显示HTML。感谢您抓住这一点!
eltigre 2015年

使用代码格式设置(选择文本,然后按Ctrl-K)。否则,<>强制将其视为HTML标记。
muru

为什么不匹配href参数的开头和结尾引号?另外,我认为正则表达式不是最适合html的。
把友情留在无盐2015年

我想专门使用grep编写命令并剪切以执行此操作。我知道还有其他方法,但是我想知道这些。
eltigre

9
通常,用正则表达式解析HTML不是一个好主意,因为HTML不是一种正则语言。如果可以保证要解析的HTML非常简单,并且要提取的内容是可以预测的,可以摆脱它。但请参阅stackoverflow.com/a/1732454/4014959
2

Answers:


25

正如我在评论中说的那样,用正则表达式解析HTML通常不是一个好主意,但是如果您解析的HTML表现良好,有时您可以摆脱它。

为了只获取元素href属性中的URL <a>,我发现在多个阶段中最容易做到这一点。从您的评论看来,您只需要顶级域名,而不是完整URL。在这种情况下,您可以使用以下方式:

grep -Eoi '<a [^>]+>' source.html |
grep -Eo 'href="[^\"]+"' | 
grep -Eo '(http|https)://[^/"]+'

source.html包含要解析的HTML代码的文件在哪里。

此代码将打印所有出现在每一行href中任何<a>元素属性的顶级URL 。第-i一个grep命令的选项是确保它可以同时在<a><A>元素上使用。我想您也-i可以使用第二种方法grep来捕获大写HREF属性OTOH,我更喜欢忽略这种损坏的HTML。:)

处理内容 http://google.com/

wget -qO- http://google.com/ |
grep -Eoi '<a [^>]+>' | 
grep -Eo 'href="[^\"]+"' | 
grep -Eo '(http|https)://[^/"]+'

输出

http://www.google.com.au
http://maps.google.com.au
https://play.google.com
http://www.youtube.com
http://news.google.com.au
https://mail.google.com
https://drive.google.com
http://www.google.com.au
http://www.google.com.au
https://accounts.google.com
http://www.google.com.au
https://www.google.com
https://plus.google.com
http://www.google.com.au

当我重定向到澳大利亚Google页面时,我的输出与其他示例略有不同。


谢谢。现在这正是我想要的。这是最干净的方法。
eltigre 2015年

@eltigre:我很高兴!但是请注意我在上面的评论中链接到的警告。:)
下午15年

我想到了这个问题,希望得到一些简单的答案……而您已经完全钉住了头
Mark K Cowan 2015年

谢谢@MarkKCowan。:) FWIW,我最初开始使用awk编写答案,但是后来我决定,对于不熟悉awk的人来说,基于grep的解决方案会更容易理解。而且无论如何,上面的代码比我的awk代码短。
下午15年

2
@mavavilj:因为OP只需要顶级域名,所以之后://我们只接受第一个/或之前的字符"。但是,如果您想查看完整的URL,请将命令更改为grep -Eo '(http|https)://[^"]+。该行的另一个选项是grep -Eo '(http|https)://[^?"]+'切断查询选项。但是,该变体仍将打印包含在另一个URL中的URL作为查询参数,但是它们将被打印在单独的行上。
下午15年

25

不知道您是否受限于工具:

但是正则表达式可能不是最好的方式,但是下面是我整理的一个示例:

cat urls.html | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
  • grep -E:与egrep相同
  • grep -o:仅输出已被grepped的内容
  • (http | https):是/或
  • az:全部为小写
  • AZ:都是大写字母
  • 。:是点
  • \ ?:是?
  • *:重复[...]组
  • uniq:将删除所有重复项

输出:

bob@bob-NE722:~s$  wget -qO- https://stackoverflow.com/ | grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" | sort -u
https://stackauth.com
https://meta.stackoverflow.com
https://cdn.sstatic.net/Img/svg-icons
https://stackoverflow.com
https://www.stackoverflowbusiness.com/talent
https://www.stackoverflowbusiness.com/advertising
https://stackoverflow.com/users/login?ssrc=head
https://stackoverflow.com/users/signup?ssrc=head
https://stackoverflow.com
https://stackoverflow.com/help
https://chat.stackoverflow.com
https://meta.stackoverflow.com
...

您也可以添加\d以捕获其他数字类型。


2
IRI正则表达式!使用其中之一并吓OP OP!:)
muru 2015年

2
@muru ... 颤抖着我...我不知道该说些什么。那些是真的吗?
jmunsch 2015年

4
@ jmunsch,uniq只会删除相邻的重复项。sort -u
JJoao 2015年

1
它很棒,最好的答案!!
Gery

@JJoao是排序-u的源,比管道更快?只是一个思想实验,身份证就得看。但是关于外壳中间件,您可能是正确的。
jmunsch

9

如果您的grep支持Perl正则表达式:

grep -Po '(?<=href=")[^"]*(?=")'
  • (?<=href=")并且(?=")环视的表达式href属性。这需要-P选项。
  • -o 打印匹配的文本。

例如:

$ curl -sL https://www.google.com | grep -Po '(?<=href=")[^"]*(?=")'
/search?
https://www.google.co.in/imghp?hl=en&tab=wi
https://maps.google.co.in/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
https://www.youtube.com/?gl=IN&tab=w1
https://news.google.co.in/nwshp?hl=en&tab=wn
...

与往常一样,不能保证这些是有效的URI,也不保证您正在解析的HTML将是有效的。


8

作为非正则表达式的替代品,请使用pup

pup 'a[href] attr{href}' < yourfile.html

将查找所有a具有href属性的元素,然后显示该href属性的值。

要安装pup,您需要Go(一种编程语言):

sudo apt-get install golang
sudo go get github.com/ericchiang/pup

该解决方案的优点是它不依赖于正确格式化的HTML


1
+1 pup,需要时间安装....
Mark K Cowan 2015年

您也可以将它们归档。pup 'a.classname[href] attr{href}' < tut.html >links.md
艾哈迈德·阿怀斯

1

我在这里找到了一个解决方案,恕我直言,它比这里提出的解决方案简单得多,而且可能更快。我做了一些调整以支持https文件。但是TD; TR版本是...

PS:您可以将站点URL替换为文件路径,并且将以相同的方式工作。

lynx -dump -listonly -nonumbers "http://www.goggle.com" > links.txt

lynx -dump -listonly -nonumbers "some-file.html" > links.txt

如果您只想查看链接而不是将链接放在文件中,请尝试使用此链接...

lynx -dump -listonly -nonumbers "http://www.google.com"

lynx -dump -listonly -nonumbers "some-file.html"

结果将类似于以下内容...

http://www.google.ca/imghp?hl=en&tab=wi
http://maps.google.ca/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
http://www.youtube.com/?gl=CA&tab=w1
http://news.google.ca/nwshp?hl=en&tab=wn
https://mail.google.com/mail/?tab=wm
https://drive.google.com/?tab=wo
https://www.google.ca/intl/en/options/
http://www.google.ca/history/optout?hl=en
...
etc.

对于我的用例,这很好。但是请注意,如今人们为库的CDN URI添加了诸如src =“ // blah.tld”之类的链接。我不想在检索的链接中看到这些内容。

无需尝试检查href或其他来源的链接,因为默认情况下,“ lynx -dump”将提取给定页面中的所有可点击链接。因此,在此之后,您唯一需要做的就是使用grep解析“ lynx -dump”的结果,以获得相同结果的更原始版本。


但问题是“从[外观]相似的HTML 文件中提取URL ”(示例),而不是 “从网页中提取URL”。如果您的答案可以用于本地计算机上的文件,请说明如何使用。请不要在评论中回复;编辑您的答案,使其更清晰,更完整。
G-Man说'Resstate Monica''De​​c

1
您可以将URL替换为文件名。
asiby

@ G-Man,为什么为-1?您需要亲自尝试该代码,并查看它也适用于本地文件。我添加了澄清,以防不明显。
asiby

这真的很方便..如果与xargs一起使用,则值得添加| 排序| uniq修剪重复的链接。
Stuart Axon

0
wget -qO- google.com |
tr \" \\n | grep https\*://

...可能会做得很好。如所写,它打印:

http://schema.org/WebPage
http://www.google.com/imghp?hl=en&tab=wi
http://maps.google.com/maps?hl=en&tab=wl
https://play.google.com/?hl=en&tab=w8
http://www.youtube.com/?tab=w1
http://news.google.com/nwshp?hl=en&tab=wn
https://mail.google.com/mail/?tab=wm
https://drive.google.com/?tab=wo
http://www.google.com/intl/en/options/
http://www.google.com/history/optout?hl=en
https://accounts.google.com/ServiceLogin?hl=en&continue=http://www.google.com/
https://www.google.com/culturalinstitute/project/the-holocaust?utm_source=google&amp;utm_medium=hppromo&amp;utm_campaign=auschwitz_q1&amp;utm_content=desktop
https://plus.google.com/116899029375914044550

如果仅匹配链接以及这些顶级域中的链接很重要,则可以执行以下操作:

wget -qO- google.com |
sed '/\n/P;//!s|<a[^>]*\(https*://[^/"]*\)|\n\1\n|;D'

...或类似的东西-尽管对于某些seds,您可能需要用字面的\n斜线字符代替最后两个ns。

按照上面的命令,上面的命令显示:

http://www.google.com
http://maps.google.com
https://play.google.com
http://www.youtube.com
http://news.google.com
https://mail.google.com
https://drive.google.com
http://www.google.com
http://www.google.com
http://www.google.com
https://www.google.com
https://plus.google.com

...并且对于任何一种情况(但对于后一种情况,可能都是最有用的),您可以将|sort -u过滤器添加到末尾以获取列表sorted并删除重复项。



-1
echo "<a href="http://examplewebsite.com/">"|sed -r 's:<.*"::g'|sed 's:/">$::g'

我不确定这些“智能”引号是否是您想要的—也许是常规的“双”引号?
杰夫·谢勒
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.