25.04.2023

8

Like

144

Views

Patika için Basit Bir PHP Web Scraping

Merhaba dostum, makalemi okumak için burada olduğun için teşekkür ederim. Bu, senin için tam anlamıyla bir makale olmayabilir, sadece biraz örnek PHP kodu içeriyor.


Patika Akademi'nin yeni arayüzüne göz atarken, kullanıcıların telefon numarasına ulaşabildiğimi fark ettim. Biraz eğlenceli olması için, Guzzle kullanarak basit bir PHP kodu yazdım. Umarım bu örnek ile işinize yarar sağlayabilirim.


Aşağıdaki komutu çalıştırarak Guzzle kütüphanesini projenize ekleyin.

composer require guzzlehttp/guzzle


PHP uzantılı bir dosya oluşturalım ve adını FetchUsername.php koyalım.


GuzzleHttp istemcisini dahil edelim.

require_once "vendor/autoload.php";

use GuzzleHttp\Client;

$client = new Client();


Daha sonra, Usernames.json dosyasının adını ve ayarları tanımlayalım.

$jsonFile = "Usernames.json";

$offset = 0;

$perPage = 6;


GraphQL sorgusu için gerekli yük bilgilerini oluşturalım.

$payload = [
"operationName" => "articles",
"variables" => [
"search" => "",
"sort" => ["updatedAt" => -1],
"offset" => 0,
],
"query" =>
"query articles(\$topic: String, \$search: String, \$self: Boolean, \$sort: ArticleSort, \$offset: Int) {\n blogs: articles(\n topic: \$topic\n search: \$search\n self: \$self\n sort: \$sort\n offset: \$offset\n ) {\n articles {\n _id\n title\n updatedAt\n authorUsername\n authorName\n slug\n likeCount\n viewCount\n isPublished\n selectedCourses {\n id\n label\n value\n __typename\n }\n __typename\n }\n totalCount\n __typename\n }\n}",
];


Kullanıcı adlarını saklamak için bir dizi oluşturalım. Eğer Usernames.json dosyası varsa, içeriğini okur ve diziye dönüştürelim. Yoksa, boş bir dizi ile dosyayı oluşturalım.

$usernamesData = [];

if (file_exists($jsonFile)) {
$usernamesData = json_decode(file_get_contents($jsonFile), true);
} else {
file_put_contents($jsonFile, json_encode([]));
}


Döngüyü başlatalım. Bu döngü, mevcut sayfanın toplam sayfa sayısının üstünde olana kadar devam eder.

do {
//...
} while ($pageCount * $perPage > $offset);


Her döngüde, offset değerini yük değişkenlerine atayalım. Bu, sorgunun hangi sayfayı alacağını belirler.

$payload["variables"]["offset"] = $offset;


GraphQL istemcisini kullanarak sorguyu gönderelim ve yanıtı alalım.

$payload["variables"]["offset"] = $offset;

$response = $client->post("https://cohorts.patika.dev/graphql", [
"headers" => [
"Content-Type" => "application/json",
],
"body" => json_encode($payload),
"verify" => false,
]);

$responseBody = $response->getBody()->getContents();

$responseData = json_decode($responseBody, true);


Yanıttan makaleleri çıkaralım ve her bir makale için yazarın kullanıcı adını alalım.

$articles = $responseData["data"]["blogs"]["articles"];

foreach ($articles as $article) {
$username = $article["authorUsername"];

//...
}


Eğer kullanıcı adı henüz usernamesData dizisinde bulunmuyorsa, kullanıcı adını bu diziye ekleyelim ve Usernames.json dosyasına kaydedelim. Ardından kullanıcı adını ekrana yazdıralım.

if (!in_array(["Username" => $username], $usernamesData)) {
$usernamesData[] = ["Username" => $username];

file_put_contents($jsonFile, json_encode($usernamesData));

echo $username . PHP_EOL;
}


Döngünün sonunda, toplam yazı sayısını ve sayfa sayısını güncelleyelim ve offset değerini arttıralım.

$totalCount = $responseData["data"]["blogs"]["totalCount"];

$pageCount = ceil($totalCount / $perPage);

$offset += $perPage;


Aşağıda yer alan kod bloğunda, FetchUsername.php dosyasındaki tüm kodları bulabilirsiniz.

<?php

require_once "vendor/autoload.php";

use GuzzleHttp\Client;

$client = new Client();

$jsonFile = "Usernames.json";

$offset = 0;

$perPage = 6;

$payload = [
"operationName" => "articles",
"variables" => [
"search" => "",
"sort" => ["updatedAt" => -1],
"offset" => 0,
],
"query" =>
"query articles(\$topic: String, \$search: String, \$self: Boolean, \$sort: ArticleSort, \$offset: Int) {\n blogs: articles(\n topic: \$topic\n search: \$search\n self: \$self\n sort: \$sort\n offset: \$offset\n ) {\n articles {\n _id\n title\n updatedAt\n authorUsername\n authorName\n slug\n likeCount\n viewCount\n isPublished\n selectedCourses {\n id\n label\n value\n __typename\n }\n __typename\n }\n totalCount\n __typename\n }\n}",
];

$usernamesData = [];

if (file_exists($jsonFile)) {
$usernamesData = json_decode(file_get_contents($jsonFile), true);
} else {
file_put_contents($jsonFile, json_encode([]));
}

do {
$payload["variables"]["offset"] = $offset;

$response = $client->post("https://cohorts.patika.dev/graphql", [
"headers" => [
"Content-Type" => "application/json",
],
"body" => json_encode($payload),
"verify" => false,
]);

$responseBody = $response->getBody()->getContents();

$responseData = json_decode($responseBody, true);

$articles = $responseData["data"]["blogs"]["articles"];

foreach ($articles as $article) {
$username = $article["authorUsername"];

if (!in_array(["Username" => $username], $usernamesData)) {
$usernamesData[] = ["Username" => $username];

file_put_contents($jsonFile, json_encode($usernamesData));

echo $username . PHP_EOL;
}
}

$totalCount = $responseData["data"]["blogs"]["totalCount"];

$pageCount = ceil($totalCount / $perPage);

$offset += $perPage;
} while ($pageCount * $perPage > $offset);


PHP uzantılı yeni bir dosya oluşturalım ve adını FetchPhoneNumber.php koyalım.


Tekrardan Guzzle HTTP istemcisini içe aktaralım.

require_once "vendor/autoload.php";

use GuzzleHttp\Client;

$client = new Client();


Telefon numaralarını saklayacak olan JSON dosyasının ismini tanımlayalım.

$phonesFile = "PhoneNumbers.json";


Kullanıcı adlarını içeren JSON dosyasını okuyalım ve $usernamesData dizisine atayalım.

$usernamesData = json_decode(file_get_contents("Usernames.json"), true);


Telefon numaralarını içeren JSON dosyasını kontrol edelim, varsa okuyalım ve $phoneNumbers dizisine atayalım. Yoksa, boş bir diziyi telefon numaraları dosyasına yazalım.

$phoneNumbers = [];

if (file_exists($phonesFile)) {
$phoneNumbers = json_decode(file_get_contents($phonesFile), true);
} else {
file_put_contents($phonesFile, json_encode([]));
}


Kullanıcı adları verilerini döngüye alarak her kullanıcı için aşağıdaki işlemleri gerçekleştirelim.

foreach ($usernamesData as $user) {
$username = $user["Username"];

//...
}


Kullanıcının profil sayfasının JSON veri URL'sini oluşturalım ve $url değişkenine atayalım.

$url = "https://academy.patika.dev/_next/data/ZALmorHPrZskcSlOvlBjQ/en/user/$username.json?slug=$username";


JSON veri URL'sinden kullanıcının profil bilgilerini almak için bir GET isteği gönderelim ve yanıtı alalım.

try {
$response = $client->get($url, [
"headers" => [
"Cookie" =>
"__Secure-next-auth.session-token=",
],
"verify" => false,
]);

$responseBody = $response->getBody()->getContents();

$responseData = json_decode($responseBody, true);

//...
} catch (Exception $e) {
//...
}


__Secure-next-auth.session-token çerezindeki değeri görüntülemek için inceleme modunu açın ve ardından Cookies (Çerezler) bölümüne geçin.


Yanıttan kullanıcının telefon numarasını çıkaralım.

$phoneNumber = $responseData["pageProps"]["data"]["phoneNumber"];


Eğer telefon numarası geçerli ve daha önce kaydedilmemişse, $phoneNumbers dizisine ekleyelim, telefon numaralarını içeren JSON dosyasına yazalım ve ekrana kullanıcı adı ve telefon numarasını yazdıralım.

if ($phoneNumber && !in_array($phoneNumber, $phoneNumbers)) {
$phoneNumbers[] = ["PhoneNumber" => $phoneNumber];

file_put_contents($phonesFile, json_encode($phoneNumbers));

echo "$username: $phoneNumber" . PHP_EOL;
}


Hata durumunda, kullanıcı adını ve hata mesajını ekrana yazdıralım.

catch (Exception $e) {
echo "$username: " . $e->getMessage() . PHP_EOL;
}


Aşağıda yer alan kod bloğunda, FetchPhoneNumber.php dosyasındaki tüm kodları bulabilirsiniz.

<?php

require_once "vendor/autoload.php";

use GuzzleHttp\Client;

$client = new Client();

$phonesFile = "PhoneNumbers.json";

$usernamesData = json_decode(file_get_contents("Usernames.json"), true);

$phoneNumbers = [];

if (file_exists($phonesFile)) {
$phoneNumbers = json_decode(file_get_contents($phonesFile), true);
} else {
file_put_contents($phonesFile, json_encode([]));
}

foreach ($usernamesData as $user) {
$username = $user["Username"];

$url = "https://academy.patika.dev/_next/data/ZALmorHPrZskcSlOvlBjQ/en/user/$username.json?slug=$username";

try {
$response = $client->get($url, [
"headers" => [
"Cookie" =>
"__Secure-next-auth.session-token=XXXXX",
],
"verify" => false,
]);

$responseBody = $response->getBody()->getContents();

$responseData = json_decode($responseBody, true);

$phoneNumber = $responseData["pageProps"]["data"]["phoneNumber"];

if ($phoneNumber && !in_array($phoneNumber, $phoneNumbers)) {
$phoneNumbers[] = ["PhoneNumber" => $phoneNumber];

file_put_contents($phonesFile, json_encode($phoneNumbers));

echo "$username: $phoneNumber" . PHP_EOL;
}
} catch (Exception $e) {
echo "$username: " . $e->getMessage() . PHP_EOL;
}
}


İki dosya hazır olduğunda, öncelikle terminali açarak projenizin bulunduğu dizine gidelim. Ardından, "php FetchUsername.php" komutunu kullanarak kullanıcı adlarını kaydedelim. İşlem tamamlandıktan sonra, "php FetchPhoneNumber.php" komutunu çalıştıralım. Tüm işlem tamamlandığında, telefon numaraları "PhoneNumbers.json" dosyasına kaydedilecektir.


FetchPhoneNumber.phpFetchPhoneNumber.php

PHP Temel
GraphQL
REST API

Comments

You need to log in to be able to comment!

Berkan Türkmen

Location

Ordu, TR

© 2021 Patika Dev

facebook
twitter
instagram
youtube
linkedin