ChatGPT解决这个技术问题 Extra ChatGPT

从文本 JavaScript 中剥离 HTML

有没有一种简单的方法可以在 JavaScript 中获取一串 html 并去除 html?


B
Black

如果您在浏览器中运行,那么最简单的方法就是let the browser do it for you...

function stripHtml(html)
{
   let tmp = document.createElement("DIV");
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

注意:正如人们在评论中指出的那样,如果您不控制 HTML 的源,最好避免这种情况(例如,不要在任何可能来自用户输入的内容上运行它)。对于这些情况,您仍然可以让浏览器为您完成工作 - see Saba's answer on using the now widely-available DOMParser


请记住,这种方法相当不一致,并且无法在某些浏览器中删除某些字符。例如,在 Prototype.js 中,我们使用这种方法来提高性能,但要解决一些缺陷 - github.com/kangax/prototype/blob/…
请记住,您的空白将被弄乱。我曾经使用这种方法,然后遇到问题,因为某些产品代码包含双空格,在我从 DIV 中取回 innerText 后,最终成为单个空格。然后产品代码在应用程序中不匹配。
@Magnus Smith:是的,如果空格是一个问题 - 或者真的,如果你需要这个不直接涉及你正在使用的特定 HTML DOM 的文本 - 那么你最好使用另一个这里给出的解决方案。此方法的主要优点是 1) 简单,2) 将可靠地处理标签、空格、实体、注释等,就像您运行的浏览器一样。这对于 Web 客户端代码通常很有用,但不一定适合与规则不同的其他系统交互。
不要将它与来自不受信任来源的 HTML 一起使用。要查看原因,请尝试运行 strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")
如果 html 包含图像(img 标签),则浏览器将请求图像。这不好。
M
Mike Samuel
myString.replace(/<[^>]*>?/gm, '');

如果您通过 document.write 注入或在通过 innerHTML 注入之前与包含 > 的字符串连接,则不适用于 <img src=http://www.google.com.kh/images/srpr/nav_logo27.png onload="alert(42)"
@PerishableDave,我同意 > 将留在第二个。不过,这不是注射危险。由于 < 留在第一个中,从而导致 HTML 解析器在第二个启动时处于 data state 以外的上下文中,因此发生危险。请注意,> 上的数据状态没有转换。
@MikeSamuel 我们决定这个答案了吗?天真的用户在这里准备复制粘贴。
我相信,如果给出类似 <button onClick="dostuff('>');"></button> 之类的内容,这也会完全混淆。假设 HTML 编写正确,您仍然需要考虑到属性中引用的文本中可能存在大于号。此外,您至少希望删除 <script> 标记内的所有文本。
@AntonioMax,我已经回答了这个问题ad nauseam,但就您问题的实质而言,因为 安全关键代码不应该被复制 & 您应该下载一个库,并使其保持最新状态并进行修补,以确保您免受最近发现的漏洞和浏览器更改的影响。
C
Community

最简单的方法:

jQuery(html).text();

从一串html中检索所有文本。


我们总是在项目中使用 jQuery,因为我们的项目总是有很多 Javascript。因此我们没有添加批量,我们利用了现有的 API 代码......
您使用它,但 OP 可能不会。问题是关于 Javascript 而不是 JQuery。
对于需要与 OP 做同样事情(比如我)并且不介意使用 jQuery(比如我)的人来说,它仍然是一个有用的答案,更不用说,如果他们正在考虑使用它,它可能对 OP 有用jQuery。该网站的重点是分享知识。请记住,在没有充分理由的情况下批评有用的答案可能会产生令人不寒而栗的效果。
@Dementic 令人震惊的是,我发现具有多个答案的线程是最有用的,因为通常次要答案可以满足我的确切需求,而主要答案可以满足一般情况。
如果您的字符串的某些部分未包含在 html 标记中,那将不起作用。例如“Error: Please enter a valid email”将只返回“Error:”
B
Black

我想分享 Shog9's approved answer 的编辑版本。

正如 Mike Samuel 在评论中指出的那样,该函数可以执行内联 javascript 代码。但是 Shog9 说“让浏览器为你做这件事……”是对的。

所以..这里是我编辑的版本,使用 DOMParser

function strip(html){
   let doc = new DOMParser().parseFromString(html, 'text/html');
   return doc.body.textContent || "";
}

这里是测试内联javascript的代码:

strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")

此外,它不会在解析时请求资源(如图像)

strip("Just text <img src='https://assets.rbl.ms/4155638/980x.jpg'>")

值得补充的是,此解决方案仅适用于浏览器。
这不是条带标签,而是更像 PHP htmlspecialchars()。对我还是有用的。
请注意,这也会从文本的开头删除空格。
此外,它不会尝试 parse html using regex
这应该是公认的答案,因为它是最安全和最快的方法
B
Black

作为 jQuery 方法的扩展,如果您的字符串可能不包含 HTML(例如,如果您尝试从表单字段中删除 HTML)

jQuery(html).text();

如果没有 HTML,将返回一个空字符串

利用:

jQuery('<p>' + html + '</p>').text();

反而。

更新: 正如评论中所指出的,在某些情况下,如果 html 的值可能受到攻击者的影响,此解决方案将执行 html 中包含的 javascript,请使用不同的解决方案。


$("<p>").html(html).text();
这仍然会执行可能很危险的代码 jQuery('<span>Text :) <img src="a" onerror="alert(1)"></span>').text()
试试 jQuery("aa<script>alert(1)</script>a").text();
V
Victor

将 HTML 转换为纯文本电子邮件,保持超链接 (a href) 不变

hypoxide 发布的上述函数工作正常,但我想要的东西基本上可以转换在 Web RichText 编辑器(例如 FCKEditor)中创建的 HTML 并清除所有 HTML 但保留所有链接,因为我想要 HTML 和纯文本版本,以帮助为 STMP 电子邮件(HTML 和纯文本)创建正确的部分。

在我自己和我的同事在 Javascript 中使用正则表达式引擎搜索 Google 很长时间之后,我想出了这个:

str='this string has <i>html</i> code i want to <b>remove</b><br>Link Number 1 -><a href="http://www.bbc.co.uk">BBC</a> Link Number 1<br><p>Now back to normal text and stuff</p>
';
str=str.replace(/<br>/gi, "\n");
str=str.replace(/<p.*>/gi, "\n");
str=str.replace(/<a.*href="(.*?)".*>(.*?)<\/a>/gi, " $2 (Link->$1) ");
str=str.replace(/<(?:.|\s)*?>/g, "");

str 变量的开头是这样的:

this string has <i>html</i> code i want to <b>remove</b><br>Link Number 1 -><a href="http://www.bbc.co.uk">BBC</a> Link Number 1<br><p>Now back to normal text and stuff</p>

然后在代码运行后它看起来像这样:-

this string has html code i want to remove
Link Number 1 -> BBC (Link->http://www.bbc.co.uk)  Link Number 1


Now back to normal text and stuff

正如您所看到的,所有的 HTML 都已被删除,并且链接已被保留,超链接文本仍然完好无损。我还用 \n(换行符)替换了 <p><br> 标签,以便保留某种视觉格式。

要更改链接格式(例如 BBC (Link->http://www.bbc.co.uk) ),只需编辑 $2 (Link->$1),其中 $1 是 href URL/URI,$2 是超链接文本。大多数 SMTP 邮件客户端使用纯文本正文中的链接直接转换这些链接,以便用户能够单击它们。

希望您觉得这个有帮助。


它不处理“ ”
J
Janghou

对已接受答案的改进。

function strip(html)
{
   var tmp = document.implementation.createHTMLDocument("New").body;
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

这样运行的东西不会有任何害处:

strip("<img onerror='alert(\"could run arbitrary JS here\")' src=bogus>")

Firefox、Chromium 和 Explorer 9+ 是安全的。 Opera Presto 仍然很脆弱。字符串中提到的图像也不会在 Chromium 和 Firefox 中下载保存 http 请求。


这是其中的一些方法,但对于 <script><script>alert(); 来说并不安全
这不会在 Linux 上的 Chromium/Opera/Firefox 中运行任何脚本,那为什么不安全呢?
抱歉,我一定是测试失败了,我可能忘记在 jsFiddle 上再次单击运行。
我认为“新”论点是多余的吗?
根据 specs,它现在是可选的,但并非总是如此。
K
Karl.S

这应该可以在任何 Javascript 环境(包括 NodeJS)上工作。

    const text = `
    <html lang="en">
      <head>
        <style type="text/css">*{color:red}</style>
        <script>alert('hello')</script>
      </head>
      <body><b>This is some text</b><br/><body>
    </html>`;
    
    // Remove style tags and content
    text.replace(/<style[^>]*>.*<\/style>/gm, '')
        // Remove script tags and content
        .replace(/<script[^>]*>.*<\/script>/gm, '')
        // Remove all opening, closing and orphan HTML tags
        .replace(/<[^>]+>/gm, '')
        // Remove leading spaces and repeated CR/LF
        .replace(/([\r\n]+ +)+/gm, '');

@pstanton 你能举一个你的陈述的工作例子吗?
<html><style..>* {font-family:comic-sans;}</style>Some Text</html>
@pstanton 我已经修复了代码并添加了评论,抱歉回复晚了。
请考虑阅读以下注意事项:stackoverflow.com/a/1732454/501765
C
Community

我更改了 Jibberboy2000's answer 以包含几种 <BR /> 标记格式,删除 <SCRIPT><STYLE> 标记内的所有内容,通过删除多个换行符和空格来格式化生成的 HTML,并将一些 HTML 编码的代码转换为正常的。经过一些测试,您似乎可以将大部分完整网页转换为保留页面标题和内容的简单文本。

在简单的例子中,

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<!--comment-->

<head>

<title>This is my title</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style>

    body {margin-top: 15px;}
    a { color: #D80C1F; font-weight:bold; text-decoration:none; }

</style>
</head>

<body>
    <center>
        This string has <i>html</i> code i want to <b>remove</b><br>
        In this line <a href="http://www.bbc.co.uk">BBC</a> with link is mentioned.<br/>Now back to &quot;normal text&quot; and stuff using &lt;html encoding&gt;                 
    </center>
</body>
</html>

变成

这是我的标题 这个字符串有我想要删除的 html 代码 在这一行中提到了带有链接的 BBC (http://www.bbc.co.uk)。现在回到“普通文本”和使用的东西

JavaScript 函数和测试页面如下所示:

function convertHtmlToText() {
    var inputText = document.getElementById("input").value;
    var returnText = "" + inputText;

    //-- remove BR tags and replace them with line break
    returnText=returnText.replace(/<br>/gi, "\n");
    returnText=returnText.replace(/<br\s\/>/gi, "\n");
    returnText=returnText.replace(/<br\/>/gi, "\n");

    //-- remove P and A tags but preserve what's inside of them
    returnText=returnText.replace(/<p.*>/gi, "\n");
    returnText=returnText.replace(/<a.*href="(.*?)".*>(.*?)<\/a>/gi, " $2 ($1)");

    //-- remove all inside SCRIPT and STYLE tags
    returnText=returnText.replace(/<script.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/script>/gi, "");
    returnText=returnText.replace(/<style.*>[\w\W]{1,}(.*?)[\w\W]{1,}<\/style>/gi, "");
    //-- remove all else
    returnText=returnText.replace(/<(?:.|\s)*?>/g, "");

    //-- get rid of more than 2 multiple line breaks:
    returnText=returnText.replace(/(?:(?:\r\n|\r|\n)\s*){2,}/gim, "\n\n");

    //-- get rid of more than 2 spaces:
    returnText = returnText.replace(/ +(?= )/g,'');

    //-- get rid of html-encoded characters:
    returnText=returnText.replace(/&nbsp;/gi," ");
    returnText=returnText.replace(/&amp;/gi,"&");
    returnText=returnText.replace(/&quot;/gi,'"');
    returnText=returnText.replace(/&lt;/gi,'<');
    returnText=returnText.replace(/&gt;/gi,'>');

    //-- return
    document.getElementById("output").value = returnText;
}

它与此 HTML 一起使用:

<textarea id="input" style="width: 400px; height: 300px;"></textarea><br />
<button onclick="convertHtmlToText()">CONVERT</button><br />
<textarea id="output" style="width: 400px; height: 300px;"></textarea><br />

我喜欢这个解决方案,因为它可以处理 html 特殊字符......但仍然远远不够......对我来说最好的答案是处理所有这些字符。 (这可能是 jquery 所做的)。
我认为 /<p.*>/gi 应该是 /<p.*?>/gi
请注意,要删除所有 <br> 标记,您可以改用一个好的正则表达式:/<br\s*\/?>/ 这样您只有一个替换而不是 3 个。在我看来,除了实体的解码之外,您可以有一个正则表达式,类似这样:/<[a-z].*?\/?>/
不错的剧本。但是表格内容呢?知道如何显示
@DanielGerson,对 html 进行编码真的很麻烦,真的很快,但是 best approach seems to be using the he library
h
hegemon
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

这是一个正则表达式版本,它对格式错误的 HTML 更具弹性,例如:

未封闭的标签

Some text <img

标签属性内的“<”、“>”

Some text <img alt="x > y">

换行符

Some <a href="http://google.com">

编码

var html = '<br>This <img alt="a>b" \r\n src="a_b.gif" />is > \nmy<>< > <a>"text"</a'
var text = html.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, "");

你怎么能把它翻转过来做相反的事情呢?我只想在文本部分使用 string.replace(),并保持任何 HTML 标记及其属性不变。
我个人最喜欢的,我还会添加删除换行符,例如:const deTagged = myString.replace(/<\/?("[^"]*"|'[^']*'|[^>])*(>|$)/g, ''); const deNewlined = deTagged.replace(/\n/g, '');
A
Anatol

来自 CSS 技巧:

https://css-tricks.com/snippets/javascript/strip-html-tags-in-javascript/

const originalString = `

嘿,那是 somthing

`; const strippedString = originalString.replace(/(<([^>]+)>)/gi, ""); console.log(strippedString);


这无法删除 ipt>' 那么剥离的版本将是这样的:''。所以这是一个 XSS 漏洞。
您应该将 [^<>] 更改为 [^>],因为有效标签不能包含 < 字符,然后 XSS 漏洞就会消失。
a
aWebDeveloper

下面的代码允许您保留一些 html 标签,同时剥离所有其他标签

function strip_tags(input, allowed) {

  allowed = (((allowed || '') + '')
    .toLowerCase()
    .match(/<[a-z][a-z0-9]*>/g) || [])
    .join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)

  var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
      commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;

  return input.replace(commentsAndPhpTags, '')
      .replace(tags, function($0, $1) {
          return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
      });
}

您应该引用来源 (phpjs)。如果您使用 allowed 参数,您很容易受到 XSS 攻击:stripTags('<p onclick="alert(1)">mytext</p>', '<p>') 返回 <p onclick="alert(1)">mytext</p>
F
FrigginGlorious

我只需要去掉 <a> 标记并将它们替换为链接的文本。

这似乎工作得很好。

htmlContent= htmlContent.replace(/<a.*href="(.*?)">/g, '');
htmlContent= htmlContent.replace(/<\/a>/g, '');

这仅适用于标签,需要调整才能成为广泛的功能。
是的,加上锚标记可以有许多其他属性,例如 title="..."
b
basarat

接受的答案大部分都可以正常工作,但是在 IE 中,如果 html 字符串是 null,您会得到 "null"(而不是 '')。固定的:

function strip(html)
{
   if (html == null) return "";
   var tmp = document.createElement("DIV");
   tmp.innerHTML = html;
   return tmp.textContent || tmp.innerText || "";
}

C
Community

使用 jQuery 剥离 html 的一种更安全的方法是首先使用 jQuery.parseHTML 创建一个 DOM,忽略任何脚本,然后让 jQuery 构建一个元素,然后只检索文本。

function stripHtml(unsafe) {
    return $($.parseHTML(unsafe)).text();
}

可以安全地从以下位置剥离 html:

<img src="unknown.gif" onerror="console.log('running injections');">

和其他漏洞。

开心!


i
ianaz

使用 jQuery,您可以简单地使用

$('#elementID').text()

M
MarekJ47

我自己创建了一个工作正则表达式:

str=str.replace(/(<\?[a-z]*(\s[^>]*)?\?(>|$)|<!\[[a-z]*\[|\]\]>|<!DOCTYPE[^>]*?(>|$)|<!--[\s\S]*?(-->|$)|<[a-z?!\/]([a-z0-9_:.])*(\s[^>]*)?(>|$))/gi, ''); 

D
Developer

简单的 2 行 jquery 来剥离 html。

 var content = "<p>checking the html source&nbsp;</p><p>&nbsp;
  </p><p>with&nbsp;</p><p>all</p><p>the html&nbsp;</p><p>content</p>";

 var text = $(content).text();//It gets you the plain text
 console.log(text);//check the data in your console

 cj("#text_area_id").val(text);//set your content to text area using text_area_id

m
math2001

使用jQuery:

function stripTags() {
    return $('<p></p>').html(textToEscape).text()
}

M
Mike Datsko

input 元素 support only one line text

文本状态表示元素值的单行纯文本编辑控件。

function stripHtml(str) {
  var tmp = document.createElement('input');
  tmp.value = str;
  return tmp.value;
}

更新:这按预期工作

function stripHtml(str) {
  // Remove some tags
  str = str.replace(/<[^>]+>/gim, '');

  // Remove BB code
  str = str.replace(/\[(\w+)[^\]]*](.*?)\[\/\1]/g, '$2 ');

  // Remove html and line breaks
  const div = document.createElement('div');
  div.innerHTML = str;

  const input = document.createElement('input');
  input.value = div.textContent || div.innerText || '';

  return input.value;
}

不起作用,请在发布答案时始终提及您使用的浏览器。这是不准确的,并且在 Chrome 61 中不起作用。标签只是呈现为字符串。