Interní prolinkování (nahrazení slova odkazem) – PHP – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Interní prolinkování (nahrazení slova odkazem) – PHP – Fórum – Programujte.comInterní prolinkování (nahrazení slova odkazem) – PHP – Fórum – Programujte.com

 

Hledá se programátor! Plat 1 800 € + bonusy (firma Boxmol.com)
Josef
~ Anonymní uživatel
24 příspěvků
8. 2. 2016   #1
-
0
-

Zdravím,

potřeboval bych poradit s regulárním výrazem.

určitá slova v textu (HTML text) bych potřeboval nahradit odkazem. To samo o sobě není problém, chyba nastává, když je nahrazované slovo uvnitř atributu (napr. alt obrázku). Pak se odkaz vložít do altu a to by neměl. Stejně tak odkaz nesmí nahradit slo, která již v odkazu je. Tedy vyloučit i slova, která se nacházejí v tagu "a", ale nevyloučit slova, která jsou v např. v tagu "strong". Nyní se používá:

$patterns[]     = '/([^\"!\/!])('.$r->word.')([$\s\.\<])/i';
$replacements[]  = '$1<a href="' . $r->anchor . '" title="' . $r->title . '">$2</a>$3';

Je to trochu zbastlený. Hlavně to nevyločí slova, která se nachází uvnitř atributu a jsou z obou stran krytá dalším textem.

Doufám, že je to srozumitelné a díky za pomoc.

Nahlásit jako SPAM
IP: 85.119.89.–
Reklama
Reklama
Kit+11
Guru
8. 2. 2016   #2
-
0
-

#1 Josef
Pokud takhle potřebuješ zpracovat HTML, tak si ho nejprve rozparsuj na elementy. Obsah těch elementů teprve prožeň tím regulárním výrazem a pak z toho znovu nechej vygenerovat HTML.

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
peter
~ Anonymní uživatel
2528 příspěvků
8. 2. 2016   #3
-
0
-

Jestli s tim ma nekdo pracovat, musis dat cely example. zdrojovy text, vyrazy, funkce, vystup, jak vypada, jak by vypadat mel. Proste, spustitelna forma.
Ano, slo by to, vyraz by byl slozitejsi a mozna pouzit callback funkci. Proc to nedelas v html/js

Nahodny vyber z googlu
preg_replace('/<span class="it">(.*?)<\/span>/', '{it}$1{/it}', $text)
http://www.joellipman.com/…wo-tags.html

Vyraz bych videl asi nejak takto (plus minus lomitka a tak, mozna i jima se zapisuje $2 a replacovani)
(<(\w+).*?>)(.*?)(</$2.*?>), $1.replace($3).$4
Cili, tak je tvoreny pismeny \w, minimalne 1 az nekonecno po prvni nepismenovy znak \w+.
Ta $2 by mela predstavovat druhou zavorku, cili to \w+, stejny tag. no, Ale proglem, kdyz das dva stejne tagy do sebe <a><b></b></a>. A  dal to selze, kdyz bude vic tagu v sobe.

Ja bych udelal to, co napsal kit. Pouzil bych parsovani na tagy a pak nahradil text. Mozna pujde pouzit primo simplexmlparser. Nebo to provedl v javascriptu, ktery umi pristupovat k tagum jako elementum (childnodes). Tam bys parser nepotreboval a taky by se tim nezatezoval server.

Nahlásit jako SPAM
IP: 2001:718:2601:26c:d16e:54...–
Kit+11
Guru
8. 2. 2016   #4
-
0
-

#3 peter
Výhodou toho parsování je, že v případě uživatelského vstupu si povolím jen ty značky a ty atributy, které povolit chci. Ostatní jdou nemilosrdně pryč a zůstane po nich jen textový obsah. Navíc ten výstup bude i validní. Parsování HTML je v PHP na dva řádky a slepení na jeden.

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Josef
~ Anonymní uživatel
24 příspěvků
8. 2. 2016   #5
-
0
-

#3 peter

Připravil jsem k tomu malý test, zdroj zde:

<!DOCTYPE html>
<html>
    <head>	          
        <title>Řezací plotr | UV STAR</title>	          
        <meta charset="UTF-8" />
    </head>
    <body>
<?php
$links =  array((object) array('word' => 'materiály', 'anchor' => '/produkty/' , 'title' => 'title'));
$html = '<p>materiály <a href="asdf" title="materiály"> asdf materiály asdf</a> asdf asdf materiály asd <strong>materiály</strong> <img alt="asdf materiály asdf " src="/www/images/zoomovatko.jpg" height="30" /></p>';

echo 'Originalni text';
echo $html;

$patterns = array();
$replacements = array();        
       
foreach ($links AS $link) {
     
   $patterns[]     = '/([^\"!\/!])('.$link->word.')([$\s\.\<])/i';
   $replacements[]  = '$1<a href="' . $link->anchor . '" title="' . $link->title . '">$2</a>$3';

} 
         
echo 'Novy text';            
echo preg_replace($patterns, $replacements, $html);

echo 'Takhle by mel vypadat';            
echo '<p><a href="/produkty/" title="title">materiály</a> <a href="asdf" title="materiály"> asdf materiály asdf</a> asdf asdf <a href="/produkty/" title="title">materiály</a> asd <strong><a href="/produkty/" title="title">materiály</a></strong> <img alt="asdf materiály asdf " src="/www/images/zoomovatko.jpg" height="30" /></p>';

?>
</body>
</html>

Výsledný produkt:

http://www.uvstar.cz/test.php

Spatne je:

  • udela odkaz v odkaze
  • prepise obrazek

Pomocí JS to přepisovat nechci, je to hlavně pro vyhledávacě...

Nahlásit jako SPAM
IP: 85.119.89.–
Kit+11
Guru
8. 2. 2016   #6
-
0
-

#5 Josef
Mohu vědět, jak vznikl původní text? To je z nějakého cizího webu?

Jinak už to skoro mám, ale čím dál víc pochybuji o smyslu takového počínání.

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Josef
~ Anonymní uživatel
24 příspěvků
8. 2. 2016   #7
-
0
-

#6 Kit
Text je samozrejme pouze testovaci a je napsan tak, aby otestoval script.

V reálu bude script upravovat obsah článků - do DB se bude generovat seznam slov, ty pak tento  script v clanku pretvori za odkazy na jine clanky.

Diky za pomoc, snad se zadari.

Nahlásit jako SPAM
IP: 85.119.89.–
peter
~ Anonymní uživatel
2528 příspěvků
9. 2. 2016   #8
-
0
-

To uplne nesnasim, kdyz jsou v clanku zamichane odkazy a do toho jeste fake-odkazy na jine clanky jen proto, ze se shoduje slovo.
Seznam slov se da ziskat snadno, pres striptags, tusim. Pripadne jednoduchym reg. vyrazem na odstraneni tagu. S im nahrazenim je to pak horsi, no.

No, mozna, zcela omezene, by se dali pouzit i vyrazy. Nahradil bych vse nezadouci za nejakou svou zkratku a pak tam dosadil zpet

<!DOCTYPE html>
<html>
    <head>	          
        <title>Řezací plotr | UV STAR</title>	          
        <meta charset="win-1250" />
    </head>
    <body>
<?php
@ini_set('error_reporting', E_ALL);
@ini_set("display_errors", "1");
error_reporting(E_ALL);

$html = '<p>materiály <a href="asdf" title="materiály"> asdf materiály asdf</a> asdf asdf materiály asd <strong>materiály</strong> <img alt="asdf materiály asdf " src="/www/images/zoomovatko.jpg" height="30" /></p>';

echo 'Originalni text';
echo '<hr>'.$html;
echo '<hr>'.htmlspecialchars($html); // proc mi to nefunguje?

$patterns = array();
$replacements = array();        
       
$links =  array((object) array('word' => 'materiály', 'anchor' => '/produkty/' , 'title' => 'title'));
foreach ($links AS $link) {
     
//   $patterns[]     = '/([^\"!\/!])('.$link->word.')([$\s\.\<])/i';
   $patterns[]     = '/([^\"!\/!])('.$link->word.')([$\s\.\<])/i';
/* preg_replace('~(<.*?>)(.*)?<~', '$1 <a href="$2">$2</a> <') */
   $replacements[]  = '$1<a href="' . $link->anchor . '" title="' . $link->title . '">$2</a>$3';

} 
         
echo 'Novy text';            
$new = $html;
$list = array();
$new = preg_replace_callback(
        	'~(\<(a) .*?(\>).*\<\/\2?\>)|(\<(img) .*?\>)~i',
        	function ($matches) {
			global $list;
			$list[] = $matches[0];
			return '#'.(count($list)-1);
		        },
		$new);
var_dump($list);
echo '<hr>'.$new;
$new = preg_replace($patterns, $replacements, $new);
$new = preg_replace_callback(
        	'~\#(\d+)~',
        	function ($matches) {
			global $list;
			$list[] = $matches[0];
			return $list[$matches[1]*1];
		        },
		$new);
echo '<hr>'.$new;

//echo preg_replace($patterns, $replacements, $html);

echo 'Takhle by mel vypadat';            
echo '<p><a href="/produkty/" title="title">materiály</a> <a href="asdf" title="materiály"> asdf materiály asdf</a> asdf asdf <a href="/produkty/" title="title">materiály</a> asd <strong><a href="/produkty/" title="title">materiály</a></strong> <img alt="asdf materiály asdf " src="/www/images/zoomovatko.jpg" height="30" /></p>';

/*
$doc = DOMDocument::loadHTML($string);
$xpath = new DOMXPath($doc);

$query = "//body/text()";
$nodes = $xpath->query($query);

$text = "";
foreach($nodes as $node) {
    $text .= $node->wholeText;
}    
*/

?>
</body>
</html>
Nahlásit jako SPAM
IP: 2001:718:2601:26c:79ca:ee...–
peter
~ Anonymní uživatel
2528 příspěvků
9. 2. 2016   #9
-
0
-

V tom druhem callback je samozrejme nesmysl radek
$list[] = $matches[0];
Jako, on neskodi, viditelne, ale... Chyba kopirovani :)
 

Nahlásit jako SPAM
IP: 2001:718:2601:26c:79ca:ee...–
peter
~ Anonymní uživatel
2528 příspěvků
9. 2. 2016   #10
-
0
-

A taky ten vyraz muze byt jiny.
'~(\<(a)\W.*?\>).*?\<\/\2?\>)|(\<(img) .*?\>)~i', // a+ne_pismeno+cokoliv
'~(\<(\w+).*?\>).*?\<\/\2?\>)|(\<(\w+).*?\>)~i', // pismeno_opakovani+cokoliv - to by melo resit jakekoliv tagy, nejdriv se pokusi najit pary. Jenze, opet to selze na zanorenem tagu, treba <b>text<i>text</i>text</b>, cele to odstrani do $list
 

Nahlásit jako SPAM
IP: 2001:718:2601:26c:79ca:ee...–
peter
~ Anonymní uživatel
2528 příspěvků
9. 2. 2016   #11
-
0
-

jeste bych to zmenil
'~(\<(\w+)(\W.*)*?\>).*?\<\/\2?\>)|(\<(\w+)(\W.*)*?\>)~i',

\w+.* je totez pro deleni abcd na abcd (spolu nebo) ab cd (jakkoliv zvlast), takze tam musi byt za textem netextovy znak a ten tam muze ci nemusi byt

(\w+)(\W.*)*
\w+ = pismena jmena tagu pripadne tam muzes dat [\w\d]+ necisla, nepismena
\W = nepismenovy znak
.* = jakykoliv znak v poctu 0-nekonecno
(\W.*)* = vyskyt retezce, ktery zacina nepismenkovym znakem (popsano vys, dva radky) a opakuje se 0-nekonecno
\> = znak ukonceni tagu ">"
?\> = hledej, dokud nenarazis na retezec ">" (ukonceni tagu), kdybys tam otaznik nedal, tak .* pred tim je jakykoliv  znak a tam patri i ukonceni tagu ">"

Ps. Vsechny ty vyrazy mimo php kod jsou netestovane. Pouze tipuji, jak by to mohlo vypadat. Doladis sam.

Nahlásit jako SPAM
IP: 2001:718:2601:26c:79ca:ee...–
Josef
~ Anonymní uživatel
24 příspěvků
10. 2. 2016   #12
-
0
-

#11 peter

Je to OK, takhle mi to bude stacit. 

Moc dik za pomoc!

Nahlásit jako SPAM
IP: 85.119.89.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 74 hostů

Podobná vlákna

Problem s odkazem — založil Hlavinka

Problém s odkazem — založil wise

Interní forum — založil MaxDJs

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý