Skocz do zawartości

Automatyczne pobieranie obrazków


throw.pl

Rekomendowane odpowiedzi

Ten skrypt nie jest do końca związany z SEO, ale myślę, że może się przydać. Ten skrypt powstał przy okazji większego projektu, którego celem była analiza dużej ilości danych w tym obrazów. Większość danych pochodziła z ogólnodostępnych źródeł, które nie wymagały specjalnych dodatkowych nakładów pracy. Pojawiła się jednak potrzeba, aby w miarę jednolity sposób pobierać obrazki z niestandardowych źródeł.

Trochę przerobiłem klasy z mojego projektu, scaliłem w jeden plik i rezultat oddaję do Waszej dyspozycji. Skrypt trzeba uruchomić jako proces PHP, a nie WWW tj. za pomocą polecenia typu: php -f index.php. (Można uruchomić jako proces potomny HTTPD, ale wtedy trzeba wyłączyć limity czasu uruchomiania).

Najlepiej zainstalować sobie XAMPP: https://xampp.pl/xampp-download/ i w pliku run.bat podać pełną ścieżkę do php.exe

index.php (to nasz główny skrypt)

<?php
/*

Ten skrypt powstał przy okazji większego projektu, którego celem była analiza dużej ilości danych w tym obrazów. Większość danych pochodziła z ogólnodostępnych źródeł, które nie wymagały specjalnych dodatkowych nakładów pracy. Pojawiła się jednak potrzeba, aby w miarę jednolity sposób pobierać obrazki z niestandardowych źródeł. Po analizie wielu amatorskich galerii doszliśmy do wniosku, że skrypt powinien działać w następujący sposób: 

1. Skrypt porusza się po linkach zamieszczonych w pliku input.txt
1.1 Dla każdego linka pobiera wszystkie obrazki
1.2 Jeżeli jeden z obrazków jest częścią linka <a href=''><img src=''></a> to pobieramy również i ten obrazek (często jest to obraz w pełnych wymiarach)
1.3 Odrzucamy obrazki nie spełniające kryteriów

Takie, a nie inne podejście, wpływa również na techniczne rozwiązanie prezentowanego skryptu. Widać poniżej w kodzie, że priorytetem są właśnie <img src=''>, a nie <a href=''></a>.

Przykładem użycia skryptu może być przeglądanie najnowszych szablonów np. https://wordpress.org/extend/themes/browse/updated/ czy https://www.templatemonster.com/website-templates.php

*/

error_reporting(E_ALL);
set_time_limit(0);

// ustawienia cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 90);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729)");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

//domyślne ustawienia
$default = array
(
	'directory' => md5(time()),
	'extensions' => array('jpg', 'jpeg', 'png', 'gif'),
);

// lista wejściowa
$input = file('input.txt');

// "parsowanie" danych wejściowych
for($i=0, $j=count($input); $i<$j; $i++)
{
	$params = array();
	if(preg_match_all('/(\w*=".*")/Ui', $input[$i], $matches))
	{
		for($k=0, $l=count($matches[0]); $k<$l; $k++)
		{
			$tmp = explode("=", $matches[0][$k]);
			$params[$tmp[0]] = str_replace('"', '', $tmp[1]);
		}
	} else {
		echo 'Błędny format w input.txt';
		continue;
	}

	if(!isset($params['url']))
	{
		echo 'Brak adresu w input.txt';
		continue;
	}

	$target = strtolower(trim($params['url']));
	$outputdir = (isset($params['directory'])) ? $params['directory'] : md5($target);

	curl_setopt($ch, CURLOPT_URL, $target);
	// domena i katalog uzyskane z adresu
	$domain = str_replace('https://', '', $target);
	if(strpos($domain, '/')===false)
	{	// https://domain.tld
		$domain = $directory = $target;
	} else {
		// https://domain.tld/ 
		// https://domain.tld/...
		// https://domain.tld/.../...
		// itd,.
		$tmpArray = explode('/', $domain);
		$domain = 'https://'.$tmpArray[0].'/';
		if(substr($target, -1)=='/')
		{
			// https://domain.tld/(...)/
			$directory = $target;
		} else {
			// https://domain.tld/(...)/...
			$tmpArray[count($tmpArray)-1] = null;
			unset($tmpArray[count($tmpArray)-1]);
			$directory = 'https://'.implode('/', $tmpArray).'/';
		}
	}

	$html = str_replace(array(chr(13),chr(10)), '', curl_exec($ch));

	$preg_extensions = (isset($params['extensions'])) ? str_replace(',', '|', str_replace(' ', '', $params['extensions'])) : implode('|', $default['extensions']);
	$extensions = (isset($params['extensions'])) ? explode(',', str_replace(' ', '', $params['extensions'])) : $default['extensions'];

	// pobiera wszystkie linki do obrazków
	preg_match_all("/href=(?:'|\"|)(\S*".$preg_extensions.")(?:'|\"|)>(.*)<\/a>/Ui", $html, $links);

	// pobiera wszystkie obrazki ze strony
	if(preg_match_all("/src=(?:'|\"|)(.*)(?:'|\"|)(?:\s|\/>)/Ui", $html, $matches))
	{
		$imgcnt=0;
		for($x=0, $y=count($matches[1]); $x<$y; $x++)
		{
			// działamy lokalnie, a nie jako strona WWW, więc można sobie trochę 
			// poswawolić - mam tutaj na myśli kolejną pętlę, a w niej if()
			$preimgsrc = str_replace(array('\'', '"'), '', $matches[1][$x]);

			for($n=0, $m=count($links[0]); $n<$m; $n++)
			{
				if(strpos($links[0][$n], $preimgsrc) !== false)
				{
					$preimgsrc = $links[1][$n];
					$links[0][$n] = null;
				}
			}

			// rozponawanie, czy jest to link relatywny (i jaki) czy bezwzgledny
			if(substr($preimgsrc, 0, 7) == "https://")
			{
				$imgsrc = $preimgsrc;
			} else if(substr($preimgsrc, 0, 1) == "/")
			{
				$imgsrc = $domain.substr($preimgsrc, 1);
			} else {
				$imgsrc = $directory.$preimgsrc;
			}

			if(strpos($imgsrc, '.')!== false)
			{
				$extension = substr(strrchr($imgsrc, '.'), 1);
			} else {
				$extension = '';
			}

			if(!in_array($extension, $extensions)) continue; // czy rozszerzenie obrazka spełnia kryterium
			if(!is_dir($outputdir) && !mkdir($outputdir)) $outputdir = $default['directory']; // czy da sie uzyskać dostęp/stworzyć katalog na dane
			$image_filename = $outputdir.'/'.md5($target).$imgcnt++.'.'.$extension; // nazwa pliku 

			// zapisywanie danych obrazka
			$image_file = fopen($image_filename, 'w+');
			fwrite($image_file, file_get_contents($imgsrc));
			fclose($image_file);

			// po ściągnięciu sprawdzamy czy spełnia kryterium wymiarów
			list($width, $height) = getimagesize($image_filename);
			if((isset($params['minwidth']) && $width<intval($params['minwidth'])) || (isset($params['minheight']) && $height<intval($params['minheight'])) || (isset($params['maxheight']) && $height>intval($params['maxheight'])) || (isset($params['maxwidth']) && $width>intval($params['maxwidth'])))
			{
				unlink($image_filename);
				continue; 
			}

			// plik z listą obrazków i źródłem, z którego je pobraliśmy
			$index_file = fopen($outputdir.'/index.txt', 'a+');
			fwrite($index_file, md5($imgsrc).'.'.$extension.' = '.$imgsrc."\n");
			fclose($index_file);
		}
	}
}

curl_close($ch);
?>

Poniżej plik do sterowania skryptem/określenia co i jak ma zostać pobrane.

Składania jest prosta, w jednej linii mamy informację o jednym źródle danych.

Parametry

  • url="https://....", czyli informacja o tym skąd pobieramy obrazki, bez niego skrypt nie pobierze danych
  • directory="nazwa katalogu", możemy (nie musimy) podać nazwę katalogu docelowego. Domyślnie jest md5(url)
  • extensions="jpg,jpeg,png", możemy (nie musimy) podać listę rozszerzeń. Domyślnie jest jpg,jpeg,png,gif
  • minwidth="100", możemy podać minimalną szerokość obrazka (po ściągnięciu jest sprawdzana), obrazki mniejsze są kasowane
  • minheight="101", możemy podać minimalną wysokość obrazka (po ściągnięciu jest sprawdzana), obrazki mniejsze są kasowane
  • maxwidth="102", możemy podać maksymalną szerokość obrazka (po ściągnięciu jest sprawdzana), obrazki większe są kasowane
  • maxheight="103", możemy podać maksymalną wysokość obrazka (po ściągnięciu jest sprawdzana), obrazki większe są kasowane

Parametry wprowadzamy tak:

nazwa(url,directory,maxwidth)="wartość" - cudzysłów(") musi być!

Poniżej przykładowy plik z danymi wejściowymi.

input.txt (dane wejściowe)

url="https://www.gazeta.pl/0,0.html" directory="gazeta-wszystsko"
url="https://www.gazeta.pl/0,0.html" directory="gazeta-gif" extensions="gif"
url="https://www.gazeta.pl/0,0.html" directory="gazeta-jpg" extensions="jpg,jpeg"
url="https://www.gazeta.pl/0,0.html" directory="gazeta-jpg-max100" extensions="jpg,jpeg" maxwidth="100"
url="https://www.gazeta.pl/0,0.html" directory="gazeta-jpg-max100xmax100" extensions="jpg,jpeg" maxwidth="100" maxheight=100"
url="https://www.gazeta.pl/0,0.html" directory="gazeta-jpg-min140xmin100" extensions="jpg,jpeg" minwidth="140" minheight="100"
url="https://technologie.gazeta.pl/internet/0,0.html" directory="technologia-min100xmin100" extensions="jpg,jpeg" minwidth="100" minheight="100"
url="https://techcrunch.com/" directory="technologia-min100xmin100" extensions="jpg,jpeg" minwidth="100" minheight="100"

Jak widać:

1. Do katalogu gazeta-wszystsko zostaną wrzucone pliki typu: jpg,jpeg,png,gif (domyślne ustawienia)

2. Do katalogu gazeta-gif zostaną wrzucone pliki typu: gif

3. Do katalogu gazeta-jpg zostaną wrzucone pliki typu: jpg,jpeg

4. Do katalogu gazeta-jpg-max100 zostaną wrzucone pliki typu: jpg,jpeg o szerokości mniejszej równej 100 (100x)

5. Do katalogu gazeta-jpg-max100xmax100 zostaną wrzucone pliki typu: jpg,jpeg o szerokości mniejszej lub równej 100 i wysokości mniejszej lub równej 100 (100x100)

6. Do katalogu gazeta-jpg-min140xmin100 zostaną wrzucone pliki typu: jpg,jpeg o szerokości większej lub równej 140 i wysokości większej lub równej 100 (140+x100+)

7. Do katalogu technologia-min100xmin100 zostaną wrzucone pliki typu: jpg,jpeg o szerokości mniejszej lub równej 100 i wysokości mniejszej lub równej 100 (100x100)

8. Do katalogu technologia-min100xmin100 zostaną wrzucone pliki typu: jpg,jpeg o szerokości mniejszej lub równej 100 i wysokości mniejszej lub równej 100 (100x100)

Jak widać mamy duża dowolność w ściąganiu i rozmieszczaniu obrazków:

1. Możemy wybrać dokładny zakres rozmiarów

2. Możemy do jednego katalogu wrzucać zdjęcia z różnych źródeł

3. Możemy z jednej strony zdjęcia porozdzielać do różnych katalogów (w zależności od kryteriów)

Skrypt można spokojnie rozszerzyć. Zadbać o to, aby zagłębiał się w strony i pobierał jeszcze skuteczniej obrazy i/lub skalował te, które nie spełniają kryteriów (np. zmniejszał za duże zdjęcia).

run.bat

[b]C:\xampp\php\php -f [/b](ścieżka do skryptu)[b]\index.php[/b]

Najlepiej uruchomić skrypt z danymi zamieszczonymi w poście i przyjrzeć się rezultatom (utworzonym folderom i plikom w ich wnętrzu).

UWAGA

1. Stworzyłem skrypt z myślą o tym, aby pobierać obrazki konkretnego rodzaju (rozszerzenie/wymiary) z wielu źródeł i zapisywać do jednego katalogu. Dlatego, kilka wpisów z jednej strony powoduje kilkukrotne wejście na daną stronę. Wpisy typu:

url="https://www.gazeta.pl/0,0.html" directory="gazeta-gif" extensions="gif"
url="https://www.gazeta.pl/0,0.html" directory="gazeta-jpg" extensions="jpg"

Spowoduje, że 2x zostanie ściągnięty kod HTML, ale obrazi pobierane tylko raz. Natomiast

url="https://www.gazeta.pl/0,0.html" directory="gazeta-jpg" extensions="jpg" maxwidth="100"
url="https://www.gazeta.pl/0,0.html" directory="gazeta-jpg" extensions="jpg" maxwidth="110"

Spowoduje, ze wszystkie pliki .jpg zostaną pobrane 2x, ponieważ sprawdzanie wymiarów jest możliwe dopiero po ściągnięciu pliku na dysk.

2. Niektóre preg_match() i późniejsza korekta wyników może się wydawać 'dziwna', ale akurat spotkałem się z wieloma niepoprawnie tworzonymi stronami, a chciałem, żeby skrypt był zdolny do pobierania różnych tworów :)

Jakie są praktyczne zastosowania tego skryptu?

- własna wyszukiwarka obrazków

- odświeżanie galerii zdjęć

- masowe pobieranie zdjęć o określonych rozmiarach

Odnośnik do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...

Powiadomienie o plikach cookie

Umieściliśmy na Twoim urządzeniu pliki cookie, aby pomóc Ci usprawnić przeglądanie strony. Możesz dostosować ustawienia plików cookie, w przeciwnym wypadku zakładamy, że wyrażasz na to zgodę. Warunki użytkowania Polityka prywatności