我有一个 html 源文件,我需要提取其中的链接,每个文件的链接数量各不相同,并且链接的格式如下,且位于单引号内:
../xxx/yyy/ccc/bbbb/nameoffile.extension
我需要获取单引号之间的文本,用 替换..
并将http://
结果输出到文件。
我是一名新手,正在寻找一种解决方案来在终端中自动执行此过程。
它的 html 源文件和链接遍布文件的各个角落,我需要在文件中每行输出一个链接,然后传递给我现有的 xargs curl 进行下载。
示例文件几乎是这样的:
<head>
<body>
<html>
blabla
</>
blibli afg fgfdg sdfg <b> blo blo href= '../xxx/yyy/ccc/bbbb/nameoffile1.extension' target blibli bloblo href= '../xxx/yyy/ccc/bbbb/nameoffile2.extension' blibli
bloblo href= '../xxx/yyy/ccc/bbbb/nameoffile3.extension'
…
寻找的结果是包含以下内容的文件:
http://z.z.com/xxx/yyy/ccc/bbbb/nameoffile1.extension
http://z.z.com/xxx/yyy/ccc/bbbb/nameoffile2.extension
http://z.z.com/xxx/yyy/ccc/bbbb/nameoffile3.extension
有人可以帮我找到解决办法吗?
尽可能接近源文件:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML>
<HEAD>
<TITLE>Inter num num - nil</TITLE>
<link rel="stylesheet" type="text/css" href="style.css" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</HEAD>
<BODY><table width=1200 align=center class=tabForm><tr><td align=left width=largeur_2 valign=top><img src=Img/logo.gif><br /></td><td align=center valign=center width=largeur_6><h1><font color='#CB150A'>Test d'épreuve</font></h1></td><td align=right valign=top width=largeur_2 class=dataLabel>Reçu le 11/03/2018 à 17:49<br /></td></tr>
<tr><td width=1200 colspan=3 align=center><b><font color='#CB150A' size=+1>Client : zzz - Référence : 232323 - Désignation : Fiche d'accueil </font></b></color></td></tr>
</table><BR/><table width=1200 align=center class=tabForm><tr><td class=dataLabelBig width=1200>M numnum ,<BR/><BR/>
Job citée ci-dessus.<BR/>
ci-joints toutes les informations nécessaires.
<BR/><BR/>
Sandy Jan<BR/>
[email protected]</font></td></tr></table><br /><table width=1200 align=center class=tabForm><tr><td colspan=2 width=1200 class=dataLabel>Documents nécessaires à votre réponse</td></tr><tr><td colspan=2 width=1200 class=dataLabel><u><b>Job :</b></u> Suivi Travaux - <u><b>Article :</b></u> 232323 - Fiche d'accueil</td></tr><tr><td colspan=2 width=1200 class=dataLabel><a href='../path/path/path/path/path.html' target=_blank><img src=Img/pdf.png border=0> Fiche.html</a></td></tr><tr><td colspan=2 width=1200 class=dataLabel><a href='../path/path/path/path/pathd%27accueil%20traitant-20160621163240.pdf' target=_blank><img src=Img/pdf.png border=0> text.pdf</a></td></tr><tr><td colspan=2 width=1200 class=dataLabel><a href='../path/path/path/path/pathla%20S%E9curit%E9%20%281%29.doc' target=_blank><img src=Img/pdf.png border=0> Fiched'accueil.doc</a></td></tr></table><br /><table width=1200 align=center class=tabForm><tr><td colspan=2 class=dataLabelRed width=1200 >Notre commentaire</td></tr></tr><td colspan=2 class=dataLabel>mise a jour - Attention<br />
Impression <br /><br /></td></tr></table><br /><table width=1200 align=center class=tabForm><form method=post name=formvolume action=?&dossier=111734&coo=135&auth=b182f10b82ba&key=2e7c69213b28d7de6655&action=submit&type=volume enctype=multipart/form-data ><tr><td width=1200 align=left colspan=2 class=dataLabel><h3><img src=Img/h3Arrow.gif border=0> Remise de job :</h3><br /></td></tr><tr><td align=left valign=top width=120 class=dataLabelRed>Votre commentaire</td><td width=1080 align=left class=dataLabel><textarea cols=200 rows=5 name=comment ></textarea></td></tr><tr><td align=left width=120 class=dataLabelRed>Votre fichier</td><td width=1080 align=left><input type=file name=fichier size=82></td></tr><tr><td align=center colspan=2 width=1200><br /><input type=button class=button value=" Remettre votre réponse " onClick="javascript: var ok=confirm('Etes vous certain de vouloir effectuer cette action ?');if(ok==true){ document.formvolume.submit();}else {return false}" ></form></td></tr><table></table></br><table width=1200 align=center class=tabForm><form method=post name=formvolume_complement action=?&dossier=111734&coo=135&auth=b182f10b82ba&key=2e7c69213b28d7de6655&action=submit_complement&type=volume enctype=multipart/form-data ><tr><td width=1200 align=left colspan=2 class=dataLabel><h3><img src=Img/h3Arrow.gif border=0> Demande de complément, votre réponse :</h3><br /></td></tr><tr><tr><td align=left valign=top width=120 class=dataLabelRed>Votre commentaire</td><td width=1080 align=left class=dataLabel><textarea cols=200 rows=5 name=comment ></textarea></td></tr><td align=left width=120 class=dataLabelRed>Votre fichier</td><td width=1080 align=left><input type=file name=fichier size=82></td></tr><tr><td align=center colspan=2 width=1200><br /><input type=button class=button value=" Remettre votre réponse " onClick="javascript: var ok =confirm('Etes v ?');if(ok==true){ document.formvolume_complement.submit();}else {return false}" ></form></td></tr><table></table></BODY></HTML></BODY>
</HTML>
答案1
sed
等实用程序awk
不适用于解析 html 等结构化数据。因此,更可行的解决方案是使用 python 来执行相同操作。
首先,确保美丽的汤安装者:
sudo apt-get install python3 python3-bs4
现在创建一个新文件(例如test.py
)并粘贴我为此目的编写的简短脚本:
#!/usr/bin/env python3
import sys
from bs4 import BeautifulSoup
DOMAIN = 'z.z.com/'
if len(sys.argv)<2 or not sys.argv[1].endswith('.html'):
print("Argument not provided or not .html file", file=sys.stderr)
exit()
with open(sys.argv[1], 'r', encoding='latin-1') as f:
webpage = f.read()
soup = BeautifulSoup(webpage, "lxml")
for a in soup.findAll('a', href=True):
print(a['href'].replace("../","http://"+DOMAIN))
根据要求提供 Python 2 版本:
#!/usr/bin/env python2
import sys
from bs4 import BeautifulSoup
DOMAIN = 'z.z.com/'
if len(sys.argv)<2 or not sys.argv[1].endswith('.html'):
print >> sys.stderr, "Argument not provided or not .html file"
exit()
with open(sys.argv[1], 'rb') as f:
webpage = f.read().decode("latin-1")
soup = BeautifulSoup(webpage, "html.parser")
for a in soup.findAll('a', href=True):
print(a['href'].replace("../","http://"+DOMAIN))
修改DOMAIN
变量以匹配您的实际域,将此脚本保存在当前目录中并运行如下:
./test.py yourfile.html > outputfile
作为参考,这是使用问题中提供的示例运行脚本时产生的输出:
http://z.z.com/path/path/path/path/path.html
http://z.z.com/path/path/path/path/pathd%27accueil%20traitant-20160621163240.pdf
http://z.z.com/path/path/path/path/pathla%20S%E9curit%E9%20%281%29.doc
答案2
另一个使用适当 HTML 解析器的 Perl 解决方案如下(例如get-links.pl
):
#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use WWW::Mechanize;
my $filename = shift or die "Must supply a *.html file\n";
my $absolute_filename = File::Spec->rel2abs($filename);
my $mech = WWW::Mechanize->new();
$mech->get( "file://$absolute_filename" );
my @links = $mech->links();
foreach my $link ( @links ) {
my $new_link = $link->url;
if ( $new_link =~ s(^\.\./)(http://z.z.com/) ) {
print "$new_link\n";
}
}
您可能需要安装WWW::Mechanize
模块首先,因为它不是一个核心模块(这意味着它默认不与 Perl 一起安装)。为此,请运行
sudo apt install libwww-mechanize-perl
该脚本读取给定的文件,将文件名转换为绝对路径(因为我们想要构建一个像这样的正确 URI file:///path/to/source.html
)。
提取链接(my @links = $mech->links();
)后,它会检查每个链接的 URL,如果以 开头,../
则将该部分替换为http://z.z.com/
并打印。
用法:
./get-links.pl source.html
输出:
http://z.z.com/path/path/path/path/path.html
http://z.z.com/path/path/path/path/pathd%27accueil%20traitant-20160621163240.pdf
http://z.z.com/path/path/path/path/pathla%20S%E9curit%E9%20%281%29.doc
作为@Amith KK已经说过他的回答:解析 HTML(或 XML)最好使用适当的解析器,因为sed
当源中存在其他元素时,诸如及其同类的工具可能会失败看喜欢一个链接但实际上不是。
答案3
要从文件中提取单引号之间的数据并用URL 中的test.html
两个点替换,并将提取的数据保存到文件中,请执行以下操作:..
http://
newfile.txt
cat test.html | sed -ne 's/^.*'\''\([^'\'']*\)'\''.*$/\1/p' | sed -e 's/\.\./http:\//g' > newfile.txt
或者尝试不使用 sed:
cat test.html | grep -Eo "'[^'() ]+'" | tr -d \'\" | perl -pe 's/../http:\//' > newfile.txt
这适用于作者添加到问题中的文件示例:
cat test.html | grep -Eo "'[^|'() ]+'" | grep -wE "('..)" | tr -d \'\" | perl -pe 's/../http:\/\/mysite.mydomain.com/' > newfile.txt
答案4
将 HTML 转换为文本
正如评论中提到的,您需要转换html
为文本格式。为此,有一个单行应该涵盖所有的基础:
sed 's/ / /g; s/&/\&/g; s/</\</g; s/>/\>/g; s/"/\"/g; s/#'/\'"'"'/g; s/“/\"/g; s/”/\"/g;'
如果你要转换数十万行,bash 内置命令的速度会快很多倍:
#-------------------------------------------------------------------------------
LineOut="" # Make global
HTMLtoText () {
LineOut=$1 # Parm 1= Input line
# Replace external command: Line=$(sed 's/&/\&/g; s/</\</g;
# s/>/\>/g; s/"/\"/g; s/'/\'"'"'/g; s/“/\"/g;
# s/”/\"/g;' <<< "$Line") -- With faster builtin commands.
LineOut="${LineOut// / }"
LineOut="${LineOut//&/&}"
LineOut="${LineOut//</<}"
LineOut="${LineOut//>/>}"
LineOut="${LineOut//"/'"'}"
LineOut="${LineOut//'/"'"}"
LineOut="${LineOut//“/'"'}" # TODO: ASCII/ISO for opening quote
LineOut="${LineOut//”/'"'}" # TODO: ASCII/ISO for closing quote
} # HTMLtoText ()
检查文件是否存在
要测试文件是否存在,请使用此功能:
function validate_url(){
if [[ `wget -S --spider $1 2>&1 | grep 'HTTP/1.1 200 OK'` ]]; then echo "true"; fi
}
综合起来
仍然需要根据来自具有有效文件名的有效网页的示例数据来编写最终脚本。