HTTP istekleri (+çerezlerle çalışma, proxy, oturumlar)
Temel sınıf yöntemleri
Bir web sayfasından veri toplamak için bir HTTP isteği yürütmeniz gerekir. A-Parser'ın JavaScript API v2 sürümünde, belirtilen yöntem argümanlarına bağlı olarak yanıt olarak bir JSON nesnesi döndüren, kullanımı kolay bir HTTP isteği yürütme yöntemi uygulanmıştır. Aşağıda şunları öğreneceksiniz: HTTP isteğinin nasıl yapıldığı, yöntemin hangi argümanlara ve seçeneklere sahip olduğu, belirtilen seçeneklerin sonuçları, bir HTTP isteğinin başarı koşulunun nasıl belirtileceği ve daha fazlası.
Bu yöntemler BaseParser sınıfından miras alınır ve özel veri kazıyıcılar oluşturmak için temel teşkil eder.
İstek üzerine HTTP yanıtı alma, argüman olarak şunlar belirtilir:
method- istek yöntemi (GET, POST...)url- istek için bağlantıqueryParams- get parametrelerini içeren bir hash veya post isteği gövdesini içeren bir hash HTTP istekleri veya Oturum Yöneticisi yardımıyla başka bir iş parçacığı tarafından yürütülmek üzere kaydedin.
Bu yöntemler BaseParser sınıfından miras alınır ve özel veri kazıyıcılar oluşturmak için temel teşkil eder
await this.request(method, url[, queryParams][, opts])
await this.request(method, url, queryParams, opts)
İsteğe göre HTTP yanıtı alma, argüman olarak şunlar belirtilir:
method- istek yöntemi (GET, POST...)url- istek için bağlantıqueryParams- get parametrelerini içeren hash veya post isteği gövdesini içeren hashopts- istek seçeneklerini içeren hash
opts.check_content
check_content: [ koşul1, koşul2, ...] - alınan içeriği kontrol etmek için koşullar dizisi, eğer kontrol
başarısız olursa, istek başka bir proxy ile tekrarlanacaktır.
Özellikler:
- koşul olarak dizelerin kullanılması (dize eşleşmesine göre arama)
- koşul olarak düzenli ifadelerin (regex) kullanılması
- verilerin ve yanıt başlıklarının iletildiği özel kontrol fonksiyonlarının kullanılması
- aynı anda birkaç farklı koşul türü tanımlanabilir
- mantıksal değilleme için koşulu bir dizi içine yerleştirin, yani
check_content: ['xxxx', [/yyyy/]]ifadesi, isteğin başarılı sayılması için alınan verilerinxxxxalt dizesini içermesi ve aynı zamanda/yyyy/düzenli ifadesinin sayfada hiçbir eşleşme bulmaması gerektiği anlamına gelir
İsteğin başarılı olması için dizide belirtilen tüm kontrollerin geçmesi gerekir
Örnek (yorum satırlarında isteğin başarılı sayılması için ne gerektiği belirtilmiştir):
let response = await this.request('GET', set.query, {}, {
check_content: [
/<\/html>|<\/body>/, // alınan sayfada bu düzenli ifade çalışmalıdır
['XXXX'], // alınan sayfada bu alt dize bulunmamalıdır
'</html>', // alınan sayfada bu alt dize bulunmalıdır
(data, hdr) => {
return hdr.Status == 200 && data.length > 100;
} // bu fonksiyon true döndürmelidir
]
});
opts.decode
decode: 'auto-html' - kodlamanın otomatik tespiti ve utf8 formatına dönüştürülmesi
Olası değerler:
auto-html- başlıklara, meta etiketlerine ve sayfa içeriğine göre (önerilen en uygun seçenek)utf8- belgenin utf8 kodlamasında olduğunu belirtir<encoding>- diğer herhangi bir kodlama
opts.headers
headers: { ... } - başlıkları içeren hash, başlık adı küçük harfle belirtilir, cookie dahil edilebilir.
Örnek:
headers: {
accept: 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
'accept-encoding': 'gzip, deflate, br',
cookie: 'a=321; b=test',
'user-agent' 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36'
}
opts.headers_order
headers_order: ['cookie', 'user-agent', ...] - başlıkların sıralama düzenini geçersiz kılmaya olanak tanır
opts.onlyheaders
onlyheaders: 0 - data okumasını belirler; etkinse (1), yalnızca başlıkları alır
opts.recurse
recurse: N - yönlendirmeler üzerinden geçişlerin maksimum sayısıdır, varsayılan olarak 7'dir, geçişi devre dışı bırakmak için 0 kullanın
yönlendirmelere
opts.proxyretries
proxyretries: N - istek yürütme deneme sayısı, varsayılan olarak veri kazıyıcı ayarlarından alınır
opts.parsecodes
parsecodes: { ... } - veri kazıyıcının başarılı sayacağı HTTP yanıt kodlarının listesi, varsayılan olarak
veri kazıyıcı ayarlarından alınır. Eğer '*': 1 belirtilirse tüm yanıtlar başarılı sayılır.
Örnek:
parsecodes: {
200: 1,
403: 1,
500: 1
}
opts.timeout
timeout: N - saniye cinsinden yanıt zaman aşımı, varsayılan olarak veri kazıyıcı ayarlarından alınır
opts.do_gzip
do_gzip: 1 - sıkıştırma (gzip/deflate/br) kullanılıp kullanılmayacağını belirler, varsayılan olarak açıktır (1), kapatmak için
0 değeri atanmalıdır
opts.max_size
max_size: N - bayt cinsinden maksimum yanıt boyutu, varsayılan olarak veri kazıyıcı ayarlarından alınır
opts.cookie_jar
cookie_jar: { ... } - çerezleri içeren hash. Örnek hash:
"cookie_jar": {
"version": 1,
".google.com": {
"/": {
"login": {
"value": "true"
},
"lang": {
"value": "ru-RU"
}
}
},
".test.google.com": {
"/": {
"id": {
"value": 155643
}
}
}
opts.attempt
attempt: N - mevcut deneme numarasını belirtir, bu parametre kullanıldığında bu istek için
yerleşik deneme işleyicisi yoksayılır
opts.browser
browser: 1 - tarayıcı başlıklarının otomatik emülasyonu (1 - açık, 0 - kapalı)
opts.use_proxy
use_proxy: 1 - küresel Use proxy parametresinin üzerinde, JS veri kazıyıcı içindeki münferit bir istek için
proxy kullanımını geçersiz kılar (1 - açık, 0 - kapalı)
opts.noextraquery
noextraquery: 0 - istek URL'sine Extra query string eklenmesini devre dışı bırakır (1 - açık, 0 - kapalı)
opts.save_to_file
save_to_file: file - dosyayı doğrudan diske indirmenizi sağlar, belleğe yazmadan. file yerine
dosyanın kaydedileceği yol. Bu seçenek kullanıldığında, data ile ilgili her şey (içerik kontrolü
içerik kontrolü yapılmaz, response.data boş olur vb.)
opts.bypass_cloudflare
bypass_cloudflare: 0 - Chrome tarayıcısını kullanarak CloudFlare JavaScript korumasını otomatik olarak atlama (1 - açık, 0 -
kapalı)
Bu durumda Chrome Headless kontrolü, veri kazıyıcının bypassCloudFlareChromeMaxPages ayarlarıyla gerçekleştirilir
ve bypassCloudFlareChromeHeadless ayarlarıyla yapılır; bunlar static defaultConf ve static editableConf içine belirtilmelidir:
static defaultConf: typeof BaseParser.defaultConf = {
version: '0.0.1',
results: {
flat: [
['title', 'Title'],
]
},
max_size: 2 * 1024 * 1024,
parsecodes: {
200: 1,
},
results_format: "$title\n",
bypass_cloudflare: 1,
bypassCloudFlareChromeMaxPages: 20,
bypassCloudFlareChromeHeadless: 0
};
static editableConf: typeof BaseParser.editableConf = [
['bypass_cloudflare', ['textfield', 'bypass_cloudflare']],
['bypassCloudFlareChromeMaxPages', ['textfield', 'bypassCloudFlareChromeMaxPages']],
['bypassCloudFlareChromeHeadless', ['textfield', 'bypassCloudFlareChromeHeadless']],
];
async parse(set, results) {
const {success, data, headers} = await this.request('GET', set.query, {}, {
bypass_cloudflare: this.conf.bypass_cloudflare
});
return results;
}
opts.follow_meta_refresh
follow_meta_refresh: 0 - HTML meta etiketi aracılığıyla bildirilen yönlendirmelerin takip edilmesini sağlar:
<meta http-equiv="refresh" content="time; url=..."/>
opts.redirect_filter
redirect_filter: (hdr) => 1 | 0 - yönlendirme takibi için bir filtreleme fonksiyonu tanımlamaya olanak tanır, eğer fonksiyon
1 döndürürse, veri kazıyıcı yönlendirmeyi takip eder (opts.recurse parametresini dikkate alarak), 0 döndürürse
yönlendirme takibi durur:
redirect_filter: (hdr) => {
if (hdr.location.match(/login/))
return 1;
return 0;
}
opts.follow_common_rediects
opts.follow_common_rediects: 0 - standart yönlendirmelere geçilip geçilmeyeceğini belirler (örneğin http -> https
ve/veya www.domain.com -> domain.com), 1 belirtilirse veri kazıyıcı
opts.recurse parametresinin
opts.http2
opts.http2: 0 - istekleri gerçekleştirirken HTTP/2 protokolünün kullanılıp kullanılmayacağını belirler, varsayılan olarak
HTTP/1.1 kullanılır
opts.randomize_tls_fingerprint
opts.randomize_tls_fingerprint: 0 - bu seçenek, sitelerin TLS parmak izine göre engellemesini aşmaya olanak tanır (1 - açık, 0 -
kapalı)
opts.tlsOpts
tlsOpts: { ... } – şunlar için
ayarları
https bağlantılarına iletmeyi sağlar
await this.cookies.*
Mevcut istek için çerezlerle çalışma
.getAll()
Çerez dizisini alma
await this.cookies.getAll();

.setAll(cookie_jar)
Çerezleri ayarlama, argüman olarak çerezleri içeren bir hash iletilmelidir
async parse(set, results) {
this.logger.put("Start scraping query: " + set.query);
await this.cookies.setAll({
"version": 1,
".google.com": {
"/": {
"login": {
"value": "true"
},
"lang": {
"value": "ru-RU"
}
}
},
".test.google.com": {
"/": {
"id": {
"value": 155643
}
}
}
});
let cookies = await this.cookies.getAll();
this.logger.put("Cookies: " + JSON.stringify(cookies));
results.SKIP = 1;
return results;
}

.set(host, path, name, value)
await this.cookies.set(host, path, name, value) - tek bir çerez ayarlama.
Çerezin görünürlük alanı doğrudan belirtilen alan adı formatına bağlıdır, bu nedenle host kısmında ana bilgisayarın önündeki nokta dikkate alınır:
- eğer nokta belirtilmişse (
this.cookies.set('.domain.com', ...)), çerez tüm alt alan adları için kullanılacaktır (örneğin a.domain.com, b.a.domain.com) - eğer ana bilgisayar önünde nokta olmadan belirtilmişse (
this.cookies.set('site.com', ...)), çerez kesinlikle belirtilen ana bilgisayar için kullanılacaktır (host-only cookie) ve alt alan adlarına iletilmez
Bu ayrım kritik öneme sahiptir, çünkü noktalı ve noktasız çerezlerin aynı anda var olması bunların yinelenmesine ve sitenin öngörülemez çalışmasına neden olabilir. Doğru emülasyon için hedef sitenin çerezleri tam olarak nasıl ayarladığını (Domain özniteliği ile mi yoksa onsuz mu) her zaman kontrol edin ve uygun formatı kullanın.
async parse(set, results) {
this.logger.put("Start scraping query: " + set.query);
await this.cookies.set('.a-parser.com', '/', 'Test-cookie-1', 1);
await this.cookies.set('.a-parser.com', '/', 'Test-cookie-2', 'test-value');
let cookies = await this.cookies.getAll();
this.logger.put("Cookies: " + JSON.stringify(cookies));
results.SKIP = 1;
return results;
}

await this.proxy.*
Proxy ile çalışma
.next()
Proxy'yi bir sonrakine değiştir, eski proxy mevcut istek için artık kullanılmayacaktır
.ban()
Proxy'yi değiştir ve yasakla (servis IP üzerinden çalışmayı engellediğinde kullanılmalıdır), proxy veri kazıyıcı
ayarlarında belirtilen süre boyunca (proxybannedcleanup) yasaklanacaktır
.get()
Mevcut proxy'yi al (isteğin yapıldığı son proxy)
.set(proxy, noChange?)
await this.proxy.set('http://127.0.0.1:8080', true) - sonraki istek için proxy ayarla. noChange parametresi isteğe bağlıdır, true olarak verilirse proxy denemeler arasında değişmez. Varsayılan olarak noChange = false
await this.sessionManager.*
Oturumlarla çalışma yöntemleri. Her oturum mutlaka kullanılan proxy'yi ve çerezleri saklar. Ayrıca isteğe bağlı olarak rastgele veriler de kaydedilebilir.
JS veri kazıyıcıda oturumları kullanmak için önce mutlaka Oturum Yöneticisi'ni başlatmanız gerekir. Bu, init() içinde await this.sessionManagerinit() yöntemiyle yapılır
.init(opts?)
Oturum Yöneticisi'nin başlatılması. Argüman olarak ek parametreler içeren bir nesne (opts) iletilebilir (tüm parametreler isteğe bağlıdır):
name- oturumların ait olduğu veri kazıyıcı adını geçersiz kılmaya olanak tanır, varsayılan olarak başlatmanın yapıldığı veri kazıyıcı adına eşittirwaitForSession- veri kazıyıcıya oturum görünene kadar beklemesini söyler (bu, yalnızca birden fazla görev çalışırken geçerlidir; örneğin biri oturum üretir, diğeri onları kullanır), yani.get()ve.reset()her zaman oturumu beklerdomain- bu veri kazıyıcı için kaydedilmiş tüm oturumlar arasından arama yapılmasını belirtir (değer belirtilmemişse) veya yalnızca belirli bir alan adı için arama yapılmasını belirtir (başında nokta olan alan adıyla yazılmalıdır, örneğin.site.com)sessionsKey- oturum deposunun adını elle belirlemeyi sağlar; belirtilmezse ad,name(veyanamebelirtilmemişse veri kazıyıcının adı), alan adı ve proxy denetleyicisi temel alınarak otomatik oluşturulurexpire- oturumun ömür süresini dakika cinsinden belirler, varsayılan olarak sınırsızdır
Kullanım örneği:
async init() {
await this.sessionManager.init({
name: 'JS::test',
expire: 15 * 60
});
}
.get(opts?)
Yeni bir oturum alma, istek gerçekleştirilmeden önce (ilk denemeden önce) çağrılmalıdır. Oturumda saklanan rastgele verileri içeren bir nesne döndürür. Argüman olarak ek parametreler içeren bir nesne (opts) iletilebilir (tüm parametreler isteğe bağlıdır):
waitTimeout- oturumun görünmesi için kaç dakika bekleneceğini belirtme imkânı sağlar,.init()içindekiwaitForSessionparametresinden bağımsız çalışır (onu yoksayar), süre dolduğunda boş bir oturum kullanılırtag- belirtilen etikete sahip oturumu alma, örneğin oturumları alındıkları alan adlarına bağlamak için alan adı kullanılabilir
Kullanım örneği:
await this.sessionManager.get({
waitTimeout: 10,
tag: 'test session'
})
.reset(opts?)
Çerezleri temizleme ve yeni bir oturum alma. Mevcut oturumla istek başarılı olmadıysa kullanılmalıdır. Oturumda saklanan rastgele verileri içeren bir nesne döndürür. Argüman olarak ek parametreler içeren bir nesne (opts) iletilebilir (tüm parametreler isteğe bağlıdır):
waitTimeout- oturumun görünmesi için kaç dakika bekleneceğini belirtme imkânı sağlar,.init()içindekiwaitForSessionparametresinden bağımsız çalışır (onu yoksayar), süre dolduğunda boş bir oturum kullanılırtag- belirtilen etikete sahip oturumu alma, örneğin oturumları alındıkları alan adlarına bağlamak için alan adı kullanılabilir
Kullanım örneği:
await this.sessionManager.reset({
waitTimeout: 5,
tag: 'test session'
})
.save(sessionOpts?, saveOpts?)
Oturumda rastgele verileri saklama imkanıyla başarılı bir oturumu kaydetme. 2 isteğe bağlı argümanı destekler:
sessionOpts- oturumda saklanacak rastgele veriler; sayı, dize, dizi veya nesne olabilirsaveOpts- oturum kaydetme parametrelerini içeren nesne:multiply- isteğe bağlı parametre, oturumu çoğaltmaya olanak tanır, değer olarak bir sayı belirtilmelidirtag- isteğe bağlı parametre, kaydedilen oturum için bir etiket belirler, örneğin oturumları alındıkları alan adlarına bağlamak için alan adı kullanılabilir
Kullanım örneği:
await this.sessionManager.save('some data here', {
multiply: 3,
tag: 'test session'
})
.count()
Mevcut Oturum Yöneticisi için oturum sayısını döndürür
Kullanım örneği:
let sesCount = await this.sessionManager.count();
.removeById(sessionId)
Belirtilen id'ye sahip tüm oturumları siler. Silinen oturum sayısını döndürür. Mevcut oturumun id'si this.sessionId değişkeninde bulunur
Kullanım örneği:
const removedCount = await this.sessionManager.removeById(this.sessionId);
Oturum Yöneticisi kullanımına dair kapsamlı örnek
async init() {
await this.sessionManager.init({
expire: 15 * 60
});
}
async parse(set, results) {
let ses = await this.sessionManager.get();
for(let attempt = 1; attempt <= this.conf.proxyretries; attempt++) {
if(ses)
this.logger.put('Data from session:', ses);
const { success, data } = await this.request('GET', set.query, {}, { attempt });
if(success) {
// process data here
results.success = 1;
break;
} else if(attempt < this.conf.proxyretries) {
const removedCount = await this.sessionManager.removeById(this.sessionId);
this.logger.put(`Removed ${removedCount} bad sessions with id #${this.sessionId}`);
ses = await this.sessionManager.reset();
}
}
if(results.success) {
await this.sessionManager.save('Some data', { multiply: 2 });
this.logger.put(`Total we have ${await this.sessionManager.count()} sessions`);
}
return results;
}

İstek yöntemleri await this.request
GET metodu
İstek parametreleri doğrudan istek dizesinde iletilebilir https://a-parser.com/users/?type=staff:
const { success, data, headers } = await this.request('GET', 'https://a-parser.com/users/?type=staff');
Ya da queryParams içinde nesne olarak, burada key: value param=value'e eşittir:
const { success, data, headers } = await this.request('GET', 'https://a-parser.com/users/', {
type: 'staff'
});
POST metodu
Eğer POST yöntemi kullanılıyorsa, istek gövdesi iki şekilde iletilebilir:
Değişken adlarını ve değerlerini
queryParamsiçinde listeleyin, örneğin:{
"key": set.query,
"id": 1234,
"type": "text"
}Bunları
opts.bodyiçinde listeleyin, örneğin:body: 'key=' + set.query + '&id=1234&type=text'
Eğer istek gövdesi nesne olarak aktarılırsa otomatik olarak form-urlencoded biçimine dönüştürülür; ayrıca body belirtilmiş ve
content-type başlığı belirtilmemişse, otomatik olarak content-type: application/x-www-form-urlencoded atanır:
const { success, data, headers } = await this.request('POST', 'https://jsonplaceholder.typicode.com/posts', {
title: 'foo,',
body: 'bar',
userId: 1
});
Eğer POST isteğinin gövdesi bir dize veya tampon (buffer) ise, olduğu gibi iletilir:
// dize ile istek
const string = 'title=foo&body=bar&userId=1';
const { success, data, headers } = await this.request('POST', 'https://jsonplaceholder.typicode.com/posts', {}, {
body: string
});
// tampon ile istek
const string = 'title=foo&body=bar&userId=1';
const buf = Buffer.from(string, 'utf8');
const { success, data, headers } = await this.request('POST', 'https://jsonplaceholder.typicode.com/posts', {}, {
body: buf
});
Dosya yükleme
form-data modülünü kullanarak POST isteği ile dosya gönderme:
const file = fs.readFileSync('pathToFile');
const FormData = require('form-data');
const format = new FormData();
format.append('file', file, 'fileName.ext');
const { success, data, headers } = await this.request('POST', 'https://file.io', {}, {
headers: format.getHeaders(),
body: format.getBuffer()
});
multipart/form-data içerik türü ile bir POST isteğinde dosya gönderme örneği:
const EOL = '\r\n';
const file = fs.readFileSync('pathToFile');
const boundary = '----WebKitFormBoundary' + String(Math.random()).slice(2);
const requestHeaders = {
'content-type': 'multipart/form-data; boundary=' + boundary
};
const body = '--'
+ boundary
+ EOL
+ 'Content-Disposition: form-data; name="file"; filename="fileName.ext"'
+ EOL
+ 'Content-Type: text/html'
+ EOL
+ EOL
+ file
+ EOL
+ '--'
+ boundary
+ '--';
const { success, data, headers } = await this.request('POST', 'https://file.io', {}, {
headers: requestHeaders,
body
});