Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Skrapowanie obrazków
Forum PHP.pl > Forum > Przedszkole
wiedzma92
Witajcie! Próbuję stworzyć funkcję, która zwróci główne obrazki ze strony http://jbzd.pl. TYLKO główne obrazki, nie jakieś loga czy inne pierdoły. Niestety mój twór wywala kilka błędów. Zerknijcie, proszę, na te hieroglify i powiedzcie, co w nich nie gra.

  1. <?php
  2.  
  3. function getImages($url, $referrer)
  4. {
  5. $ch = curl_init($url);
  6.  
  7. if (curl_errno($ch))
  8. {
  9. echo 'Error ' . curl_errno($ch) . ': ' .curl_error($ch);
  10. }
  11.  
  12. curl_setopt($ch, CURLOPT_REFERER, $referrer);
  13.  
  14. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  15. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3');
  16.  
  17. $content = curl_exec($ch);
  18.  
  19. $doc = new DOMDocument();
  20. $doc->loadHTML($content);
  21.  
  22. $xpath = new DOMXPath($doc);
  23. $images = $xpath->query('//span[@class = "image rolled"]/img');
  24.  
  25. return $images;
  26. }
  27.  
  28. echo getImages('http://jbzd.pl', 'http://localhost/img.php');
markuz
Podzielisz się z nami treścią tych błędów?
wiedzma92
Oczywiście, oto te straszydła:

Warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 35 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): Unexpected end tag : script in Entity, line: 220 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): Unexpected end tag : script in Entity, line: 226 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 487 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity, line: 487 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): Tag video invalid in Entity, line: 554 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): Tag source invalid in Entity, line: 555 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): Unexpected end tag : p in Entity, line: 800 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Warning: DOMDocument::loadHTML(): Unexpected end tag : p in Entity, line: 816 in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 20

Catchable fatal error: Object of class DOMNodeList could not be converted to string in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 28
Pyton_000
Kod
$content = file_get_contents('http:/...');

preg_match_all('/image rolled.*?src="(.*?)"/s', $content, $match);
var_dump($match);
wiedzma92
Poprawiłam mój kod. Chciałabym teraz, żeby powstała tablica ze wszystkimi ścieżkami oraz info, czy jest to jpg, czy gif, bo teraz pojawia się tylko wskaźnik (liczba obrazków). Podpowiedzcie, proszę, jak to zrobić. Będę wdzięczna smile.gif

  1. libxml_use_internal_errors(true);
  2.  
  3. function getImages($url, $referrer)
  4. {
  5. $ch = curl_init($url);
  6.  
  7. if (curl_errno($ch))
  8. {
  9. echo 'Error ' . curl_errno($ch) . ': ' .curl_error($ch);
  10. }
  11.  
  12. curl_setopt($ch, CURLOPT_REFERER, $referrer);
  13.  
  14. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  15. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3');
  16.  
  17. $content = curl_exec($ch);
  18.  
  19. $doc = new DOMDocument();
  20. $doc->loadHTML($content);
  21.  
  22. $xpath = new DOMXPath($doc);
  23. $images = $xpath->query('//div[@class="image rolled"]/a/img[@src]');
  24.  
  25. return $images;
  26.  
  27. foreach ($images as $image)
  28. {
  29. $src = $image->getAttribute('src');
  30. }
  31. }
  32.  
  33. print_r(getImages('http://jbzd.pl', 'http://localhost/img.php'));

mlawnik
Funkcja substr($src, -3);

Pobiera ostatnie 3 znaki atrybutu src (rozszerzenie pliku).
Możnaby też explode z kropką i wtedy ostatni ciąg.
wiedzma92
Cytat(mlawnik @ 13.07.2016, 22:00:03 ) *
Funkcja substr($src, -3);

Pobiera ostatnie 3 znaki atrybutu src (rozszerzenie pliku).
Możnaby też explode z kropką i wtedy ostatni ciąg.

Przepraszam, pewnie wyjdę na debilkę, ale nie za bardzo rozumiem :/
mlawnik
Lepiej nie rozumieć i zapytać o wyjaśnienie niż nie rozumieć i błądzić wink.gif

Funkcja substr zwraca część ciągu podanego jako argument.
Skoro masz już adres obrazka, można wyciągnąć jego rozszerzenie.
  1. <?php
  2. $src = 'http://img.jbzd.pl/2016/07/1501aae12527847eb4e7f0eabdd93b0a.jpg';
  3.  
  4. $rozszerzenie = substr($src, -3);
  5. echo $rozszerzenie;
  6. ?>


Tu uruchomione:
https://3v4l.org/fOdBM

Albo też możemy użyć funkcji explode, która dzieli ciąg w miejscu gdzie znajduje się podany znak:
  1. <?php
  2. $src = 'http://img.jbzd.pl/2016/07/1501aae12527847eb4e7f0eabdd93b0a.jpg';
  3.  
  4. $rozszerzenie = explode('.', $src);
  5. var_dump($rozszerzenie);
  6.  
  7. echo 'Rozszerzenie: ' . end($rozszerzenie);
  8.  
  9. ?>


Tu uruchomione:
https://3v4l.org/oHe33

Mam nadzieję że teraz na przykładzie wyda się to prostsze.
Jeżeli umiesz angielski to polecam szukać w google i na stackoverflow, a jak Ci się nie uda, to zapraszamy z powrotem tutaj wink.gif.
wiedzma92
Dziękuję za wyjaśnienie i pomoc, Przyjacielu! smile.gif Mniej więcej o coś takiego mi chodziło, chciałabym jednak, żeby wyrzuciło mi na ekran tablicę ze wszystkimi plikami z rozszerzeniem .gif i .jpg, do których prowadzi ścieżka $src, oraz info o na ich temat - że gif to gif, a jpg to jpg. Zaczęłam więc kombinować z wyrażeniami regularnymi, ale pozytywnego efektu narazie brak. Stworzyłam coś takiego, ale nie wiem czy mój tok rozumowania jest słuszny i czy ma choć trochę sensu :/

  1. libxml_use_internal_errors(true);
  2.  
  3. function getImages($url, $referrer)
  4. {
  5. $ch = curl_init($url);
  6.  
  7. if (curl_errno($ch))
  8. {
  9. echo 'Error ' . curl_errno($ch) . ': ' .curl_error($ch);
  10. }
  11.  
  12. curl_setopt($ch, CURLOPT_REFERER, $referrer);
  13.  
  14. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  15. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3');
  16.  
  17. $content = curl_exec($ch);
  18.  
  19. $doc = new DOMDocument();
  20. $doc->loadHTML($content);
  21.  
  22. $xpath = new DOMXPath($doc);
  23. $images = $xpath->query('//div[@class="image rolled"]/a/img[@src]');
  24.  
  25.  
  26. foreach ($images as $image)
  27. {
  28. $src = $image->getAttribute('src');
  29. }
  30.  
  31. preg_match_all('/gif/i', $src, $gif);
  32. preg_match_all('/jpg/i', $src, $jpg);
  33.  
  34. print_r($gif);
  35. print_r($jpg);
  36.  
  37. return $images;
  38.  
  39. }
  40.  
  41. print_r(getImages('http://jbzd.pl', 'http://localhost/img.php'));
trueblue
  1. $images = $xpath->query('//div[@class="image rolled"]/a/img[contains(@src,".jpg") or contains(@src,".gif")]');


  1. $images = $xpath->query('//div[@class="image rolled"]/a/img[substring(@src,string-length(@src)-string-length(".gif")+1)=".gif" or substring(@src,string-length(@src)-string-length(".jpg")+1)=".jpg"]');
wiedzma92
Niestety rezultat jest podobny do tego z mojego kodu. Czyli wypluwa tablicę z liczbą elementów, bez ścieżek do obrazków i bez informacji, czy to jpg, czy gif… sadsmiley02.gif
trueblue
Tyle, że tym zapytaniem nie zastąpisz tego o czym piszesz, ale wyciągasz tylko jpg i gif.
Po nim stosujesz foreach, który podałaś wyżej, a w nim wystarczy sprawdzić czy rozszerzenie to jpg, jeśli nie to gif (przykład podał mlawnik).
wiedzma92
No, teraz wszystko pięknie śmiga. Dzięki za pomoc i cierpliwość, Chłopaki smile.gif
mlawnik
Takim osobom jak ty przyjemnie się pomaga, dlatego że potrafią czytać ze zrozumieniem i wytłumaczyć o co im chodzi wink.gif
wiedzma92
Miło mi to słyszeć happy.gif Raz jeszcze, z całego serduszka, dziękuję za pomoc heart.gif

Myślałam, że dalej dam sobie radę sama, ale za cienka jestem jeszcze w kodzie, by nie zadawać głupich pytań. Założyłam, że mój skrypt będzie sprawdzał, czy obrazek to .jpg czy nie, dlatego w wyrażeniu regularnym tylko .jpg uwzględniłam. Dodatkowo chciałabym, żeby mój skrypt pobrał wszystkie obrazki z 5 stron i zapisał je na dysku oraz informację, czy są jpg.

Wiem, że w poniższym kodzie jest bajzel i wszystko źle, ale uczę się dopiero i jeszcze błądzę, dlatego tak często szukam pomocy. Z góry bardzo dziękuję za rady, jak to ugryźć, żeby działało smile.gif

  1. libxml_use_internal_errors(true);
  2.  
  3. function getImages($url, $referrer)
  4. {
  5. $ch = curl_init($url);
  6.  
  7. if (curl_errno($ch))
  8. {
  9. echo 'Error ' . curl_errno($ch) . ': ' .curl_error($ch);
  10. }
  11.  
  12. curl_setopt($ch, CURLOPT_REFERER, $referrer);
  13.  
  14. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  15. curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8.0.3) Gecko/20060426 Firefox/1.5.0.3');
  16.  
  17. $content = curl_exec($ch);
  18.  
  19. $doc = new DOMDocument();
  20. $doc->loadHTML($content);
  21.  
  22. $xpath = new DOMXPath($doc);
  23. $images = $xpath->query('//div[@class="image rolled"]/a/img[@src]');
  24.  
  25. foreach ($images as $image)
  26. {
  27. $src = $image->getAttribute('src');
  28.  
  29. preg_match('/.jpg$/', $src, $ext);
  30. $imagesInfo = ['src' => $src, 'ext' => $ext];
  31.  
  32.  
  33. print_r($imagesInfo);
  34. file_get_contents($src, set_include_path('/usr/downloads'));
  35. }
  36.  
  37. return $images;
  38. }
  39.  
  40. print_r(getImages('http://jbzd.pl', 'http://localhost/img.php'));


EDIT:

Już chyba wszystko ogarnęłam, poza jednym. Za nic nie potrafię stworzyć pętli, która będzie powtarzać wyżej wymienione operacje między stroną główną a piątą podstroną. Nie mam pojęcia, jak inkrementować adres… :/
markuz
  1. $pages = 5;
  2. for($p = 0; $p < $pages; $p++)
  3. print_r(getImages('http://jbzd.pl' . ($p > 0 ? '/strona/' . ($p + 1) : ''), 'http://jbzd.pl'));
wiedzma92
Niestety ten sposób nie działa, wywala mi milion warningów tego typu: Warning: DOMDocument::loadHTML(): Empty string supplied as input in /Applications/XAMPP/xamppfiles/htdocs/img.php on line 22

Zaraz pokręci mnie przy tym skrypcie. Powiedzcie, mi proszę, co w tym fragmencie kodu nie gra, że obrazki nie chcą pobrać się na dysk, tylko to cholerstwo mi wyskakuje: „Warning: file_put_contents(/Users/agnieszka/Downloads/): failed to open stream: Is a directory in /Applications/XAMPP/xamppfiles/htdocs/img.php”.

Wrzucam tylko foreach, bo reszta kodu jest bez zmian smile.gif

  1. foreach ($images as $image)
  2. {
  3. $src = $image->getAttribute('src');
  4. preg_match('/.gif$/', $src, $ext);
  5. $imagesInfo = ['src' => $src, 'ext' => $ext];
  6.  
  7. $con = file_get_contents('http://jbzd.pl/obr/');
  8. file_put_contents('/Users/agnieszka/Downloads/', $con);
  9.  
  10. print_r($imagesInfo);
  11. }
markuz
W funkcji file_get_contents musisz podać url obrazka tj. $src a nie 'http://jbzd.pl/obr/'.
W file_put_contents podajesz pełną ścieżkę wraz z nazwą pliku, albo samą nazwe pliku żeby zapisać do tego samego folderu gdzie jest skrypt.
wiedzma92
Pozmieniałam to, oczym wspomniałeś. Teraz pojawia się inny komunikat: „Warning: file_put_contents(/Applications/XAMPP/xamppfiles/htdocs/img.php): failed to open stream: Permission denied in /Applications/XAMPP/xamppfiles/htdocs/img.php”.

Skrypt wygląda teraz tak:

  1. foreach ($images as $image)
  2. {
  3. $src = $image->getAttribute('src');
  4. preg_match('/.gif$/', $src, $ext);
  5. $imagesInfo = ['src' => $src, 'ext' => $ext];
  6.  
  7. $con = file_get_contents($src);
  8. file_put_contents('/Applications/XAMPP/xamppfiles/htdocs/scrap_img.php', $con);
  9.  
  10. print_r($imagesInfo);
  11. }
markuz
Ok. A więc jeszcze raz, file_put_contents zapisuje do pliku podanego w 1 argumencie, zawartość która jest w 2 argumencie. W 2 argumencie tj. $con masz zawartość obrazka i chcesz go zapisać do skryptu PHP o nazwie scrap_img.php? Raczej nie.

Utwórz sobie katalog o nazwie images zaraz obok pliku scrap_img.php a następnie zmień argument tej funkcji na:
  1. file_put_contents(dirname(__FILE__) . 'images/' . uniqid() . '.' . $ext, $con);


Co oznacza:
dirname(__FILE__) - ścieżka do tego pliku, u Ciebie będzie to "(.....)/XAMPP/xamppfiles/htdocs/"
images/ - nowo utworzony katalog images do którego chcesz zapisać te obrazki
uniqid() - losowa nazwa obrazka, unikalna
$ext - rozszerzenie obrazka
markuz
Zamiast $ext wstaw (end(explode('.', $src)))
nospor
Na stronie na ktorej szukasz, wszystkie wszystkie obrazki maja SRC jako .jpg wiec trudno oczekiwac by nagle sie zamienilo na .gif bo tak sobie zyczysz. Patrz na przyszlosc troche uwazniej co zawieraja dane na ktorych operujesz

ps: gify to ty masz tam w
<span class="gif_player init" data-gif="http://www.humorek.com.pl/upload/images/gif/2014/12/bardzo_wesola_mamusia_2014-12-11_20-03-58.gif">
a nie w IMG SRC
wiedzma92
Cytat(nospor @ 22.07.2016, 15:02:50 ) *
ps: gify to ty masz tam w
<span class="gif_player init" data-gif="http://www.humorek.com.pl/upload/images/gif/2014/12/bardzo_wesola_mamusia_2014-12-11_20-03-58.gif">
a nie w IMG SRC

Wiem, wiem. Tylko że kiedy zmieniam img[@src] na span[@data-gif] pobierają mi się, co oczywiste, tylko gify. Myślałam, że mimo że wszystkie obrazki mają SRC jako .jpg, da się coś zrobić, żeby skrypt przypisał im prawidłowe rozszerzenie.
markuz
  1. $con = file_get_contents('http://humorek.com.pl/');
  2. preg_match_all("/\.humorek\.com\.pl\/upload\/images\/([^\"]*)\"/", $con, $out);
  3. $images = array_map(function($a) {
  4. return 'http://www.humorek.com.pl/upload/images/' . $a;
  5. }, $out[1]);
  6.  
  7. var_export($images);
wiedzma92
Pewnie robię coś źle, bo ściągają mi się same uszkodzone .jpg :/
markuz
Pokaż kod - będziemy wiedzieć w jaki sposób połączyłaś te 2 skrypty.
markuz
Długa droga przed Tobą jeszcze, staraj się czytać kod i go rozumieć.
  1. function getImages($page = 0)
  2. {
  3. $con = file_get_contents('http://humorek.com.pl/' . ($page > 0 ? 'page/' . ($page + 1) : ''));
  4. preg_match_all("/\.humorek\.com\.pl\/upload\/images\/([^\"]*)\"/", $con, $out);
  5. foreach($out[1] as $image) {
  6. $content = file_get_contents('http://www.humorek.com.pl/upload/images/' . $image);
  7. file_put_contents(
  8. dirname('/Users/agnieszka/Downloads/') .
  9. '/Downloads/images/' . uniqid() .
  10. '.' . (end(explode('.', $image))),
  11. $content);
  12. }
  13. }
  14.  
  15. for($p = 0; $p < 3; $p++)
  16. getImages($p);
trueblue
Sprawdź co otrzymujesz po pobraniu atrybutu src.
markuz
Widzę, że szykuje się agregator "śmiesznych obrazków" z internetu - żeby wyelminować chociaz część duplikatów możesz użyć https://github.com/jenssegers/imagehash, przy pobieraniu zapisuj sobie do bazy hash obrazka i jego nazwe a potem możesz usuwać te które wystąpiły więcej niż 1 raz.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.