#javascript #asynchronous #web-scraping #async-await #axios
#javascript #асинхронный #очистка веб-страниц #async-ожидание #axios
Вопрос:
Я использую Axios для извлечения данных продукта в формате JSON с веб-сайта. Приведенный ниже скрипт сначала запрашивает данные категории с сервера и перебирает три иерархии категорий, подкатегорий и (я предполагаю) подразделов. В третьем цикле параметр запроса вложенных подкатегорий используется в качестве параметра в вызове функции, который вызывает асинхронную функцию, которая использует этот параметр запроса для объединения с URL-адресом для создания нового URL-адреса, выполняет запрос GET для данных продукта, связанных с параметром запроса, и выполняет цикл до тех пор, пока переменная итерации pageCounter (которая используется в качестве параметра запроса разбивки на страницы, чтобы получить N страниц для каждого нового URL-адреса) не станет равной значению разбивки на страницы в текущем новом URL-адресе, содержащем вложенный URL-адрес. параметр запроса подкатегории.
for (let i=0; i<obj.length; i ) {
let subcats = obj[i].subcategories.length;
for(let n=0; n<subcats; n ) {
if(obj[i].subcategories[n].facetValueData) {
let subsubcats = obj[i].subcategories[n].facetValueData.length
for(let p=0; p<subsubcats; p ) {
let productData = []
obj[i].subcategories[n].facetValueData[p].productData = productData
const scrapedData = await scrapeData(obj[i].subcategories[n].facetValueData.code)
obj[i].subcategories[n].facetValueData[p].productData.push(scrapedData)
}
} else {
console.log(`No facet values present - ${obj[i].subcategories[n]}`)
}
}
}
Это асинхронная функция, вызываемая третьим циклом
async function scrapeData(queryParam) {
var product = []
var pagination;
try {
do {
var nextPageLink = `currentPage=${pageCounter}amp;query=::cagCollectionPoint:Departure from Singapore:cagCategory:${queryParam}`
var nextUrl = url.concat(nextPageLink)
const response = await axios({
method: "GET",
url: nextUrl,
withCredentials: true,
headers: headers
})
product = response.data["products"]
pagination = response.data["pagination"]["totalPages"]
pageCounter ;
//this logs all of the correct current queries
console.log(response.data.currentQuery.query.value)
} while (pageCounter<=pagination)
return product
} catch (error) {
console.error(error)
}
}
На первый взгляд кажется, что он работает, поскольку он заполняет первые несколько объектов подкатегории массивом очищенных продуктов, однако некоторые из них не заполнены, т.Е. productData = []
Функция console log в функции scrapeData возвращает все правильные текущие запросы за итерацию, однако, когда они возвращаются, она возвращает только первые несколько ответов.
Я предполагаю, что массиву product нужно подождать? Но запрос axios уже ожидается, поэтому я не понимаю, почему это происходит.
Ответ №1:
Если я правильно понимаю ваше намерение относительно этого фрагмента кода:
var product = [];
do {
// ...
const response = await axios(/* ... */);
product = response.data["products"]
// ...
} while (pageCounter<=1)
return product
похоже, что существует несколько страниц, и вы хотите поместить их все в массив product?
Но на самом деле на каждой странице вы заменяете массив product. Я бы предположил, что на пустых циклах ваша последняя выборка не дает результатов, и вы просто теряете все остальные из них.
Что вы, вероятно, хотите сделать, это просто изменить product = response.data["products"]
на:
product.push(...response.data["products"])
Комментарии:
1. Спасибо, я изменил свой код, как вы предложили, однако проблема все еще сохраняется, и только первые несколько (6, если быть точным, из 60) фактически добавляются в виде массивов к объекту json
2. откуда
pageCounter
берется? Моим первым предположением было бы то, что вы никогда не сбрасываете его обратно на ноль при переключении продуктов. Далее мне интересно, что происходит с вложенными циклами в функции, и когда вы вызываете эту функцию, выawait
это делаете?3. Спасибо, это был счетчик страниц, я вызывал его вне функции, спасибо, что прояснили это, мой мозг плавился от этого