我目前正在创建一个Node.js webscraper /
proxy,但是在解析在源脚本部分中找到的相对Urls时遇到了麻烦,我发现REGEX可以解决问题。虽然不知道我将如何实现。
反正有什么我可以解决的吗?
另外,我愿意采取一种更简单的方法来执行此操作,因为我对其他代理如何解析网站感到困惑。我认为大多数只是赞美的网站抓取工具,可以读取网站的来源,将所有链接/表格中继回代理。
OP的注释,因为他请求了这样的功能:更改base_url
为代理的basE URL,以实现所需的结果。
下面将显示两个功能(代码中包含使用指南)。确保您不跳过此答案的任何部分以完全理解该功能的行为。
rel_to_abs(urL)
-此函数返回绝对URL。当传递具有普遍信任协议的绝对URL时,它将立即返回此URL。否则,将根据base_url
和函数参数生成一个绝对URL 。相对URL正确解析(../
; ./
; .
; //
)。replace_all_rel_by_abs
-此函数将解析 所有 出现的在HTML中具有重要意义的URL,例如CSS url()
,链接和外部资源。请参阅代码以获取已解析实例的完整列表。 以获取经过调整的实现,以 清理 来自外部源(嵌入到文档中)的 HTML字符串 。rel_to_abs
- 解析相对网址
function rel_to_abs(url){
/* Only accept commonly trusted protocols:
* Only data-image URLs are accepted, Exotic flavours (escaped slash,
* html-entitied characters) are not supported to keep the function fast */
if(/^(https?|file|ftps?|mailto|javascript|data:image\/[^;]{2,9};):/i.test(url))
return url; //Url is already absolute
var base_url = location.href.match(/^(.+)\/?(?:#.+)?$/)[0]+"/";
if(url.substring(0,2) == "//")
return location.protocol + url;
else if(url.charAt(0) == "/")
return location.protocol + "//" + location.host + url;
else if(url.substring(0,2) == "./")
url = "." + url;
else if(/^\s*$/.test(url))
return ""; //Empty = Return nothing
else url = "../" + url;
url = base_url + url;
var i=0
while(/\/\.\.\//.test(url = url.replace(/[^\/]+\/+\.\.\//g,"")));
/* Escape certain characters to prevent XSS */
url = url.replace(/\.$/,"").replace(/\/\./g,"").replace(/"/g,"%22")
.replace(/'/g,"%27").replace(/</g,"%3C").replace(/>/g,"%3E");
return url;
}
案例/示例:
http://foo.bar
。已经是绝对URL,因此立即返回。/doo
相对于根:返回当前根+提供的相对URL。./meh
相对于当前目录。../booh
相对于父目录。该函数将相对路径转换为../
,并执行搜索和替换(http://domain/sub/anything-but-a- slash/../me
至http://domain/sub/me
)。
replace_all_rel_by_abs
- 转换
脚本实例内部的 所有相关URL URL(<script>
,事件处理程序 不会
被替换,因为创建一个快速安全的过滤器来解析JavaScript几乎是不可能的。
该脚本内部带有一些注释。动态创建正则表达式,因为单个RE的大小可以为 3000个 字符。<meta http-equiv=refresh content=.. >
可以以各种方式混淆,因此RE的大小。
function replace_all_rel_by_abs(html){
/*HTML/XML Attribute may not be prefixed by these characters (common
attribute chars. This list is not complete, but will be sufficient
for this function (see http://www.w3.org/TR/REC-xml/#NT-NameChar). */
var att = "[^-a-z0-9:._]";
var entityEnd = "(?:;|(?!\\d))";
var ents = {" ":"(?:\\s| ?|�*32"+entityEnd+"|�*20"+entityEnd+")",
"(":"(?:\\(|�*40"+entityEnd+"|�*28"+entityEnd+")",
")":"(?:\\)|�*41"+entityEnd+"|�*29"+entityEnd+")",
".":"(?:\\.|�*46"+entityEnd+"|�*2e"+entityEnd+")"};
/* Placeholders to filter obfuscations */
var charMap = {};
var s = ents[" "]+"*"; //Short-hand for common use
var any = "(?:[^>\"']*(?:\"[^\"]*\"|'[^']*'))*?[^>]*";
/* ^ Important: Must be pre- and postfixed by < and >.
* This RE should match anything within a tag! */
/*
@name ae
@description Converts a given string in a sequence of the original
input and the HTML entity
@param String string String to convert
*/
function ae(string){
var all_chars_lowercase = string.toLowerCase();
if(ents[string]) return ents[string];
var all_chars_uppercase = string.toUpperCase();
var RE_res = "";
for(var i=0; i<string.length; i++){
var char_lowercase = all_chars_lowercase.charAt(i);
if(charMap[char_lowercase]){
RE_res += charMap[char_lowercase];
continue;
}
var char_uppercase = all_chars_uppercase.charAt(i);
var RE_sub = [char_lowercase];
RE_sub.push("�*" + char_lowercase.charCodeAt(0) + entityEnd);
RE_sub.push("�*" + char_lowercase.charCodeAt(0).toString(16) + entityEnd);
if(char_lowercase != char_uppercase){
/* Note: RE ignorecase flag has already been activated */
RE_sub.push("�*" + char_uppercase.charCodeAt(0) + entityEnd);
RE_sub.push("�*" + char_uppercase.charCodeAt(0).toString(16) + entityEnd);
}
RE_sub = "(?:" + RE_sub.join("|") + ")";
RE_res += (charMap[char_lowercase] = RE_sub);
}
return(ents[string] = RE_res);
}
/*
@name by
@description 2nd argument for replace().
*/
function by(match, group1, group2, group3){
/* Note that this function can also be used to remove links:
* return group1 + "javascript://" + group3; */
return group1 + rel_to_abs(group2) + group3;
}
/*
@name by2
@description 2nd argument for replace(). Parses relevant HTML entities
*/
var slashRE = new RegExp(ae("/"), 'g');
var dotRE = new RegExp(ae("."), 'g');
function by2(match, group1, group2, group3){
/*Note that this function can also be used to remove links:
* return group1 + "javascript://" + group3; */
group2 = group2.replace(slashRE, "/").replace(dotRE, ".");
return group1 + rel_to_abs(group2) + group3;
}
/*
@name cr
@description Selects a HTML element and performs a
search-and-replace on attributes
@param String selector HTML substring to match
@param String attribute RegExp-escaped; HTML element attribute to match
@param String marker Optional RegExp-escaped; marks the prefix
@param String delimiter Optional RegExp escaped; non-quote delimiters
@param String end Optional RegExp-escaped; forces the match to end
before an occurence of <end>
*/
function cr(selector, attribute, marker, delimiter, end){
if(typeof selector == "string") selector = new RegExp(selector, "gi");
attribute = att + attribute;
marker = typeof marker == "string" ? marker : "\\s*=\\s*";
delimiter = typeof delimiter == "string" ? delimiter : "";
end = typeof end == "string" ? "?)("+end : ")(";
var re1 = new RegExp('('+attribute+marker+'")([^"'+delimiter+']+'+end+')', 'gi');
var re2 = new RegExp("("+attribute+marker+"')([^'"+delimiter+"]+"+end+")", 'gi');
var re3 = new RegExp('('+attribute+marker+')([^"\'][^\\s>'+delimiter+']*'+end+')', 'gi');
html = html.replace(selector, function(match){
return match.replace(re1, by).replace(re2, by).replace(re3, by);
});
}
/*
@name cri
@description Selects an attribute of a HTML element, and
performs a search-and-replace on certain values
@param String selector HTML element to match
@param String attribute RegExp-escaped; HTML element attribute to match
@param String front RegExp-escaped; attribute value, prefix to match
@param String flags Optional RegExp flags, default "gi"
@param String delimiter Optional RegExp-escaped; non-quote delimiters
@param String end Optional RegExp-escaped; forces the match to end
before an occurence of <end>
*/
function cri(selector, attribute, front, flags, delimiter, end){
if(typeof selector == "string") selector = new RegExp(selector, "gi");
attribute = att + attribute;
flags = typeof flags == "string" ? flags : "gi";
var re1 = new RegExp('('+attribute+'\\s*=\\s*")([^"]*)', 'gi');
var re2 = new RegExp("("+attribute+"\\s*=\\s*')([^']+)", 'gi');
var at1 = new RegExp('('+front+')([^"]+)(")', flags);
var at2 = new RegExp("("+front+")([^']+)(')", flags);
if(typeof delimiter == "string"){
end = typeof end == "string" ? end : "";
var at3 = new RegExp("("+front+")([^\"'][^"+delimiter+"]*" + (end?"?)("+end+")":")()"), flags);
var handleAttr = function(match, g1, g2){return g1+g2.replace(at1, by2).replace(at2, by2).replace(at3, by2)};
} else {
var handleAttr = function(match, g1, g2){return g1+g2.replace(at1, by2).replace(at2, by2)};
}
html = html.replace(selector, function(match){
return match.replace(re1, handleAttr).replace(re2, handleAttr);
});
}
/* <meta http-equiv=refresh content=" ; url= " > */
cri("<meta"+any+att+"http-equiv\\s*=\\s*(?:\""+ae("refresh")+"\""+any+">|'"+ae("refresh")+"'"+any+">|"+ae("refresh")+"(?:"+ae(" ")+any+">|>))", "content", ae("url")+s+ae("=")+s, "i");
cr("<"+any+att+"href\\s*="+any+">", "href"); /* Linked elements */
cr("<"+any+att+"src\\s*="+any+">", "src"); /* Embedded elements */
cr("<object"+any+att+"data\\s*="+any+">", "data"); /* <object data= > */
cr("<applet"+any+att+"codebase\\s*="+any+">", "codebase"); /* <applet codebase= > */
/* <param name=movie value= >*/
cr("<param"+any+att+"name\\s*=\\s*(?:\""+ae("movie")+"\""+any+">|'"+ae("movie")+"'"+any+">|"+ae("movie")+"(?:"+ae(" ")+any+">|>))", "value");
cr(/<style[^>]*>(?:[^"']*(?:"[^"]*"|'[^']*'))*?[^'"]*(?:<\/style|$)/gi, "url", "\\s*\\(\\s*", "", "\\s*\\)"); /* <style> */
cri("<"+any+att+"style\\s*="+any+">", "style", ae("url")+s+ae("(")+s, 0, s+ae(")"), ae(")")); /*< style=" url(...) " > */
return html;
}
私有功能的简短摘要:
rel_to_abs(url)
-将相对/未知URL转换为绝对URLreplace_all_rel_by_abs(html)
-用绝对URL替换HTML字符串中所有与URL相关的出现。
ae
- 一个 纽约 è ntity -返回RE模式来处理HTML实体。by
-替换 为 -此简短函数请求实际的url替换(rel_to_abs
)。此功能可能称为数百次(如果不是数千次)。注意不要在此功能(自定义)中添加慢速算法。cr
- ç reate ř E放置-创建并执行一个搜索和替换。
示例:(href="..."
在任何HTML标记内)。
cri
- ç reate ř E放置 我 n第-创建并执行一个搜索和替换。
示例:url(..)
在style
HTML标记内的all 属性内。
打开任何页面,然后将以下书签粘贴到位置栏中:
javascript:void(function(){var s=document.createElement("script");s.src="http://rob.lekensteyn.nl/rel_to_abs.js";document.body.appendChild(s)})();
注入的代码包含上面定义的两个功能,以及如下所示的测试用例。 注意 :测试用例 不会
修改页面的HTML,但是会在文本区域(可选)中显示已解析的结果。
var t=(new Date).getTime();
var result = replace_all_rel_by_abs(document.documentElement.innerHTML);
if(confirm((new Date).getTime()-t+" milliseconds to execute\n\nPut results in new textarea?")){
var txt = document.createElement("textarea");
txt.style.cssText = "position:fixed;top:0;left:0;width:100%;height:99%"
txt.ondblclick = function(){this.parentNode.removeChild(this)}
txt.value = result;
document.body.appendChild(txt);
}
问题内容: 我的Python迷宫生成程序似乎有问题。我正在尝试随机创建一条在选择点处分支的路径,并随其进行存储点。当迷宫走到尽头时,它将测试最高值,而不是将其弹出并转到下一个,从而对访问的点进行排序,直到到达不是死角的位置。但是,当我尝试将项目追加到我用来保存我曾经去过的空间的列表时,发生了一些奇怪的事情,实际上我从未见过。这是代码,查看该代码的最佳方法是将其运行一段时间,直到完全运行为止。我还没
问题内容: 我的数据库确实发生了一些奇怪的事情。我正在使用PHP将数据插入数据库中,并且在过去的两年中我一直在这样做,没有任何问题。当客户在我的网站上付款时,我会将交易中的所有数据存储在数据库中。每个交易都有一个唯一的“ transaction_id”。当我将付款信息插入数据库时,除“ transaction_id”外,所有信息均已正确插入。所有交易均被赋予“ 4294967295”的“ tr
问题内容: 我有一个JSON字符串,并且键具有大写和小写字符: 我想将其转换为对象,并将所有键都转换为小写。因此在内部,它应该如下所示: 以前,我曾经使用过转换,但是我找不到如何使键变为小写。 有任何想法吗? 我之所以需要这样做是为了使我的验证不区分大小写。 问题答案: 用最少的代码来解决这个问题的一种可能方式是继承并重写属性返回一个小写的字符串,只要当前是: 之所以可行,是因为底层在内部状态变化
问题内容: 我有一个约有100列的遗留表(90%可为空)。在这90列中,我要删除所有空字符串并将其设置为null。我知道我可以: 但这很乏味且容易出错。必须在整个桌子上做到这一点吗? 问题答案: 这仍然是手动完成的,但比您要痛苦的要少一些,因为它不需要您为每一列发送查询。除非您想编写脚本麻烦,否则在执行此类操作时必须忍受一定的痛苦。 编辑:增加了小号
我已经将一些文件从S3转移到GCS,但是这些对象现在归传输服务所有,当我试图使用GSUTIL更新ACL时,它会说我不是所有者。这似乎是因为传输服务创建了它拥有的对象。是否有一种方法来模仿转移服务(或通过它的服务帐户登录),以便将所有权改变给我自己。 这样做时,我会得到以下错误: 请确保您拥有对此资源的所有者角色访问权限