什么是从HTML文件中输出两个特定字段值的最简单方法?

3

我正在从此网址提取HTML。我对以下两行感兴趣:

<meta name="SAC:price" content="444000"> <meta name="SAC:published" content="2020-03-28 11:06:22">

我想提取这两行的内容值。在这个例子中,我需要的输出是:

[444000,2020-03-28 11:06:22]

最简单的方法是什么?这是我到目前为止尝试过的:

function myFunction() {
  var url = "https://asunnot.oikotie.fi/myytavat-asunnot/helsinki/15597485"
  var str = UrlFetchApp.fetch(url).getContentText();
  let r = /ce" content="(\d{6})">|hed" content="(.*)">/g,out=[];     
  let arr = [...str.matchAll(r)]; //[[ce" content="444000">, 444000, null], [hed" content="2020-03-28 11:06:22">, null, 2020-03-28 11:06:22]]
  for(a of arr){
    a.shift();
    (a[0])?out.push(a[0]):out.push(a[1]);
    } 
  Logger.log(out); //[444000, 2020-03-28 11:06:22]
}

这似乎过于繁琐,有更好的选项吗?我不介意如何实现(正则表达式或其他方法),只要能以最简单的方式一致地获取这两个字段的内容。

感谢Wiktor Stribiżew的贡献,最终解决方案:

function myFunction() {
  var url = "https://asunnot.oikotie.fi/myytavat-asunnot/helsinki/15597485"
  var str = UrlFetchApp.fetch(url).getContentText();
  let r = /(?<=ce" content=")\d{6}(?=">)|(?<=hed" content=").*(?=">)/g;     
  let arr = str.match(r);
  Logger.log(arr); //[444000, 2020-03-28 11:06:22]
}

1
如果你想除去空值并只保留匹配的数值,确保你只消耗想要获取的内容:let r = /(?<=ce" content=")\d{6}(?=">)|(?<=hed" content=")[^"]*(?=")>/g; - Wiktor Stribiżew
那个正则表达式似乎只选择了444000,请参见https://regex101.com/r/rAjZOe/1 - jlo
1
我的笔误(在(?=")>处),它应该是let r = /(?<=ce" content=")\d{6}(?=">)|(?<=hed" content=")[^"]*(?=">)/g - Wiktor Stribiżew
谢谢,我之前并不熟悉正向先行断言/反向先行断言。这真的使事情变得简单了! - jlo
请注意,JavaScript 中的后顾支持非常有用,但并不是所有情况下都被支持。 - Pointy
3个回答

2

如果你想去除空值并只保留匹配的值,请确保只使用你想要获取的内容:

let r = /(?<=ce" content=")\d{6}(?=">)|(?<=hed" content=")[^"]*(?=">)/g;

在这里,(?<=ce" content=")(?<=hed" content=") 是正向后瞻,它们匹配字符串中紧随特定文本(此处为固定文本)之后的位置,而(?=">)是正向前瞻,它匹配字符串中紧跟着某个文本的位置。请参见正则表达式演示

然后,您只需要使用String#match调用正则表达式即可得到结果数组:

let arr = str.match(r);

查看这里了解有关环视的更多信息


0

有一个方法可以做到,您可以使用 replace 函数来获取值。请检查。

const data = `<meta name="SAC:habitationType" content="1">
 <meta name="SAC:price" content="444000">
<meta name="SAC:published" content="2020-03-28 11:06:22">
<meta name="SAC:listingType" content="1">`
let matches = []
data.replace(/content="(\d{6}|\d\d\d\d-.+)">/g, (_,m) => {
  matches.push(m)
})
console.log(matches)
.as-console-row {color: blue!important}


这可能对于问题来说是可以的,但是您的正则表达式匹配了原始表达式未匹配的输入。OP会根据“name”属性的内容限制“content”属性值可能的取值。 - Pointy

-1

你有一个|运算符。只有一侧会匹配,因此另一侧的捕获组将为null.matchAll()操作始终包括正则表达式中所有捕获组的值,包括那些未匹配的。

链接的示例页面显然有自己的代码,可以确定哪个备选项匹配。换句话说,它不仅仅使用.matchAll(),或者它正在后处理结果。


1
那么有没有办法使用一个正则表达式公式仅捕获这两个值?或者只能将该表达式分成 var re1 = /ce" content="(\d{6})">/; -> matchAll -> 提取组 和 var re2 = /hed" content="(.*)">/-> matchAll -> 提取组 两部分来处理呢? - jlo
你可以在操作后过滤掉空值,如果你不喜欢的话;但是现在不清楚你真正想要什么。 - Pointy
检查我的答案,有一个黑客可以实现! - xdeepakv

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