Parcurgere cu Dom

php
dom

(Stefu Catalin) #1

Salut, incerc sa parcurg cu DOM, o pagina dupa youtube, insa e mult prea complicata si nici eu nu sunt familiarizat cu aceasta metoda. Am reusit doar sa ajung in “tbody” din table, care “table” e singurul tag din pagina,deci n-ar fi o problema de confuzie.

                $html = file_get_contents($file) ;     
                $dom = new domDocument; 
                $dom->loadHTML($html); 
                $dom->preserveWhiteSpace = false;
                $tables = $dom->getElementsByTagName('tbody');

Si pagina preluata arata cam asa: https://pastebin.com/E1ni2X5a
Oricum, cred ca metoda corecta ar fi sa parcurg in mod ierarhic: html>body>table>tr>td.
Eu as avea nevoie de atributul “data-title” si “data-video-id” din

<tr class="pl-video yt-uix-tile " data-set-video-id="" data-title="INNA - Ruleta (feat. Erik) | Official Music Video " data-video-id="ax9ge-ymWIQ">"

si de valoarea 3:15

<div class="timestamp"><span aria-label="3 minutes, 15 seconds">3:15</span></div>

Stiu, as putea lucra cu api-ul oferit, insa nu sunt multumit de anumite rezultate. Ar merge facut si cu explode(),insa cererea cred ca dureaza mai mult decat cu DOM().
Multumesc mult !


(Ionuț Staicu) #2

Poți detalia? Singura problemă avută de mine este legată de modul în care este dată durata filmului, de multe ori mi s-a întâmplat să fie o secundă în plus sau în minus.


(Stefu Catalin) #3

Da, e vorba de videoclipurile “related” ale unui clip. De ex, daca am o melodia cu “Smiley” imi da si cele cover, adica nu-mi respecta categoria “Muzica”, care are id-ul 10 daca nu ma insel.

GET https://www.googleapis.com/youtube/v3/search?part=snippet&relatedToVideoId=5rOiW_xY-kc&type=video&key={YOUR_API_KEY}

Pentru ca in metoda “search”, nu are si campul categoryID.Sper ca ai inteles, ms.


(Andrei Terecoasa) #4

My 2 cents: (using regex. Nu sunt sigur daca e mai optim si daca se pliaza pe toate nevoile but…)

$vid = '/data\-video-id=\"(.*?)\"/';
$title = '/data\-title=\"(.*?)\"/';
$len = '/<div\sclass=\"timestamp\"\>\<span .*?\>(.*?)\<\/span\><\/div>/';

$content = file_get_contents("page.txt");

preg_match($vid, $content, $match1);
print_r($match1);
preg_match($title, $content, $match2);
print_r($match2);
preg_match($len, $content, $match3);
print_r($match3);

Output

C:\Users\aterecoasa\Desktop>php yt.php
Array
(
    [0] => data-video-id="ax9ge-ymWIQ"
    [1] => ax9ge-ymWIQ
)
Array
(
    [0] => data-title="INNA - Ruleta (feat. Erik) | Official Music Video"
    [1] => INNA - Ruleta (feat. Erik) | Official Music Video
)
Array
(
    [0] => <div class="timestamp"><span aria-label="3 minutes, 15 seconds">3:15</span></div>
    [1] => 3:15
)

(Stefu Catalin) #5

In ultima faza, am sa merg cu regex,probabil voi avea nevoie si de preg_match.Anyway, am sa le combin :slight_smile:
foreach($x->query('//tr') as $table)
Scot continutul din “tr” si-l manipulez, cu functiile de mai sus. Multumesc !


(Georgiana Gligor) #6

Personal nu incurajez scrierea de expresii regulate “manuale” care se folosesc doar o data (pe un singur caz). Eu as incerca sa folosesc componenta Symfony numita DomCrawler in combinatie cu CssSelector, e mult mai usor sa faca altcineva parcurgerea DOM-ului :smile:

Am gasit cu usurinta documentatie si exemple, aici un snippet sa iti faci o idee, un blogpost scurt la fel de targetat. Sunt si tutoriale mai avansate, care adauga Goutte in combinatie pt a obtine un pachet complet, aici cred ca depinde f mult de ce ai nevoie sa faci.


(Andrei Tripon) #7

@bystefu poate te ajuta si raspunsurile de la acest subiect.


(Stefu Catalin) #8

Multumesc frumos,dragi prieteni. Ca urmare a interesului manifestat, presupun ca ar fi frumos din partea mea sa va arat cum am reusit. Bineinteles,erau mai multe cai,insa asta cred ca e cea mai "friendly’.

        function youtubeHomePage(){
            global $_COOKIE;
            $results = array();
            $file = $this->youtubeCURL("https://www.youtube.com/playlist?list=PLFgquLnL59akxkuW7czf5TvyjzcUMgaci");
            if(is_file($file)){
                $html = file_get_contents($file) ;     
                $dom = new domDocument; 
                $dom->loadHTML($html); 
                $dom->preserveWhiteSpace = false;
                $find_id = '/data\-video-id=\"(.*?)\"/';
                $find_title = '/data\-title=\"(.*?)\"/';
                $find_length = '/<div\sclass=\"timestamp\"\>\<span .*?\>(.*?)\<\/span\><\/div>/';
                $new_file = new DOMXpath($dom);
                $i = 0;
                if($new_file->query('//tr')->length>0)
                {
                    foreach($new_file->query('//tr') as $table){
                        $i++;
                        preg_match($find_id, $table->C14N(), $id);
                        preg_match($find_title, $table->C14N(), $title);
                        preg_match($find_length, $table->C14N(), $length);
                        $results[$i] = array(
                            "i"=>$id[1],
                            "n"=>$title[1],
                            "l"=>$length[1],
                            "t"=>"https://i.ytimg.com/vi/{$id[0]}/default.jpg"
                        );
                        if($i>=30)break;
                     }
                }
            }
            return json_encode($results);
        }

N-o sa neglijez nici variantele lui @tekkie si @Andrei . Am sa arunc imediat o privire.


(Nicolicioiu Liviu) #9

In link-ul trimis de tine:
https://pastebin.com/E1ni2X5a
Html-ul nu e valid, tag-ul de tbody, nu se inchide.
Parcurgerea cu dom e posibila pe un continut valid.


(Stefu Catalin) #10

Intreaga pagina are 500kb, am pus asa sa va faceti o idee si sa scot partea care ma interesa.Iti dai seama ce iesea la 10K de linii html.