2010-06-07 5 views
3

하나의 작업으로 주어진 일반 텍스트 (HTML DOM이 아님)에서 제목 태그를 추출하려고합니다.일반 텍스트에서 제목 태그 추출

사례 1 : 예상

<html> 
<head> 
      <title>Title of the document</title> 
</head> 
<body> 
The content of the document...... 
</body> 
</html> 

:

: 문서

사례 2의 제목 나는 제목 태그 (들)을 추출해야 경우 아래에 있습니다

<html> 
<head> 
      <title>Title of the document</title> 
      <title>Continuing title</title> 
</head> 
<body> 
The content of the document...... 
</body> 
</html> 

예상 : 문서 계속 제목의 제목

사례 3 (중첩 제목 태그) 예상

<html> 
<head> 
      <title>Title of the document 
      <title>Continuing title</title></title> 
</head> 
<body> 
The content of the document...... 
</body> 
</html> 

: I가 원하는 문서를 계속 제목

제목 자바 스크립트에서 정규식을 사용하여 제목 태그를 추출합니다. Reg-ex는 위의 경우에 작동해야합니다.

사람이이 깨진 "의사 HTML"를 사용하여이 특정 문제에 대한 솔루션입니다 사전

+2

Regex 및 기형의 HTML이 기뻐합니다. – kennytm

+0

제목 태그는 제목 태그가 아니라 제목 * 요소 *입니다. http://perfectionkills.com/tag-is-not-an-element-or-is-it/ –

+0

글쎄, 이것은 HTML이 아니기 때문에 그가 좋아하는 어떤 방식 으로든 부를 수 있습니다 :-) – RoToRa

답변

1

에서 감사합니다 ... 알려 this..please에 대해 알고입니다. 그것은 일반 HTML에 적용 아니다 :

function extractTitle(text) { 
    var m = /<title>(.*)<\/title>/.exec(text); 
    if (m && m[1]) { 
    return m[1].replace(/<\/?title>/g," ").replace(/\s+/," "); 
    } 
    return; // returns undefined 
} 
+0

두 번째 예제에서 닫히고 여는 제목 태그 사이의 공백은 변경되지 않습니다. 예를 들어이 경우 많은 공백이 반환되지만 태그가 서로 옆에 쓰여진 경우 결과는 '문서 제목 연속 판매'가됩니다. –

+0

@Marcel : True. 태그를 공백으로 바꾸고 모든 공백을 하나의 공백으로 축소하는 바꾸기를 추가합니다. – RoToRa

2

Don't parse HTML with regexen!를 진심으로, 그것은 일반적인 경우에 사실상 불가능하다. 그리고 실제로, 당신은 regexen으로 원하는 것을 할 수 없습니다. 균등 중첩 된 쌍의 괄호가 일치하는 것과 동일한 문제입니다. 단, 중첩 된 <title>/</title> 쌍과 일치시키고 자하는 것은 일반 언어가 아닙니다.

(편집 1 :. 당신이 DOM에 접근하지 않았다고 본 이후 내가 내 대답을 수정했다, 나는 원래 무엇을했다, 아래 참조)에 따라서

, 왜 필요합니까 이것을하기 위해? 아마도 더 좋은 방법이있을 것입니다. 이 태그가 붙은 자바 스크립트이지만 대답에는 언급하지 않습니다. 자바 스크립트를 사용하지 않는다면 아마도 HTML 파서를 사용할 수있을 것입니다. 아마도 더 나은 선택 일 것입니다. 자바 스크립트를 사용하고 있다면 여전히 있을지 모르지만 저는 자바 스크립트 전문가가 아닙니다.

이제 여러 개의 또는 중첩 된 title 태그가있는 것은 실제로 유효한 HTML이 아니므로 에 대해 걱정할 필요가 없습니다. 이것이 사실이라면 더 많은 가정을 할 수 있다면 실제로 작동 할 수있는 유스 케이스를 만들 수 있습니다. 예를 들면 : 코멘트가없고, CDATA 블럭이 없습니다. (네스트가 없기 때문에 이것을 처리 할 수는 있겠지만) 그러나 나는 잊고있는 엣지 경우가있을 수 있습니다! 또한 Safari와 Firefox는 세 번째 케이스를 중첩 된 제목 태그로 처리하지 않고 리터럴 문자열 Title of the document <title> Continuing title을 포함하는 하나의 제목 태그로 보았습니다. 따라서, 당신이 그 케이스를 무시할 수 있다면, 이 작동 할 수있는 깨지기 쉬운 정규식 세트를 함께 해킹하는 것이 가능할 수 있습니다. 아마 (가볍게 시험 한!이 같은) 뭔가 :

// Edit 2: Made this function case-insensitive where it needed to be. 
// Edit 3: Used substring() instead of replace() to remove the extraneous 
//   title tags and fixed the "not matching" case. 
function getTitle(html) { 
    return (html.replace(/<!\[CDATA\[(.+?)\]\]>/g 
         , function (_match, body) { 
          return body.replace(/&/g, '&amp;') 
            .replace(/</g, '&lt;') 
            .replace(/>/g, '&gt;') 
         }) 
       .replace(/<!--.+?-->/g, '') 
       .match(/<title>.+?<\/title>/ig) || []) 
       .map(function (t) { return t.substring(7, t.length - 8) }) 
       .join(' ') 
} 

내가 아닌 HTML 전문가입니다, 그래서 아마 몇 가장자리 경우를 놓친하지만 여기가하는 일입니다. 먼저 CDATA section을 찾습니다. 우리는 그 내부를 가져 와서 모든 불법적 인 성격을 동등한 존재로 바꾸고 <![CDATA[]]>을 제거합니다. 다음으로, 우리는 모든 코멘트를 삭제합니다. 그 다음에는 각각의 제목을 일치시키고 일치 항목의 배열을 가져옵니다 (일치 항목의 배열을 추출하는 것은 하위 그룹 추출과 호환되지 않습니다). 이는 invalid-multiple-title입니다. 편집 3 : 그런 다음 일치하지 않는지 확인한 후 .match()null을 반환하고 그 대신에 []을 반환합니다. 이 방법으로, 우리는 항상 배열을가집니다. 그런 다음 처음부터 끝까지 태그를 자르고 (편집 3 :은이 단계에서 regexen을 더 이상 사용하지 않습니다.) 마지막으로 각 제목 단편에 공백을 넣습니다. 이건 내가 처리 할거야, , 케이스 1과 케이스 2를 생각하라. 법적 소송 (사례 1) 만 필요한 경우 마지막 세 줄 (} 제외)을 단 하나의 줄 .match(/<title>(.+?)<\/title>/)[0]으로 바꿉니다. 그러나 이것이 많은 경우에 (비록) 생각할 수도 있지만, 나는 우리의 입력 (예 :, 제목 태그가 모두 함께 나타나고 원하는 위치)과 우리가 찾고있는 사실 단일 (집합) <title>...</title> s) 및 일부 가장자리 케이스 또는 기타를 놓친 것 같습니다. 다행히도 더 나은 솔루션을 사용할 수 있다는 것을 알게 될 것입니다.


편집 1 : 나는 일반 텍스트 작업을 할 필요가 있다는 사실을 놓친; 내 원래 대답의 나머지 부분은 DOM에 대한 액세스 권한이 있다고 가정합니다. 나는 후손을 위해 이곳에 남겨 두겠다. 그러나 그것은 특별히 당신과 관련이 없다. 자바 스크립트에서 DOM에 대한 액세스 권한을 가지고 있다면 당신은 하나 적절한 HTML이 있다면

는 다음을 수행 할 수 title 태그 : 당신이 실제로 HTML이있는 경우

var titles = document.getElementsByTagName('title') 
var titleText = titles.length > 0 ? titles[0].text : '' 

그러나, 두 번째 이가지 경우처럼 보이는 당신은 우리에게 보여 줬지만 (나는 희망하지 않지만 결코 알지 못합니다), 그러면 당신은 다른 것을해야 할 것입니다. 파이어 폭스 나 사파리는 세 번째 케이스를 중첩 된 타이틀 태그로 취급하지 않고 리터럴 문자열 Title of the document <title> Continuing title을 포함하는 하나의 타이틀 태그로 보았다. 당신은 처음 두 경우를 처리 할 필요가있는 경우,이 작동합니다 :

var titles = document.getElementsByTagName('title') 
var tlength = titles.length 
var titleText = '' 
for (var i = 0; i < tlength; ++i) 
    titleText += titles[i].text 

을 그리고 당신은 세 번째 경우가 있다면, 당신이해야 할 것은 외부 <title> 태그를 제거되는 약간 까다 롭지 만 아마도 그렇지 않다. 위와 같이 형식이 잘못된 HTML을 제외하고는 <title>이 표시되지 않는다는 것을 알고 있다면 replace 메서드를 사용하여 제거 할 수 있습니다. 단일 standalone- <title>, 경우에, 당신은, 당신이

// Edit 2: Case-insensitivity 
var titles = document.getElementsByTagName('title') 
var tlength = titles.length 
var titleText = '' 
for (var i = 0; i < tlength; ++i) 
    titleText += titles[i].text.replace(/<title>/ig,'') 

<title> 경우가 다른 이유에 대한 올바른 문자열로 발생할 수있는하려는 잘못된 다중 standalone- <title> 경우

// Edit 2: Case-insensitivity 
var titles = document.getElementsByTagName('title') 
var titleText = titles.length > 0 ? titles[0].text.replace(/<title>/ig,'') : '' 

을 원하는, 그러나 그때 당신은 곤경에 빠졌습니다. 을 알아 내야 만합니다. 문자열에 있었기 때문에 당신이 가정한다면 문자열을 바꿉니다. 그리고 제가 말할 수있는 한, 그렇게 할 수있는 좋은 방법이 없습니다. 그러나 합법적 인 HTML을 가지고 있기를 바랍니다.

+1

이것은 (매우) 좋은 대답이지만, 나는 이것이 OP의 요구에 어울리는 것이라고 생각하지 않는다 : "주어진 텍스트 (HTML DOM이 아님)에서 제목 태그 [sic!]를 추출하십시오." 그는 평범한 텍스트를 파싱하고 DOM에서 제목 요소를 추출하지 않으려한다고 생각합니다. –

+1

* D' oh *, 나는 그것을 놓쳤다. 아아, 여기에 남겨 두겠습니다. 첫 번째 부분은 여전히 ​​관련이 있습니다. 실제로는 정규 표현식으로는 불가능합니다. –

+0

좋아요, 실제로 관련성이있는 것을 추가했습니다. –

관련 문제