353

HTMLテキストを含む文字列を解析したい。JavaScriptでやりたいです。

Pure JavaScript HTMLパーサーライブラリを試しましたが、文字列からではなく、現在のページのHTMLを解析しているようです。以下のコードを試してみると、ページのタイトルが変わるためです。

var parser = new HTMLtoDOM("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>", document);

私の目標は、文字列のように読んだHTML外部ページからリンクを抽出することです。

それを行うためのAPIを知っていますか?

4

14 に答える 14

463

ダミーのDOM要素を作成し、それに文字列を追加します。次に、他のDOM要素と同じように操作できます。

var el = document.createElement( 'html' );
el.innerHTML = "<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>";

el.getElementsByTagName( 'a' ); // Live NodeList of your anchor elements

編集:ファンを喜ばせるためにjQueryの回答を追加してください!

var el = $( '<div></div>' );
el.html("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>");

$('a', el) // All the anchor elements
于 2012-05-14T14:14:36.350 に答える
328

それは非常に簡単です:

var parser = new DOMParser();
var htmlDoc = parser.parseFromString(txt, 'text/html');
// do whatever you want with htmlDoc.getElementsByTagName('a');

MDNによると、これをChromeで行うには、次のようにXMLとして解析する必要があります。

var parser = new DOMParser();
var htmlDoc = parser.parseFromString(txt, 'text/xml');
// do whatever you want with htmlDoc.getElementsByTagName('a');

現在、Webkitでサポートされていないため、Florianの回答に従う必要があり、ほとんどの場合、モバイルブラウザで動作するかどうかは不明です。

編集:現在広くサポートされています

于 2014-02-19T03:28:46.183 に答える
34

編集:以下の解決策は、html、head、bodyが削除されているため、HTMLの「フラグメント」のみを対象としています。この質問の解決策は、DOMParserのparseFromString()メソッドだと思います。

const parser = new DOMParser();
const document = parser.parseFromString(html, "text/html");

HTMLフラグメントの場合、ここにリストされているソリューションはほとんどのHTMLで機能しますが、特定の場合には機能しません。

たとえば、解析してみてください<td>Test</td>。これは、div.innerHTMLソリューション、DOMParser.prototype.parseFromString、range.createContextualFragmentソリューションでは機能しません。tdタグが失われ、テキストのみが残ります。

jQueryだけがそのケースをうまく処理します。

したがって、将来の解決策(MS Edge 13以降)は、テンプレートタグを使用することです。

function parseHTML(html) {
    var t = document.createElement('template');
    t.innerHTML = html;
    return t.content;
}

var documentFragment = parseHTML('<td>Test</td>');

古いブラウザの場合、jQueryのparseHTML()メソッドを独立した要点に抽出しました-https: //gist.github.com/Munawwar/6e6362dbdf77c7865a99

于 2015-10-24T17:52:11.917 に答える
25
var doc = new DOMParser().parseFromString(html, "text/html");
var links = doc.querySelectorAll("a");
于 2012-05-14T14:18:00.727 に答える
7

次の関数は次のparseHTMLいずれかを返します。


コード :

function parseHTML(markup) {
    if (markup.toLowerCase().trim().indexOf('<!doctype') === 0) {
        var doc = document.implementation.createHTMLDocument("");
        doc.documentElement.innerHTML = markup;
        return doc;
    } else if ('content' in document.createElement('template')) {
       // Template tag exists!
       var el = document.createElement('template');
       el.innerHTML = markup;
       return el.content;
    } else {
       // Template tag doesn't exist!
       var docfrag = document.createDocumentFragment();
       var el = document.createElement('body');
       el.innerHTML = markup;
       for (i = 0; 0 < el.childNodes.length;) {
           docfrag.appendChild(el.childNodes[i]);
       }
       return docfrag;
    }
}

使い方 :

var links = parseHTML('<!doctype html><html><head></head><body><a>Link 1</a><a>Link 2</a></body></html>').getElementsByTagName('a');
于 2013-12-09T03:38:55.680 に答える
7

ChromeとFirefoxでHTMLを解析する最速の方法は、Range#createContextualFragmentです。

var range = document.createRange();
range.selectNode(document.body); // required in Safari
var fragment = range.createContextualFragment('<h1>html...</h1>');
var firstNode = fragment.firstChild;

可能な場合はcreateContextualFragmentを使用し、そうでない場合はinnerHTMLにフォールバックするヘルパー関数を作成することをお勧めします。

ベンチマーク: http: //jsperf.com/domparser-vs-createelement-innerhtml/3

于 2015-02-08T04:41:29.693 に答える
6
const parse = Range.prototype.createContextualFragment.bind(document.createRange());

document.body.appendChild( parse('<p><strong>Today is:</strong></p>') ),
document.body.appendChild( parse(`<p style="background: #eee">${new Date()}</p>`) );


NodeNode(の先頭)内の 有効な子のみRangeが解析されます。そうしないと、予期しない結果が発生する可能性があります。

// <body> is "parent" Node, start of Range
const parseRange = document.createRange();
const parse = Range.prototype.createContextualFragment.bind(parseRange);

// Returns Text "1 2" because td, tr, tbody are not valid children of <body>
parse('<td>1</td> <td>2</td>');
parse('<tr><td>1</td> <td>2</td></tr>');
parse('<tbody><tr><td>1</td> <td>2</td></tr></tbody>');

// Returns <table>, which is a valid child of <body>
parse('<table> <td>1</td> <td>2</td> </table>');
parse('<table> <tr> <td>1</td> <td>2</td> </tr> </table>');
parse('<table> <tbody> <td>1</td> <td>2</td> </tbody> </table>');

// <tr> is parent Node, start of Range
parseRange.setStart(document.createElement('tr'), 0);

// Returns [<td>, <td>] element array
parse('<td>1</td> <td>2</td>');
parse('<tr> <td>1</td> <td>2</td> </tr>');
parse('<tbody> <td>1</td> <td>2</td> </tbody>');
parse('<table> <td>1</td> <td>2</td> </table>');
于 2019-03-07T14:22:46.083 に答える
4

jQueryを使用することに慣れている場合は、HTMLの文字列からデタッチされたDOM要素を作成するための優れた機能がいくつかあります。これらは、通常の方法で照会できます。例:

var html = "<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>";
var anchors = $('<div/>').append(html).find('a').get();

編集-正しい@Florianの答えを見たところです。これは基本的に彼が言ったこととまったく同じですが、jQueryを使用しています。

于 2012-05-14T14:17:13.583 に答える
3

1ウェイ

使用するdocument.cloneNode()

パフォーマンスは次のとおりです。

呼び出しにdocument.cloneNode()は約0.22499999977299012ミリ秒かかりました。

そして多分もっとなるでしょう。

var t0, t1, html;

t0 = performance.now();
   html = document.cloneNode(true);
t1 = performance.now();

console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")

html.documentElement.innerHTML = '<!DOCTYPE html><html><head><title>Test</title></head><body><div id="test1">test1</div></body></html>';

console.log(html.getElementById("test1"));

2ウェイ

使用するdocument.implementation.createHTMLDocument()

パフォーマンスは次のとおりです。

呼び出しにdocument.implementation.createHTMLDocument()は約0.14000000010128133ミリ秒かかりました。

var t0, t1, html;

t0 = performance.now();
html = document.implementation.createHTMLDocument("test");
t1 = performance.now();

console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")

html.documentElement.innerHTML = '<!DOCTYPE html><html><head><title>Test</title></head><body><div id="test1">test1</div></body></html>';

console.log(html.getElementById("test1"));

3ウェイ

使用するdocument.implementation.createDocument()

パフォーマンスは次のとおりです。

呼び出しにdocument.implementation.createHTMLDocument()は約0.14000000010128133ミリ秒かかりました。

var t0 = performance.now();
  html = document.implementation.createDocument('', 'html', 
             document.implementation.createDocumentType('html', '', '')
         );
var t1 = performance.now();

console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")

html.documentElement.innerHTML = '<html><head><title>Test</title></head><body><div id="test1">test</div></body></html>';

console.log(html.getElementById("test1"));

4ウェイ

使用するnew Document()

パフォーマンスは次のとおりです。

呼び出しにdocument.implementation.createHTMLDocument()は約0.13499999840860255ミリ秒かかりました。

  • ノート

ParentNode.append2020年の実験技術です。

var t0, t1, html;

t0 = performance.now();
//---------------
html = new Document();

html.append(
  html.implementation.createDocumentType('html', '', '')
);
    
html.append(
  html.createElement('html')
);
//---------------
t1 = performance.now();

console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.")

html.documentElement.innerHTML = '<html><head><title>Test</title></head><body><div id="test1">test1</div></body></html>';

console.log(html.getElementById("test1"));
于 2020-11-29T05:06:20.777 に答える
3

node.jsでこれを行うには、 node-html-parserのようなHTMLパーサーを使用できます。構文は次のようになります。

import { parse } from 'node-html-parser';

const root = parse('<ul id="list"><li>Hello World</li></ul>');

console.log(root.firstChild.structure);
// ul#list
//   li
//     #text

console.log(root.querySelector('#list'));
// { tagName: 'ul',
//   rawAttrs: 'id="list"',
//   childNodes:
//    [ { tagName: 'li',
//        rawAttrs: '',
//        childNodes: [Object],
//        classNames: [] } ],
//   id: 'list',
//   classNames: [] }
console.log(root.toString());
// <ul id="list"><li>Hello World</li></ul>
root.set_content('<li>Hello World</li>');
root.toString();    // <li>Hello World</li>
于 2021-09-16T04:45:27.327 に答える
2

最善の方法は、このAPIを次のように使用することだと思います。

//Table string in HTML format
const htmlString = '<table><tbody><tr><td>Cell 1</td><td>Cell 2</td></tr></tbody></table>';

//Parse using DOMParser native way
const parser = new DOMParser();
const $newTable = parser.parseFromString(htmlString, 'text/html');

//Here you can select parts of your parsed html and work with it
const $row = $newTable.querySelector('table > tbody > tr');

//Here i'm printing the number of columns (2)
const $containerHtml = document.getElementById('containerHtml');
$containerHtml.innerHTML = ['Your parsed table have ', $row.cells.length, 'columns.'].join(' ');
<div id="containerHtml"></div>

于 2021-12-09T19:50:27.177 に答える
0

AngularNGXBootstrapポップオーバーのポップオーバーで解析された要素のinnerHTMLを使用する必要がありました。これは私のために働いた解決策です。

public htmlContainer = document.createElement( 'html' );

コンストラクターで

this.htmlContainer.innerHTML = ''; setTimeout(() => { this.convertToArray(); });

 convertToArray() {
    const shapesHC = document.getElementsByClassName('weekPopUpDummy');
    const shapesArrHCSpread = [...(shapesHC as any)];
    this.htmlContainer = shapesArrHCSpread[0];
    this.htmlContainer.innerHTML = shapesArrHCSpread[0].textContent;
  }

HTMLで

<div class="weekPopUpDummy" [popover]="htmlContainer.innerHTML" [adaptivePosition]="false" placement="top" [outsideClick]="true" #popOverHide="bs-popover" [delay]="150" (onHidden)="onHidden(weekEvent)" (onShown)="onShown()">
于 2021-05-28T16:34:26.480 に答える
0
function parseElement(raw){
    let el = document.createElement('div');
    el.innerHTML = raw;
    let res = el.querySelector('*');
    res.remove();
    return res;
}

注:生の文字列は1要素を超えてはなりません

于 2021-12-29T13:12:11.333 に答える
-1
let content = "<center><h1>404 Not Found</h1></center>"
let result = $("<div/>").html(content).text()

内容:<center><h1>404 Not Found</h1></center>
結果:"404 Not Found"

于 2020-10-07T10:53:39.420 に答える