本文提供一個無依賴的 PHP 腳本,通過原生 Socket (fsockopen) 模擬瀏覽器請求,遞歸遍歷 Google Picasa 相冊(現已併入 Google Photos),下載所有圖片至本地目錄結構。注意:Picasa Web Albums 已於 2016 年停止服務,代碼僅供 Socket 爬蟲技術參考。
xxx.php?user=用戶名。https://picasaweb.google.com/{user},正則提取專輯標題與 URL。./{user}/{專輯}/{描述}-{索引}.{後綴}。meta refresh 跳轉下一專輯,直到結束。// 通用 Socket GET,支援 302 跟隨
function httpGet(string $host, string $path, array $headers = []): string {
$fp = fsockopen($host, 80, $errno, $errstr, 30);
if (!$fp) throw new RuntimeException("$errstr ($errno)");
$out = "GET $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: Mozilla/5.0\r\nConnection: Close\r\n\r\n";
fwrite($fp, $out);
$response = '';
while (!feof($fp)) $response .= fgets($fp, 4096);
fclose($fp);
// 簡易分離 Header/Body
list($header, $body) = explode("\r\n\r\n", $response, 2);
return $body;
}
// 圖片下載(處理 302)
function downloadImage(string $url, string $savePath): void {
$parsed = parse_url($url);
$host = $parsed['host'];
$path = $parsed['path'] . ($parsed['query'] ? '?' . $parsed['query'] : '');
$fp = fsockopen($host, 80, $errno, $errstr, 30);
// ... 發送請求、跟隨 Location、讀取 Body ...
// 確保目錄存在
if (!is_dir(dirname($savePath))) mkdir(dirname($savePath), 0755, true);
file_put_contents($savePath, $body);
}
// 主流程
$user = $_GET['user'] ?? '';
$aid = (int)($_GET['aid'] ?? 0);
$html = httpGet('picasaweb.google.com', "/$user");
preg_match_all('/access:public.*?title:(.*?).*?url:(.*?)\n/s', $html, $m);
$albums = array_combine($m[1], $m[2]);
if ($aid >= count($albums)) die('OK');
$albumTitle = array_keys($albums)[$aid];
$albumUrl = str_replace('x2F', '/', array_values($albums)[$aid]);
$albumPath = "./$user/$albumTitle";
$albumHtml = httpGet('picasaweb.google.com', str_replace('https://picasaweb.google.com', '', $albumUrl));
preg_match_all('/"summary":"(.*?)","contentType":"(.*?)","contentSrc":"(.*?)"/s', $albumHtml, $pics);
foreach ($pics[3] as $i => $picUrl) {
$ext = pathinfo($picUrl, PATHINFO_EXTENSION) ?: 'jpg';
$name = $pics[1][$i] . "-$i.$ext";
downloadImage($picUrl, "$albumPath/$name");
}
// 遞歸下一專輯
echo "<meta http-equiv='refresh' content='2;url=?aid=" . ($aid+1) . "&user=$user'>";
stream_socket_client('ssl://host:443')),極易出錯。理解 Socket 底層協議交互有助於排查 cURL 疑難雜症,但實際項目請優先選擇成熟 HTTP 客戶端庫。