Diskuze: Rozpoznání v textu, url, videa, obrázku a vytvoření náhledu cizí stránky
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.


Nahledy si predstavujes jak, ze by to fungovalo. Php pracuje s php kodem,
generuje html, posila www prohlizeci uzivatele. Prohlizec generuje www stranku.
Takze to musis odeslat nejakemu programu, ktery ti dokaze poslat pak screen. Bud
mas takovy nainstalovany a pustis to pres cmd. Nebo mozna jde prohlizec na
serveru takto spustit pres cmd. Jenze na serveru prohlizec nemusi byt, k cemu,
ze?
A nebo mne napada moznost pouzit javascript a canvas, asi. Otevrit nove okno,
vykreslit, udelat screen a odeslat na server nebo do canvasu. Nebo to mozna
canvas nejak umi. Nevim, nikdy jsem to neresil.
Moc nechapu to spojeni reg. vyrazu. Proc to chces spojit? Poud to funguje,
tak je lepsi mit 3 vyrazy nez to spojovat do jednoho. Hlavne, pokazde pouzivas
jine modifikatory a jakysi hodne zjednoduseny tvar pro url.
Napad bych mel. Pouzit call back a jediny vyraz, ktery vybere url. V call-backu
se pak rozhodnes, co je to za url. Uplne by stacilo pres strpost najit youtube
nebo pres substring posledni znaky porovnat s priponami obrazku cyklem. Ale muze
to byt reg vyraz, to uz je fuk.
function replaceCb($matches) {return '123'.$matches[1];}
$patt = "~(http|https|ftp|ftps)(\S*)~";
$str = preg_replace_callback($patt, 'replaceCb', $str);
katrincsak:31.5.2018 11:06
Vše probíhá tak, že vytvoříš příspěvek, který se ajaxově odešle. Z důvodu některých omezení, kterým jsem se musel přizpůsobit, tak si html generuji v php a pošlu zpětně hotové html, které vložím javascriptem. Takže kontrola textu probíhá již na straně serveru tedy php, které provede úpravy v obsahu. S tím náhledem si nejsem jistý zda jsme se pochopili správně. Asi nepoužíváš FB že? Tam když vložíš jakýkoliv odkaz na web, tak se rovnou vytvoří náhled. Aktuálně není řešením zda se ukáže hned, nebo až po odeslání příspěvku. Jde pouze o ten samotný proces jak dojde k načtení těch dat, nebo aspoň tohle jsem se snažil popsat.
katrincsak:31.5.2018 11:11
Zapomněl jsem odepsat na další věci:
Sjednocovat to nepotřebuji, což by asi možná ani nešlo, nebo nevím jak daleko jsou schopný reg výrazy. Ale jde o to, že jakmile se mi převedou odkazy na a href, tak v tu chvíli to je již špatně pro ostatní regulární výrazy. Kdybych to uměl, tak si to asi přepíšu, ale musel bych se tomu teď věnovat delší dobu a hrát si s tím.
Na ten cllback se podívám co vše umí a zda by vytáhl všechny odkazy, které bych pak jen přepsat za pomocí např str_replace, tak bych si s tím poradil.
katrincsak:31.5.2018 11:43
Nechal jsem se inspirovat a použil jsem callback. lze ten regexp upravit, aby to vracelo jenom ty url ?
Udělal jsem:
$text = "Mám tento obrázek: http://www.skrabal-auto.cz/images/PNGPIX-COM-BMW-M2-Coupe-White-Car-PNG-Image.png také jsem si vložil video https://www.youtube.com/watch?v=25dswmOUmD0 a rád bych to vše odkázal na http://Seznam.cz a ideálně i s náhledem.";
function replaceCb($matches) {return ";".$matches[0];}
$patt = "~(http|https|ftp|ftps)(\S*)~";
$str = preg_replace_callback($patt, 'replaceCb', $text);
foreach(explode(";",$str) AS $url){
echo $url."<br>";
}
Výsledek
Mám tento obrázek:
http://www.skrabal-auto.cz/images/PNGPIX-COM-BMW-M2-Coupe-White-Car-PNG-Image.png také jsem si vložil video
https://www.youtube.com/watch?v=25dswmOUmD0 a rád bych to vše odkázal na
http://Seznam.cz a ideálně i s náhledem.
http://php.net/…n.syntax.php
https://www.regextester.com/pregsyntax.html
$patt = "~(http|https|ftp|ftps)(\S*)~";
\S = any character that is not a whitespace character
* = 0 or more quantifier
To ostatni je klasicky or http|https|ftp|ftps = http or https or ftp or ftps
$patt = "~(?:http|https|ftp|ftps)(?:\S*)~";
(?: = non-capturing subpattern
Proc si tam nedas var_dump($matches); ? Ten vyraz jsem se snazil jenom zjednodusit. Hledej cokoliv, co zacita http a pod a pokracuj, dokud nenarazis na mezeru nebo konec.
function replaceCb($matches) {return ";".$matches[0];} // to je normal funkce
function replaceCb($matches)
{
//echo "<br>".$matches[0];
echo '<pre>';
var_dump $matches;
echo '</pre>';
}
Ty delas to, ze tam vracis puvodni text a jen pridas strednik. Takze explodovani podle stredniku ti vygeneruje, co ti vygeneruje.
"123aaa456aaa789" -> najdi aaa, nahrad ';'+'aaa' -> "123;aaa456;aaa789" -> explode(;)
123
aaa456
aaa789
Tak, to se dalo ocekavat, ne?
Pozor. To me zjednoduseni neresi pripad, kdy je adresa ukoncena teckou.
\S = any character that is not a whitespace character
whitespace = space, formfeed, newline, carriage return, horizontal tab, and
vertical tab
' ' = space, klasicka mezera
\f formfeed (hex 0C)
\n newline (hex 0A)
\r carriage return (hex 0D)
\t tab (hex 09)
Pro zajimavost, v javascriptu pattern (hledany vzor) pro link vypada takhle. Uvazujes domenu jako ip adresu nebo text. Kdyz to cele nahradis jenom \S, tak je to fakt hooodne zjednodusene.
function filterLink()
{
var ip0 = "(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])"; //255-250 249-200 199-100 99-10 9-0
var ip = "(?:(?:"+ ip0 +"\\.){3}"+ ip0 +")";
var hostsep = "_\\.-";
var linksep = "#%&-;\\.\\/\\=\\?_~";
var xProtocol = "(?:(?:(?:file|ftp|ftps|gopher|http|https|news|nntp|sftp|telnet)\\:\\/\\/)|"+ ip +")";
var xDomain = "(?:(?:[A-Za-z0-9](?:(?:["+ hostsep +"]?[a-zA-Z0-9]*)*)\\.[a-zA-Z]{2,9})|"+ ip +"|localhost)";
var xPort = "(?:\\:[0-9]{2,4})?";
var reg_link = "\\[("+ xProtocol +"("+ xDomain +")"+ xPort +"(?:\\/)?(?:[A-Za-z0-9" + linksep +"])*)\\]"
//alert(new RegExp(reg_link,'g').test("[http://msdn.microsoft.com:80/scripting/default.htm]"));
//alert(new RegExp(reg_link,'g').test("[http://www.quantum-star.com]"));
/*link*/
return reg_link;
}
katrincsak:31.5.2018 13:37
Děkuji za rozepsání.
Výstup se dá samozřejmě očekávat, ale šlo mi o to že to nevrátilo jen
URL, ale i zbytek textu a jakmile to narazilo na další url, tak z toho
vytvořilo další záznam v poli a takhle až do konce řetězce. Právě že
by to chtělo vytvořit pole, ale jen s url a to v momentě kdy to dorazí na
konec a nejlépe i v momentě kdy to narazí na tečku. Je pravda, že z toho
výstupu není tak jednoduše zřejmé co jsem tím chtěl přesně ukázat, to
se omlouvám.
To poslední co posíláš jsem našel také, ale je pravda, že s tím potřebuji pracovat mnohem víc komplexně a to z důvodu výše vypsaných věcí, které potřebuji do toho všeho implementovat.
Rozhodně jsi mi dal myšlenku a i když jsem včera na callback narazil, tak jsem stále řešil problém zaujatě. Na konec díky tobě mě napadlo to vyřešit pomocí funkcí str* a aspoň si to vše můžu upravit přesně jak chci. Není to možná úplně nejlepší řešení, ale ten regexp v pozadí bude dělat stejně něco podobného. Takhle je to pro moje znalosti mnohem srozumitelnější a již to jen přepsat na trochu lepší konstrukci a do mého MVC. Následně s tím aspoň mohu pracovat a lépe delegovat. Nemůže se mi aspoň takto stát, že se mi přepíše znova ta samá věc. Chybí tam samozřejmě ještě čtení toho obsahu, ale ověřím si jaké jsou ještě možnosti, ale curl, nebo file_get_contents asi bude jediná možnost. Možná curl by mi mohl vytáhnout jen hlavičku, ale to se musím ještě podívat.
Moje hrubé řešení, které ještě zásadně upravím (testuji to jen jako samostatný script).
$text = "Mám tento obrázek: http://www.skrabal-auto.cz/images/PNGPIX-COM-BMW-M2-Coupe-White-Car-PNG-Image.png také jsem si vložil video https://www.youtube.com/watch?v=25dswmOUmD0 a rád bych to vše odkázal na http://Seznam.cz a ideálně i s náhledem.";
kontrolaUrl($text);
function kontrolaUrl($text){
preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $text, $match);
foreach($match[0] AS $url){
$relace = false;
$arrYTB = array(
"youtube.com/watch?v"
);
$arrIMG = array("jpg","jpeg","png","gif","bmp");
foreach($arrYTB AS $key=>$ytb){
if(strpos($url,$ytb)){
$relace = true;
$text = embed($url, $text);
break;
}
}
if($relace == false){
foreach($arrIMG AS $key=>$img){
$sufix = substr($img, -5);
if(strpos($url,".".$sufix)){
$relace = true;
$text = img($url, $text);
break;
}
}
if($relace == false){
$text = alink($url, $text);
}
}
}
var_dump($text);
}
function embed($url,$text){
parse_str(parse_url($url, PHP_URL_QUERY ),$get);
if(!empty($get['v'])){
$embed = '<iframe id="ytplayer" type="text/html" width="420" height="auto"
src="https://www.youtube.com/embed/'.$get['v'].'?autoplay=1&origin=http://vajeno.cz"
frameborder="0"></iframe>';
return str_replace($url, $embed, $text);
}else{
}
}
function img($url,$text){
$img = "<img src='".$url."' width='420' height='auto'>";
return str_replace($url, $img, $text);
}
function alink($url,$text){
$alink = "<a href='".$url."'>".$url."</a>";
return str_replace($url, $alink, $text);
}
Stale nechapu, proc to delas slozite Proc to komplikujes pres str_replace. Cykly navic. Proc to hned
nenahradis? Zkusils tam dat ten var_dump? Ne. Njn...
V tom calbacku mas primo tu url. Uvnitr si rozhodni, co vratis returnem, co tam
ma to replace dat.
function replaceCb($matches)
{
$url = matches[0];
if (strpos($url,'youtube')!==false) return htmlEmbed($url,'text')
if (strrpos($url,'jpg')===0) return htmlImage($url); //rpos je reverse, ale to je fuk, pouzi klidne dalsi replace na tu url, viz tvuj puvodni kod
}
$patt = "~(?:http|https|ftp|ftps)(?:\S*)~";
$str = preg_replace_callback($patt, 'replaceCb', $str);
Mozna to pochopis z tohoto:
$patt = 'aaa';
$str = preg_replace($patt, '<a href="$1">$1</a>', $str );
$str = preg_replace_callback($patt, 'replaceCb', $str);
function replaceCb($matches) {return '<a href="'.$matches[1].'">'.$matches[1].'</a>',];} // to dela uplne to same $matches[1], mozna $matches[0], z pameti nevim, musel bych testnout
// najde 'aaa' a nahradi ho za '<a href="aaa">aaa</a>',
Jinymi slovy, ty to pole vubec nepotrebujes.
+20 Zkušeností
+2,50 Kč

katrincsak:31.5.2018 18:32
Zkoušel jsem var_dump, ale nějak nevím co by mi zásadního udělalo krom toho, že mi vypíše pole/objekt. A také uvedený příklad chápu, je to sice jednodušší, ale nejsem si jistý zda-li v praxi je to skutečně použitelné.
Jenže tenhle tvůj příklad si zkus spojit a udělat to vše v rámci jednoho textu. Ve kterém budeš mít embed video, obrázek a ještě potřebuješ udělat hypertext. Bez ohledu na pořadí, jakmile to najde http/https, tak k tomu přidá tagy + potřebuji dotáhnout data z webu, další dotaz provádí kontrolu zda je to youtube video. Hlavně potřebuješ vědět co chceš převádět na co, respektive nelze převést každý url na hypertext a href, protože je nutné ten samý odkaz použít např u obrázku a nebo v embed.
Praxe:
URL převedeš na hypertext a href, ten samý odkaz je ale obrázkem a nebo youtube a buď se stane append, nebo prepend v tu chvíli máš v sobě tagy a to je to co je nežádoucí, protože to následně nemůže fungovat.
Proto je potřeba konkrétní odkaz kontrolovaně převést jenom jednou a toho nelze docílit, aby to bylo takhle jednoduché. Na víc jsem psal, že těch embed může být více a tak to pole mi na konec připadá v pořádku. A ten preg_replace_callback dělá následně to samé, prochází jedno pole za druhém a volá volanou funkci. Možná bych dokonce řekl, že toho musí dělat více a funkce se stává náročnější, ale použít by se dala.
Samozřejmě si rád nechám poradit, ale tohle neřeší veškeré věci. Pravda je, že mě napadá ještě jedna věc pro výsledné zobrazení a možná řeším věc, kterou na konec nevyužiji. Protože si uvědomuji, že když tam vložím 2 odkazy na obrázek, jedno video a odkaz na web, tak nebudu vše zobrazovat na jednou. Vyberu pouze první odkaz a ten detekuji co je zač, podle toho vytvořím náhled a zbytek se stane hypertextovým odkazem.
Koukal jsem jak načítat náhled cizího webu, ale jinak než jak jsem psal to asi skutečně nepůjde. Ale za pomocí xpath a file_get_contents je to proces na 3 řádky, jen budu muset ještě detekovat zda cesta k obrázku je absolutní a nebo relativní a zda to začíná lomítkem a nikoliv.
Každopádně moc děkuji za snahu, určitě si mi otevřel oči a donutil mě nad tím přemýšlet trochu jinak.
U ciziho webu musis sledovat take tagy base. S cestou by to bylo mnohem slozitejsi, tam se muzou vyskytovat vylomeniny jako ./ ../ nebo /
katrincsak:1.6.2018 8:01
To máš asi pravdu, ten může tak docela měnit relativní cestu, která se pro mě musí stát absolutní a byla by tedy chybná. A já to na svém webu do konce používám také. Děkuji za připomínku.
Za tvou ochotu ti dám řešení i když tomu tak není na 100% protože by problém jak jsem psal výše nevyřešil, ale dle konečné úvahy na zobrazení prvního odkazu a převedení zbytku se dá již použít.
Zobrazeno 12 zpráv z 12.