Что нового

[RegExp] Очистка веб-страницы, созданной в WORD, от лишних ключей в тэгах

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Есть документ WORD с текстами и таблицами, он сохраняется как вэб-страница, но WORD, как известно, добавляет огромное количество лишних ключей в теги...
Подскажите, пожалуйста, как почистить теги <p>, <div>, <span>, <td>, единственно, очень желательно сохранить ключи colspan и rowspan, отвечающие за объединение ячеек... Можно удалить и другие ненужные теги и ключи, но без потери текста...

Пример:
Есть текст:
Код:
<p class=MsoNormal><span lang=EN-US style='mso-ansi-language:EN-US'><o:p> </o:p></span></p>
Нужно получить:
Код:
<p><span> </span></p>
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Код:
$sHtml = "<p class=MsoNormal><span lang=EN-US style='mso-ansi-language:EN-US'><o:p> </o:p></span></p>"

ConsoleWrite(_StringStripTags($sHtml, 'p|span', 'o:p') & @LF)

Func _StringStripTags($sStr, $sTags, $sRemoveTags = '')
	Local $sRet
	
	$sRet = StringRegExpReplace($sStr, '<(' & $sTags & ').*?>', '<\1>')
	
	If $sRemoveTags <> '' Then
		$sRet = StringRegExpReplace($sRet, '</?' & $sRemoveTags & '>', '')
	EndIf
	
	Return $sRet
EndFunc
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Creator
Спасибо за идею...
Вот в результате что получилось:

Код:
; НАЧАЛО

 $OPEN=FileOpen('site.htm')
 $TEXT=FileRead($OPEN)
 FileClose($OPEN)

 $CLEAR='p|span|div|body|br|table|td|tr|b|img|html'
 $DELETE='m:|o:|/o:|w:|v:|/v:|!\[endif\]|!\[if|head|/head|meta|link|!--'
 $TWIN='xml|style'

 $TEXT=_StringStripTags($TEXT,$CLEAR,$DELETE,$TWIN)

 $TEXT=StringReplace($TEXT,@CRLF&' '&@CRLF,'')

 Do
  $TEXT=StringReplace($TEXT,@CRLF&@CRLF,@CRLF)
 Until @extended=0

 $OPEN=FileOpen('site1.htm',2)
 FileWrite($OPEN,$TEXT)
 FileClose($OPEN)

 MsgBox(0,'','Скрипт завершён...')

 Func _StringStripTags($sStr,$CLEAR='',$DELETE='',$TWIN='')
  If $CLEAR<>'' Then $sStr=StringRegExpReplace($sStr,'(?s)<('&$CLEAR&')(.*?)>','<\1>')
  If $DELETE<>'' Then $sStr=StringRegExpReplace($sStr,'(?s)<('&$DELETE&')(.*?)>','')
  If $TWIN<>'' Then $sStr=StringRegExpReplace($sStr,'(?s)<('&$TWIN&')>(.*)</('&$TWIN&')>','')
  Return $sStr
 EndFunc

; КОНЕЦ


Осталась только проблема, как сохранить ключи colspan="x" и rowspan="x" в теге <td>...
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
snoitaleR [?]
как сохранить ключи colspan="x" и rowspan="x" в теге <td>
Как то так:

Код:
$sHtml = "<p class=MsoNormal><span lang=EN-US style=mso-ansi-language:EN-US><o:p> </o:p></span></p>"

$sClear_Tags = 'p|span|div|body|br|table|td|tr|b|img|html'
$sDel_Tags = 'm:|o:|w:|v:|!\[endif\]|!\[if|head|meta|link|!--'
$sExclude_Params = 'class|lang'

$sHtml = _StringStripTags($sHtml, $sClear_Tags, $sDel_Tags, $sExclude_Params)

ConsoleWrite($sHtml & @LF)

Func _StringStripTags($sStr, $sClear_Tags, $sDel_Tags = '', $sExclude_Params = '')
    Local $sRet
	
    $sRet = StringRegExpReplace($sStr, '<(' & $sClear_Tags & ').*?( (?:' & $sExclude_Params & ')=[^\h]*?)?( [^\h]*?)?>', '<\1\2>')
    
    If $sDel_Tags <> '' Then
        $sRet = StringRegExpReplace($sRet, '<(' & $sDel_Tags & ')(.*?)>((?s).*?)</\1\2?>', '\3')
    EndIf
	
    Return $sRet
EndFunc



У тебя в примере конструкцию
Код:
Do
  $TEXT=StringReplace($TEXT,@CRLF&@CRLF,@CRLF)
 Until @extended=0

можно заменить на
Код:
$TEXT = StringRegExpReplace($TEXT, '(\r\n){2}', @CRLF)


P.S.
Мне так и не ясно, зачем у тебя пробелы в начале каждой строки?
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
CreatoR
Если исключаемые ключи находятся в одном тэге, то после обработки регулярным выражением, остаётся последний, первый удаляется...

OffTopic:

По поводу пробелов в начале строк...
Жаль что мой стиль оформления скриптов не совпадает с Tidy, но у меня иерархия скрипта ведётся пробелами, и первый уровень иерархии - комментарий, начинающийся с точки с запятой... Далее каждый уровень вложенности выделяется одним пробелом...


Не по теме:

Шаблон заголовка для оффтопика можно сделать русским... :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
snoitaleR [?]
Если исключаемые ключи находятся в одном тэге, то после обработки регулярным выражением, остаётся последний, первый удаляется...
Ну да, я предполагал что нужен только один параметр.

OffTopic:
у меня иерархия скрипта ведётся пробелами, и первый уровень иерархии - комментарий, начинающийся с точки с запятой... Далее каждый уровень вложенности выделяется одним пробелом...
Но это же не удобно, для этого есть символы табуляции.
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
Код:
#include <Array.au3>
; $sText = FileRead(@ScriptDir & '\1.htm')
$sText = FileRead(@ScriptDir & '\site.htm')

$sText = _ClearHTML($sText)

$hFile = FileOpen(@ScriptDir & '\2.htm', 2)
FileWrite($hFile, $sText)
FileClose($hFile)


Func _ClearHTML($sText)
	Local $0, $DelAll, $DelTag, $i, $Rep, $teg, $Tr
	$Tr = 0
	$teg = 'p|div|span|html|body|b|table|td|tr|th|font|img|br'
	$sText=StringRegExpReplace($sText, '(?s)<!--.*?-->', '') ; удаление комментариев
	
	; ============= блок colspan, rowspan
	$0 = Chr(0)
	$Rep = StringRegExp($sText, '(?s)(<[^<>]+?(?:colspan|rowspan)[^<>]+?>)', 3) ; в массив
	If Not @error Then
		$Tr = 1
		$sText = StringRegExpReplace($sText, '(?s)(<[^<>]+?(?:colspan|rowspan)[^<>]+?[^/]>)', $0) ; временная подмена
	EndIf
	$sText = StringRegExpReplace($sText, '(?s)(<(?:' & $teg & '))[\r\n]* [^<>]*?(>)', '\1\2') ; очистка
	
	If $Tr Then
		For $i = 0 To UBound($Rep) - 1
			$Rep[$i] = _Replace($Rep[$i])
			$sText = StringReplace($sText, $0, $Rep[$i], 1)
		Next
	EndIf
	; =============
	
	$sText=StringReplace($sText, '<p><o:p> </o:p></p>', '

') ; замена переносов строк
	; $sText=StringRegExpReplace($sText, '(?s)(<('&$teg&').*?>)(.*?)</\2>(\s*)\1', '\1\3\4') ; очистка дублирования
	$sText=StringRegExpReplace($sText, '(?s)<('&$teg&')[^<>]*?>[\x{A0}\s]*?</\1>', '') ; очистка тегов без контента
	
	$DelAll='xml|style|script'
	$sText=StringRegExpReplace($sText,'(?s)<('&$DelAll&')[^<>]*>(.*?)</\1>','') ; удаление с содержимым
	
	$DelTag='span'
	$sText=StringRegExpReplace($sText,'(?s)</?('&$DelTag&')[^<>]*>','') ; удаление самих тегов
	
	Return $sText
EndFunc

Func _Replace($Rep)
	$teg = 'table|td|tr|th'
	$aRep=StringRegExp($Rep, '((?:colspan|rowspan)\h*=\h*"?\d+"?)', 3)
	$Rep = StringRegExpReplace($Rep, '(?s)(<(?:' & $teg & ')) .*?(>)', '\1') ; очистка
	For $i = 0 To UBound($aRep)-1
		$Rep &= ' ' & $aRep[$i]
	Next
	$Rep &= '>'
	Return $Rep
EndFunc
 
Автор
snoitaleR

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
В ожидании полного решения с помощью регулярных выражений выкладываю вариант скрипта на основе строковых функций:

Код:
; НАЧАЛО

 $DELETE='head'
 $CLEAR='p|body|br|table|tr|b|img|html'
 $WRAPPER='v:|/v:|o:|/o:|![endif]|![if|span|/span|div|/div|!--'
 Dim $EXCLUDE[1][2]=[['td','colspan|rowspan']]

 $OPEN=FileOpen(@ScriptDir&'\site.htm')
 $TEXT=FileRead($OPEN)
 FileClose($OPEN)

; Удаление парных тэгов вместе с содержимым

 $A=StringSplit($DELETE,'|')

 For $COUNTER=1 To UBound($A)-1
  While True
   $B=1
   $B=StringInStr($TEXT,'<'&$A[$COUNTER],0,1,$B)
   If $B=0 Then ExitLoop
   $E=StringInStr($TEXT,'</'&$A[$COUNTER],0,1,$B)
   $E=StringInStr($TEXT,'>',0,1,$E)
   $TEXT1=StringLeft($TEXT,$B-1)
   $TEXT2=StringTrimLeft($TEXT,$E)
   $TEXT=$TEXT1&$TEXT2
  WEnd
 Next

; Очистка тэгов от ключей

 $A=StringSplit($CLEAR,'|')

 For $COUNTER=1 To UBound($A)-1
  While True
   $B=1
   $B=StringInStr($TEXT,'<'&$A[$COUNTER]&' ',0,1,$B)
   If $B=0 Then ExitLoop
   $E=StringInStr($TEXT,'>',0,1,$B)
   $TEXT1=StringLeft($TEXT,$B+StringLen($A[$COUNTER]))
   $TEXT2=StringTrimLeft($TEXT,$E-1)
   $TEXT=$TEXT1&$TEXT2
  WEnd
 Next

; Удаление парных тэгов с сохранением содержимого

 $A=StringSplit($WRAPPER,'|')

 For $COUNTER=1 To UBound($A)-1
  While True
   $B=1
   $B=StringInStr($TEXT,'<'&$A[$COUNTER],0,1,$B)
   If $B=0 Then ExitLoop
   $E=StringInStr($TEXT,'>',0,1,$B)
   $TEXT1=StringLeft($TEXT,$B-1)
   $TEXT2=StringTrimLeft($TEXT,$E)
   $TEXT=$TEXT1&$TEXT2
  WEnd
 Next

; Очистка тэгов от ключей, кроме заданных

 For $COUNTER=0 To UBound($EXCLUDE)-1
  $B=1
  While True
   $B=StringInStr($TEXT,'<'&$EXCLUDE[$COUNTER][0]&' ',0,1,$B)
   If $B=0 Then ExitLoop
   $E=StringInStr($TEXT,'>',0,1,$B)
   $BB=$B+StringLen($EXCLUDE[$COUNTER][0])+2
   $TAG=StringMid($TEXT,$BB,$E-$BB)
   $TAG=StringReplace($TAG,@CRLF,'')

   Do
    $TAG=StringReplace($TAG,'  ',' ')
   Until @extended=0

   $A=StringSplit($TAG,' ')
   $AA=StringSplit($EXCLUDE[$COUNTER][1],'|')

   $TAG='<'&$EXCLUDE[$COUNTER][0]

   For $COUNTER2=1 To UBound($A)-1
    For $COUNTER3=1 To UBound($AA)-1
     If StringInStr($A[$COUNTER2],$AA[$COUNTER3])<>0 Then
      $TAG&=' '&$A[$COUNTER2]
     EndIf
    Next
   Next

   $TAG&='>'

   $TEXT1=StringLeft($TEXT,$B-1)
   $TEXT2=StringTrimLeft($TEXT,$E)
   $TEXT=$TEXT1&$TAG&$TEXT2

   $B+=1

  WEnd
 Next

 $OPEN=FileOpen(@ScriptDir&'\site1.htm',2)
 FileWrite($OPEN,$TEXT)
 FileClose($OPEN)

; КОНЕЦ
 
Верх