registrieren registriertes Mitglied


Anzeige

Anzeige

Sind hier PHP'ler unterwegs?

Stell hier Deine Frage zu: HTML, CSS, PHP, MySQL, htaccess, robots.txt, Javascript usw
Hanzo2012
Community-Manager
Community-Manager
Beiträge: 2146
Registriert: 26.09.2011, 23:31

Beitrag Hanzo2012 » 25.11.2020, 09:14 Sind hier PHP'ler unterwegs?

Danke für's Ausprobieren! Dass es (gefühlt) nicht schneller ist, wundert mich. Welchen Wert nutzt du denn für $nThreads? Auch nur 3? Das kannst du locker hochschrauben. Probier einfach mal verschiedene Werte wie 10, 20, ... - nur nicht übertreiben, weil jeder Thread auch RAM braucht.

Dass du damit deine eigenen Seiten aufrufst - wahrscheinlich um deinen Cache zu füllen - hatte ich mir schon gedacht.

Zu deinem Anliegen: Ich würde die Funktion so ändern, dass sie ein Array aus Paaren von URLs und dazugehörigen Optionen erwartet. Außerdem wäre es praktisch "Basis-Optionen" angeben zu können, die für jeden Request gleich sind, und pro Request nur die individuellen Optionen hinzufügen/ändern zu können. Hier ist mein erster Entwurf:

Code: Alles auswählen

function multi_thread_curl($urlsAndOptions, $numThreads, $baseOptions = array()) {
	$curlArray = array_chunk($urlsAndOptions, $numThreads, $preserve_keys = true);
	$results = array();
	
	foreach ($curlArray as $threads) {
		
		$curlHandles = array();
		foreach ($threads as $index => $urlAndOptions) {
			$curlHandle = curl_init();
			$curlHandles[$index] = $curlHandle;
			curl_setopt_array($curlHandle, $baseOptions + $urlAndOptions["options"]);
			curl_setopt($curlHandle, CURLOPT_URL, $urlAndOptions["url"]); 
		}
		
		$mh = curl_multi_init();
		foreach ($threads as $index => $urlAndOptions) {
			curl_multi_add_handle($mh, $curlHandles[$index]);
		}
		
		do {
			$status = curl_multi_exec($mh, $active);
			if ($active) {
				curl_multi_select($mh);
			}
		} while ($active && $status == CURLM_OK);
		
		foreach ($threads as $index => $urlAndOptions) {
			$curlHandle = $curlHandles[$index];
			$results[$index] = curl_multi_getcontent($curlHandle);
			curl_multi_remove_handle($mh, $curlHandle);
		}
		
		curl_multi_close($mh);
	}
	
	return $results;
}
Wie du siehst, habe ich den Code generell etwas aufgeräumt und schöner gemacht.

Nun, wie würdest du das nutzen? Ein Beispiel:

Code: Alles auswählen

// Optionen, die für alle Requests gleich sein sollen:
$baseOptions = array(
	CURLOPT_RETURNTRANSFER => 1,
	CURLOPT_HEADER => true,
	CURLOPT_CUSTOMREQUEST => 'GET',
	CURLOPT_FOLLOWLOCATION => false,
	CURLOPT_ENCODING => 'gzip',
	CURLOPT_CONNECTTIMEOUT => 10,
	CURLOPT_TIMEOUT => 10,
	CURLOPT_SSL_VERIFYHOST => 0,
	CURLOPT_SSL_VERIFYPEER => false,
	CURLOPT_NOBODY => false,
	CURLOPT_HTTPHEADER => array('Cache-Control: max-age=0,no-store,no-cache'),
	CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1
);

// Individuelle Optionen:
$individualOptions = array(
	array(
		CURLOPT_USERAGENT => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.47 Safari/537.36"
	),
	array(
		CURLOPT_USERAGENT => "Wurstbrowser/7.4 FAKE"
	)
);

// ... SQL-Code weggelassen ...

$crawlURLsAndOptions = array();
while ($row = $crawler_query_result->fetch_array()) {
	// Jede URL mit jedem individuellen Set an Optionen separat abfragen.
	$url = $row["url"];
	foreach ($individualOptions as $options) {
		$crawlURLsAndOptions[] = array("url" => $url, "options" => $options);
	}
}

$results = multi_thread_curl($crawlURLsAndOptions, $nThreads, $baseOptions);

Anzeige von: