Autor | Zpráva | ||
---|---|---|---|
honky tonk Profil * |
#1 · Zasláno: 14. 12. 2013, 15:19:06
Potřeboval bych nějak zkrátit řetězec $string o 1411 řádků které obsahují html kód . Jak to co nejefektivnějji udělat?
|
||
Alphard Profil |
#2 · Zasláno: 14. 12. 2013, 15:52:31
Ten popis je dost vágní. Jesti znáte-li např. pozice hranic, lze použít substr(), substr_replace() atd. Záleží na situaci.
|
||
Micruss Profil |
šlo by to takto ::::
<?php $string = "1411 řádků a více..."; $w = explode("\n", $string); $w = explode($w[1410], $string); $string = $w[0]; # text před 1411 echo $string; |
||
Alphard Profil |
#4 · Zasláno: 14. 12. 2013, 16:10:47
Micruss [#3]:
Méně optimální cesta vás nenapadla? :-) Vytváříte mnohatisiciprvkové pole jen abyste nakonec znovu v textu hledal jakýsi řetezec, o kterém docela naivně věříte, že je unikátní? Neberte to špatně, jen chci poukázat na značné nedostatky toho algoritmu. |
||
honky tonk Profil * |
#5 · Zasláno: 14. 12. 2013, 17:19:25
Alphard:
pozice hranice neznám. nenapadá mě nic jiného než to řešit ručně pomocí smyčky for. Budu tedy načtený sdrojový text procházet po jedné a počítat výskyt \r\n Micruss právě explode jsem se chtěl vyhnout. |
||
Tori Profil |
honky tonk:
Chcete odmazat 1411 řádků od začátku nebo od konce? |
||
honky tonk Profil * |
#7 · Zasláno: 14. 12. 2013, 19:21:17
Tori:
Od začátku. Co tak to stáhnout od pozice 1441 to by snad šlo ne? $handle = fopen("http://www.example.com/", "rb"); $contents = ''; fseek($handle,1141) while (!feof($handle)) { $contents .= fread($handle, 8192); } fclose($handle); Nevíte náhodou proč mi nejde vrátit velikost souboru? Snažím se načíst soubor, který je otevřený, ale filesize pořád vrací 0. Ale soubor existuje - cesta folder/temp.html $fh=fopen($file,"r"); die(filesize($file).""); $html=fread($fh, filesize($file) ); |
||
Tori Profil |
#8 · Zasláno: 14. 12. 2013, 19:32:12
IMHO pokud neznáte přesný offset, tak tím cca jedním kilobajtem při stahování nic neušetříte. Když se kouknete do zdrojáku toho stahovaného souboru, podle čeho poznáte, kde končí těch x řádků? Dalo by se vyhledat nějakou část HTML kódu, konec prvku s určitým ID apod.
|
||
Alphard Profil |
honky tonk:
Konečně popis problému, se kterým se dá pracovat. Původní dotaz byl k ničemu. Pořád by to ale šlo vylepšit, viz [#8] Tori. Ke kódu [#7]. fseek() vůbec neřeší řádky, bere bajty. Zkuste využít fgets(). $i = 0; while (($s = fgets($handle)) !== false) { if ($i++ > 1141) { $string .= $s; // jestli je soubor hodně dlouhý, šlo by tady hned zapisovat do jiného souboru } } |
||
honky tonk Profil * |
#10 · Zasláno: 14. 12. 2013, 19:41:12 · Upravil/a: honky tonk
Myslel jsem že bych tím že to oseknu zkrátil proces vyhledávání (v tomto smyslu bych něco ušetřil, ale ne bajtů). Tak pomocí regulárního výrazu bych to zvládl taky, ale teď potřebuju vyřešit ten filesize protože bez toho se nehnu abych to dořešil. Nejde mi otevřít stažený soubor.
Už to mám otevřené. Vyřešil jsem to takto preg_match_all("@\.\w\w\w\w{display:inline}@", $data, $matches, PREG_OFFSET_CAPTURE); print_r($matches); Výsledek: http://paste.ofcode.org/mCx9GXyCTWxKpLHdNPFk9C Nebo vlastně takto: preg_match_all("@(?<=\.)\w\w\w\w(?={display:inline})@", $data, $matches, PREG_OFFSET_CAPTURE); |
||
Micruss Profil |
#11 · Zasláno: 14. 12. 2013, 21:20:07
No abych pravdu řekl, tak mě vytvoření tisicového pole vůbec nenapadlo v té době, psal jsem to jako první nápad... ;) příště by to chtělo se nd tím více zmyslet ;)
|
||
honky tonk Profil * |
#12 · Zasláno: 14. 12. 2013, 22:01:58
Ještě se s vámi podělím o komplikace. Tak nejdříve jsem si uvědomil, že těch stylů, které hledám může být v daném bloku více. Blokem myslím určitý úsek od prvního výskytu daného stylu. Ten úsek se pohybuje zhruba mezi 1000 a 1452 znaky. Takže nejdříve jsem potřeboval spočítat styly. Napsal jsem teda tuto funkci:
http://paste.ofcode.org/GLqDYy6ZHjekM6UJbsD3RR Výsledky pak zpracovávám takto: foreach ($originalMatches[0] as $arr): $i++; $boundStylesCount = testRepeat($originalMatches,$i,$minBlockLength,23); čímž zpočítám kolik stylů daného typu se vyskytuje v tom bloku. Jednotlivé bloky totiž spolu nesouvisí. Pak ale může vzniknout další situace: od pozice prvního výskytu hledám pomocí preg_match zase ten styl, ale protože jsou ty styly 3 tak musím použít smyčku: for ($c=0; $c<$boundStylesCount; $c++){ // anchor: styles found in this block: preg_match("@(?<=class=\"".$originalMatches[0][$c]."\">)\d{1,3}(?=<)@", $data, $matches, PREG_OFFSET_CAPTURE, $begin); if ( isset($matches[0][1]) ) { $diff=$matches[0][1]-$begin; if ( $diff<$maxBlockLength ) $results[$diff]=$matches[0][1]; } }// END for |
||
Tori Profil |
honky tonk:
„Tak nejdříve jsem si uvědomil, že těch stylů, které hledám může být v daném bloku více. Blokem myslím určitý úsek od prvního výskytu daného stylu. Ten úsek se pohybuje zhruba mezi 1000 a 1452 znaky.“ Ještě jednou: Podle čeho poznáte, že tento styl hledáte? |
||
honky tonk Profil * |
#14 · Zasláno: 14. 12. 2013, 22:34:30
Tori:
Poznám to během parsování výsledků. Spočítám si kolik stylů leží ve stejném bloku, která má určitou délku. To je to: $boundStylesCount = testRepeat($originalMatches,$i,$minBlockLength,23); |
||
Alphard Profil |
#15 · Zasláno: 14. 12. 2013, 23:16:26
Kdybyste ukázal vstup a řekl, co z něj potřebujete, mohl byste si ušetřit ty monology. Přečtěte si svůj popis a zapomeňte vše, co nebylo uvedeno. Poradil byste sám sobě?
|
||
honky tonk Profil * |
#16 · Zasláno: 14. 12. 2013, 23:43:12
Alphard:
Tak já jsem na všechna řešení nakonec přišel sám. Částečně díky vyhledávači. |
||
honky tonk Profil * |
#17 · Zasláno: 16. 12. 2013, 00:55:04
Napadá vás proč tento příkaz nefunguje?
preg_match_all("@class=\"\d{1,3}\">\d{1,3}(?=<)@", $block, $matches, PREG_OFFSET_CAPTURE, 0); for($c=0; $i<count($matches[0]); $c++) $matches[0][$c][0] = preg_replace("@class=\"\d{1,3}\">@", "", $matches[0][$c][0]); print_r($matches); Snažím se odstranit class="???"> z pole výsledků: http://paste.ofcode.org/JEDBnEvvjQeQ2cYaVYCBbW |
||
Tori Profil |
#18 · Zasláno: 16. 12. 2013, 10:03:10
A co ta proměnná
$i , nevzniká vám nekonečná smyčka náhodou?
|
||
honky tonk Profil * |
#19 · Zasláno: 16. 12. 2013, 10:17:37 · Upravil/a: honky tonk
Tori:
Na tom něco bude. Teď sice smyčka nevzniká, ale i tam určitě být nemá. Když tam dám c tak tam mám smyčku. edit: ještě to musím prozkoumat. Vypadá to že těch výsledků $matches[0] je hodně |
||
honky tonk Profil * |
#20 · Zasláno: 16. 12. 2013, 11:39:15
Tori:
Ta poznámka že se to mohlo zacyklovat byla hodně dobrá. Tohle si musím zapamatovat, že smyčky tohoto druhu, které používají count je třeba pojistit proti zacyklení: if (count($matches[0])) // ochrana proti zacyklení ! ! ! for( $c=0; $c<count($matches[0]); $c++): $matches[0][$c][0] = preg_replace("@class=\"\d{1,3}\">@", "", $matches[0][$c][0]); endfor; |
||
1Pupik1989 Profil |
#21 · Zasláno: 16. 12. 2013, 11:54:00
count vrátí 0 pokud je pole prázdné. Tudíž cyklus neproběhne. Spíš bych ověřoval jestli to je pole když už. Počet prvků bych si dal zvlášť do proměnné, nemá cenu při každé iteraci zjišťovat počet prvků v poli.
|
||
Tori Profil |
#22 · Zasláno: 16. 12. 2013, 11:57:20 · Upravil/a: Tori
honky tonk:
Do té podmínky hoďte celý preg_match_all - když nic nenajde, vrací FALSE; když najde, tak vrací počet nalezených shod - takže nepotřebujete ani count($matches[0]). A vlastně, kdybyste ten regulár upravil na: preg_match_all("@class=\"\d{1,3}\">(\d{1,3})(?=<)@", $block, $matches, PREG_OFFSET_CAPTURE, 0); , tak pak máte všechna nalezená čísla v $matches[1] a nemusíte z nich nic odmazávat.
|
||
honky tonk Profil * |
#23 · Zasláno: 16. 12. 2013, 12:15:28
Tori:
Nevím co by to udělalo s tou stávající strukturou: http://paste.ofcode.org/JEDBnEvvjQeQ2cYaVYCBbW |
||
Tori Profil |
#24 · Zasláno: 16. 12. 2013, 12:31:57
honky tonk:
Tak pak se to dá ještě přepsat takhle: preg_match_all('@(?<=class="\d">|class="\d\d">|class="\d\d\d">)\d{1,3}(?=<)@', $block, $matches, PREG_OFFSET_CAPTURE, 0); |
||
honky tonk Profil * |
#25 · Zasláno: 16. 12. 2013, 12:37:41
Tori:
A nenapadá tě k tomuto: preg_match_all("@(?<=style=\"display: inline\">)\d{1,3}(?=<)@", $block, $matches, PREG_OFFSET_CAPTURE, 0); Proč mi to v kódu <span style="display: inline">201</span> |
||
Tori Profil |
#26 · Zasláno: 16. 12. 2013, 12:43:29
Mně to funguje.
|
||
honky tonk Profil * |
#27 · Zasláno: 16. 12. 2013, 13:25:23 · Upravil/a: honky tonk
Tori:
A tenhle? preg_match_all("@(?<=>)\d{1,3}(?=\.?)(?=<[^/])@", $block, $matches, PREG_OFFSET_CAPTURE, 0); Měl by vyhledat číslo 176, mezi číslem a < se může vyskytnout tečka... hledané číslo 176 v bloku: .</span>176.<span Testuju to tady a vrací mi to prázdné pole: http://www.functions-online.com/preg_match.html Tak tenhle regular jsem si už opravil "@(?<=>)\d{1,3}(?=\.?<[^/])@" Další problém mám s tímto: @(?<=style=\"display: inline\">)\d{1,3}(?=\.?<)@ <span style="display: inline">113</span><span class="qazL">.</span><span style="display: inline">111</span vrací array ( 0 => array ( 0 => '113', 1 => 30, ), ) Ale měl by vrátit 113 a 111 . Proč nevrací 111? |
||
honky tonk Profil * |
#28 · Zasláno: 16. 12. 2013, 17:46:33
Vyřešeno.
|
||
honky tonk Profil * |
#29 · Zasláno: 18. 12. 2013, 09:57:36 · Upravil/a: honky tonk
Dotaz
jak vyhledat čas psaný slovy který je mezi řádky (začíná na novém řádku, ale je předcházen >. ? > 10 hours and 52 minutes</span></td> preg_match("@(?<=>)(?s)\.{1,150}[\w ]{1,30}(?=</span></td>)@", $data, $checkMatchArr, PREG_OFFSET_CAPTURE, 0); Zkoušel jsem výraz i bez té první části která hledá ten přechod na nový řádek a ani to moc effektivně nefuguje protože mi to našlo jen 2 minutes. preg_match("@(?<=class=\"updatets \">)\n{1,250}[\w ]{1,30}(?=</span></td>)@", $data, $matches); Toto mi funguje ale vrací pouze 2 minutes. Když to testuju na té testovací stránce tak to vrací komplet: array ( 0 => ' 10 hours and 52 minutes', ) Nevíte proč to nevrací celou délku? |
||
honky tonk Profil * |
#30 · Zasláno: 18. 12. 2013, 11:15:44
Hej, tak jsem to vyřešil. Zjistil jsem že ty data se načítají z jiného souboru, než jsem měl načtený v prohlížeči ...
|
||
Časová prodleva: 10 let
|
0