Ahoj,
používáte někdo nějaké funkční API na ČSFD? Poslední dobou se mi stalo, že mi nefunguje žádný možný přístup, ani přes simple dom html parser. Jsem jediný nebo chyba někde jinde?
Díky
#1 maniakum
Na ČSFD se svým parserem nechodím (zkusit to můžu, ale zatím jsem to nepotřeboval), ale nevidím v tom problém. V PHP na to používám třídu DomDocument, která parsování HTML zvládá docela dobře. Ty ostatní (včetně SimpleXML apod.) měly vždy nějaké mouchy, kvůli kterým jsem je přestal používat.
#2 Kit
Ok. Tak jsem zkusil napsat tohle pro vytažení názvu filmu.
<?php
$dom = new domDocument;
$dom->loadHTMLfile('http://www.csfd.cz/film/32');
$dom->preserveWhiteSpace = false;
$tables = $dom->getElementsByTagName('h1');
while($table = $tables->item($i++))
{
echo $table->nodeValue;
}
?>
Funguje, ale napříklád jednou za 5 opakování se mi nic nenačte, čím to?
EDIT: respektive jsem ještě přišel třeba na to, že pod id 349573 to nic nezobrazí. To jako proč?
#3 maniakum
Jak kdyby se CSFD bránila a posílala tam náhodný bordel a občas se povede načíst stránka v pořádku
‹ í}K“Ç•îZúix¤nZ( Ux7‰fMÒ¤$R4›¢l‰ŠŽ*T£PÕM´ÅˆYÎbôÚ˜O„/æÆ]8B^¸É?rÉýNfÖÐÝäXŽ‘-5*둯“'Ïã;'?¼ñ«;_ŽöøËÛŸ?8`\þªzP.ßyz‡ýþþÓ‡ŸòäÎ=“é¥J¹|÷Q†a8Ù+—ONNJ'Õ’çÊMôå„Þ(¿ oi¾Õ75½d…VaÿÃâó/ÆŽt–¼¬·ÛmùZÚsLwÐ)ôqå{®T•Þ„»ßœ'¾z=ϵ½!›åøù~7yÞâSîà%?(õÍïzÞ¨ÔóÆÉÔ6nZû~pcÌCãN4þ]dO;…Ï ¹jOg^`=yÕ)„üEX¦Æ^g½¡éاÞÐ COÞ{ûÊOì³ÿvM6eá›ßþ}tö›ž½:åìÖÄs“øœ[f‘BîŸýÌNùøퟸÎùÛWxMpeá sMß;åîÙëq‰=FqzlŠF¨òí_ñè_§ž…öšô3Y×{ÁÆg¯P÷ÈŸÚEš£·çß«AxöÊá(â Ëc‡¶cZÜ™môbüæÇ ¤fYœœyúxþÿýûÍ݈ÏN$£Þ£>™øƒÇ?ÄX‡vèð}ÑY¶kTôú5ö={óŸ‡÷î”z§7Êò6=èØîˆùÜ邡燽(d6>\`CŸ÷R±ÇƒR/è[x¹l˜Ö ÜÕÍfÙ›”ûæ”Þ*á?‚&:q§üB_£éOk2'‡k¡õ†òöv•‰×ÄëG¢Ö‰;ÝÎu'œ9rÎ}Þž7p¸9±AòTVvìnP>þ.âþ,²Ëz©UÒkå«ìšW÷´ÈÆX`üe?ÉÓu¾ÁªêWåس"´¸|»eù¶ú#k+¯þþ\C6MUÇÄ·ÝPV1æ–mv ¢„ã)—)ü^§PVS_2-¯Ëp,†®ÖåfϬוšiêV·i6¶Ñn˜•–Õªv9¯¶[¼Ù·ÊrDZCþ¹ÝÕºõZϨY=½ß5jfC¯õõV¯Ë£i4¬Z·Òh7 K¯—Ž1°7À’¨‚`U‹2}>6§¦,ÅšP\§ ÙŽl¸â›L
#3 maniakum
Na serveru je nejspíš nějaká jednoduchá ochrana proti harvestingu.
Také ten PHP klient může padnout na timeout při tom dvojitém přesměrování, které je na začátku.
#7 Maniakum
Mně to už funguje. Jsou to data komprimovaná gzipem. Stačí je dekomprimovat.
Jinak ten string, který jsi sem poslal, tomu neodpovídá. Někde sis asi vydoloval náhodná data, protože z ČSFD to sice také vypadá jako rozsypaný čaj, ale na rozdíl od toho tvého to má platnou signaturu a dá se to dekódovat.
#10 maniakum
Prostě tam podmíněně přidám rozbalení toho gzipu.
<?php
$csfd = file_get_contents("http://www.csfd.cz/film/32");
$html = (ord($csfd[0]) == 31) ? gzdecode($csfd) : $csfd;
@$dom->loadHTML($html);
#13 maniakum
To víš, nějakou dobu už s PHP dělám, umím už dělat prototypy i testy. To je pak vcelku jednoduché na takové chyby přijít.
Také vím, že existuje dokumentace PHP, ve které je vysvětlena i funkce ord().
Opravdový programátor totiž zná nebo nezná jméno své ženy, ale zcela jistě zná tabulku ASCII a ví, že znak s ordinální hodnotou 31 není tisknutelný a začne pátrat po tom, co to číslo 31 znamená.
Kdyby to někoho zajímalo, tak jsem to nakonec udělal takto. Určitě by to šlo udělat lépe, budu rád za každý komentář. Žádný zázrak to není, ale funguje to.
$dom = new domDocument;
$csfd = file_get_contents("http://www.csfd.cz/film/$csfd_id");
$html = (ord($csfd[0]) == 31) ? gzdecode($csfd) : $csfd;
@$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;
$names = $dom->getElementsByTagName('title'); //zjištění CZ a druhého názvu filmu
$i=0;
while($names_2 = $names->item($i++))
{
$name = $names_2->nodeValue;
if ($name_obsahuje = strpos($name, "/") === false) {
$names_3 = explode(" | ", $name);
$names_4 = explode(" ( ", $names_3);
$names_cs = $names_4[0];
$names_en = $names_cs;
} else {
$names_3 = explode(" / ", $name);
$names_4 = explode(" (", $names_3[1]);
$names_cs = $names_3[0];
$names_en = $names_4[0];
}
}
$entries = $dom->getElementsByTagName('h2'); //hodnocení
for ($i=0;$i<$entries->length;$i++) {
$entry = $entries->item($i);
$average = $entry->attributes->getNamedItem('class')->value;
if($average=="average")
$hodnoceni = str_replace('%', '', $entry->nodeValue);
}
$entries = $dom->getElementsByTagName('p'); //rok, žánr, země, délka filmu
for ($i=0;$i<$entries->length;$i++) {
$entry = $entries->item($i);
$p = $entry->attributes->getNamedItem('class')->value;
if($p == "origin")
$podrobnosti = explode(", ",$entry->nodeValue);
elseif($p == "genre")
$genre = str_replace(' / ', '@;@', $entry->nodeValue);
}
$entries = $dom->getElementsByTagName('span'); //herci
for ($i=0;$i<$entries->length;$i++) {
$entry = $entries->item($i);
$p = $entry->attributes->getNamedItem('data-truncate')->value;
if($p == 340)
$hraji = $entry->nodeValue;
}
$entries = $dom->getElementsByTagName('div'); //popis
for ($i=0;$i<$entries->length;$i++) {
$entry = $entries->item($i);
$p = $entry->attributes->getNamedItem('data-truncate')->value;
if($p == 570)
$popis = $entry->nodeValue;
}
$xpath = new DOMXPath($dom); //obrázek plakátu
$nodes = $xpath->query("//img[@class='film-poster']");
$poster_url = "http:".$nodes->item(0)->getAttribute('src');
#17 maniakum
Ještě koukám, že první i druhý název parsuješ z "title". První najdeš v "@header" a druhý v seznamu "@names". Rok a země původu je pak v "@origin", žánr v "@genre". Rodičovské elementy hledat nemusíš, XPath umí hledat i podle samotných class.
#18 Kit
Tak pak takhle:
$dom = new domDocument;
$csfd = file_get_contents("http://www.csfd.cz/film/$csfd_id");
$html = (ord($csfd[0]) == 31) ? gzdecode($csfd) : $csfd;
@$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;
$xpath = new DOMXPath($dom);
$nazvy = array();
$zeme = array();
$names_other = "";
$nodes = $xpath->query("//h1[@itemprop='name']");
$names_cs = $nodes->item(0)->nodeValue;
foreach($xpath->query("//ul[@class='names']/li/h3") as $li) {
$nazvy[] = $li->nodeValue;
}
foreach($xpath->query("//ul[@class='names']/li/img") as $li) {
$zeme[] = $li->getAttribute('alt');
}
for($i=0;$i<count($nazvy);$i++){
if($i==count($nazvy)-1)
$names_other .= $zeme[$i]."-".$nazvy[$i];
else
$names_other .= $zeme[$i]."-".$nazvy[$i].";";
}
$nodes = $xpath->query("//h2[@class='average']");
$hodnoceni = str_replace('%', '', $nodes->item(0)->nodeValue);
$nodes = $xpath->query("//p[@class='origin']");
$podrobnosti = explode(", ", $nodes->item(0)->nodeValue);
$nodes = $xpath->query("//p[@class='genre']");
$genre = str_replace(' / ', '@;@', $nodes->item(0)->nodeValue);
$nodes = $xpath->query("//span[@data-truncate='340']");
$hraji = $nodes->item(0)->nodeValue;
$nodes = $xpath->query("//div[@data-truncate='570']");
$popis = $nodes->item(0)->nodeValue;
$nodes = $xpath->query("//img[@class='film-poster']");
$poster_url = "http:".$nodes->item(0)->getAttribute('src');
Pak mám ještě ale problém s těmi dalšími názvy, určitě to jde udělat lépe, tedy, aby se to všechno udělalo v jednom kroku.
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku