2013-06-21 4 views
17

Я пытаюсь прочитать источник веб-страницы в R и обрабатывать его как строки. Я пытаюсь извлечь абзацы и удалить теги html из текста абзаца. Я бегу в следующей задаче:Удаление html-тегов из строки в R

Я попытался реализовать функцию, чтобы удалить HTML-теги:

cleanFun=function(fullStr) 
{ 
#find location of tags and citations 
tagLoc=cbind(str_locate_all(fullStr,"<")[[1]][,2],str_locate_all(fullStr,">")[[1]][,1]); 

#create storage for tag strings 
tagStrings=list() 

#extract and store tag strings 
for(i in 1:dim(tagLoc)[1]) 
{ 
    tagStrings[i]=substr(fullStr,tagLoc[i,1],tagLoc[i,2]); 
} 

#remove tag strings from paragraph 
newStr=fullStr 
for(i in 1:length(tagStrings)) 
{ 
    newStr=str_replace_all(newStr,tagStrings[[i]][1],"") 
} 
return(newStr) 
}; 

Это работает для некоторых тегов, но не все теги, пример, когда это не удается в следующей строке:

test="junk junk<a href=\"/wiki/abstraction_(mathematics)\" title=\"abstraction (mathematics)\"> junk junk" 

цель будет получать:

cleanFun(test)="junk junk junk junk" 

Однако эта лань Кажется, он работает. Я думал, что это может быть связано с длиной строки или escape-символами, но я не мог найти решение, связанное с ними.

+0

Отредактировано, чтобы исправить ошибки, допущенные при вводе кода. –

+0

Здесь многое происходит ... Для начала это R, поэтому нет '.'. Вы в основном ищете 'gsub' и соответствующее регулярное выражение (в этом случае уже ответили здесь: http: //stackoverflow.com/questions/10225690/removing-data-with-tags-from-a-vector/10225883 # 10225883). Существуют и другие проблемы с кодом ('dim (tagLoc) [1]' не делает то, что вы так думаете), но я не думаю, что это вопрос вашего вопроса. – alexwhan

ответ

34

Это может быть достигнуто лишь с помощью регулярных выражений и Grep семей:

cleanFun <- function(htmlString) { 
    return(gsub("<.*?>", "", htmlString)) 
} 

Это также будет работать с несколькими HTML-тегами в одной строке!

+4

В основном, что он делает, находит ли он какие-либо экземпляры шаблона '' <.*?> "в' htmlString 'и заменяет его пустой строкой '' '' и возвращает результат. Для соответствия шаблону вам нужно научиться регулярным выражениям. Единственная немного сложная часть - ''. *? "', '?' Делает ее не жадной, поэтому, если у вас есть несколько тегов, например « junk», она будет соответствовать «» и «» вместо целая строка. –

+0

«Всякий раз, когда вы пытаетесь разобрать HTML с регулярными выражениями, нечестивый ребенок плачет кровью девственниц, а русские хакеры пишут ваш webapp_» Из [этого основного ответа] (https://stackoverflow.com/a/1732454/1156245) , – geotheory

+1

Fine I'm bite - removal! = Parsing –

2

Во-первых, ваша строка темы вводит в заблуждение; в строке, которую вы разместили, нет обратных косых черт. Вы стали жертвой одного из классических промахов: не так плохо, как участвовать в наземной войне в Азии, но все равно. Вы ошибаетесь в использовании R \ для обозначения экранированных символов для буквальной обратной косой черты. В этом случае \" означает знак двойной кавычки, а не два буквальных символа \ и ". Вы можете использовать cat, чтобы увидеть, что на самом деле будет выглядеть строка, если бы экранированные символы обрабатывались буквально.

Во-вторых, вы используете регулярные выражения для синтаксического анализа HTML. (Они не отображаются в вашем коде, но они используются под капотом в str_locate_all и str_replace_all.) Это еще один из классических промахов; см. here для дополнительной экспозиции.

В-третьих, вы должны упомянуть в своем посте, что используете пакет stringr, но это лишь незначительная ошибка при сравнении.

+0

Линия темы была ошибкой, отредактировала ее. –

5

Подход с использованием пакета qdap:

library(qdap) 
bracketX(test, "angle") 

## > bracketX(test, "angle") 
## [1] "junk junk junk junk" 
+1

Я установил ваш пакет и посмотрел исходный код для различных функций. 'bracketX' очень полезен для гораздо более общего класса проблем. Еще один для инструментария. – user1609452

2

Это может быть проще с суб или GSUB?

> test <- "junk junk<a href=\"/wiki/abstraction_(mathematics)\" title=\"abstraction (mathematics)\"> junk junk" 
> gsub(pattern = "<.*>", replacement = "", x = test) 
[1] "junk junk junk junk" 
+0

1 Проблема с этим кодом может быть, она заменяет первое появление '<' до последнего появления '>'. поэтому, когда есть несколько тегов html, это может быть проблемой –

3

Лучше всего не анализировать html, используя регулярные выражения. RegEx match open tags except XHTML self-contained tags

Используйте упаковку, как XML. Измените код html в синтаксическом анализе, используя, например, htmlParse, и используйте xpaths, чтобы найти количество, относящееся к вам.

UPDATE:

Чтобы ответить на вопрос, что ОП в

require(XML) 
xData <- htmlParse('yourfile.html') 
xpathSApply(xData, 'appropriate xpath', xmlValue) 
+1

Это применимо в этом случае? Он вообще не хочет разбирать теги, он хочет их разбить. –

+1

OP, вероятно, просто хочет использовать 'xpathSapply (doc, 'somepath', xmlValue)'. – user1609452

+0

Ссылка, которую вы указали, предоставляется так часто, когда когда-либо кто-то предлагает регулярное выражение для HTML, но на самом деле это всего лишь руководство, а не правило. Я согласен с тем, что XML (и т. Д.) Следует использовать, если это возможно, но иногда это невозможно или непрактично. Чтобы просто думать, что 'HTML + regex = bad' избегает принятия решений. Иногда регулярное выражение является подходящим. Мы не знаем формат данных или источник. Это голосование было проголосовано 2 раза, но на самом деле не дает OP ответа. –

8

Другой подход, использующий tm.plugin.webmining, который использует XML внутренне.

> library(tm.plugin.webmining) 
> extractHTMLStrip("junk junk<a href=\"/wiki/abstraction_(mathematics)\" title=\"abstraction (mathematics)\"> junk junk") 
[1] "junk junk junk junk" 
+0

+1 очень интересно. Я не использовал этот пакет. – user1609452