Я использую axios для отправки запроса на получение в Google Scholar. С cheerio я получаю доступ к данным. Когда название слишком длинное, я получаю: заголовок: «Сравнение дефектов при рождении живым после стимуляции яичников в лютеиновой фазе и обычной стимуляции яичников для экстракорпорального оплодотворения и переноса витрифицированных эмбрионов…».
Это код:
const free_proxy_url1 = "https://free-proxy-list.net";
request(free_proxy_url1, (err, response, body) => {
let $ = cheerio.load(body);
let ipResults = [];
$(".table-responsive > div > table > tbody > tr").each(
(i, el) => {
if ($(el).find("td:nth-child(7)").text() === "yes")
ipResults.push({
ip: $(el).find("td:nth-child(1)").text(),
port: Number($(el).find("td:nth-child(2)").text()),
https: $(el).find("td:nth-child(7)").text(),
});
}
);
let rand = Math.floor(Math.random() * ipResults.length);
let searchTerm = "AI";
const proxy = {
host: ipResults[rand].ip,
port: ipResults[rand].port,
};
axios
.get(
`https://scholar.google.com/scholar?q=${searchTerm}`,
proxy
)
.then(result => {
const $ = cheerio.load(result.data);
$("div.gs_ri").each((i, el) => {
const yearElement = $(el).find("div.gs_a");
const yearText = yearElement.text().match(/\d{4}/);
const titleElement = $(el).find("h3.gs_rt a");
scholar_results.push({
title: titleElement.text().trim(),
link: $(el).find(".gs_rt a").attr("href"),
year: yearText ? parseInt(yearText[0]) : null,
});
});
})
.catch(err => {
console.info(err);
});
});
Есть ли способ получить полное название, а не усеченное?
Заголовки отсутствуют на запрашиваемом вами статическом сайте. Они могут быть в другом месте в Google Scholar, или вы можете попробовать проанализировать их из произвольного HTML для каждого URL-адреса статьи. Кстати, я не думаю, что ваш прокси применяется правильно. Думаю так и должно быть axios.get(url, {proxy: {host: "xxxx", port: 80}})
.
Это немного сложно. Полного названия нет нигде в статическом HTML, поэтому, похоже, вам нужно перейти по ссылке на внешний сайт для каждой статьи, а затем попытаться угадать, что это за заголовок.
Вот пример:
const axios = require("axios");
const cheerio = require("cheerio"); // 1.0.0-rc.12
const ua =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36";
const normalizeText = s =>
s.toLowerCase()
.replace(/[^a-z]/g, " ")
.replace(/\s+/, " ")
.trim();
const tryFindingFullTitle = async (title, link) => {
const normalizedTitle = normalizeText(title);
try {
const {data} = await axios.get(link, {headers: {"User-Agent": ua}});
const $ = cheerio.load(data);
return [...$("*")]
.flatMap(e =>
[...$(e).contents()].filter(e => e.type === "text")
)
.map(e => $(e).text().trim())
.filter(Boolean)
.find(e => normalizeText(e).startsWith(normalizedTitle));
}
catch (err) {
return title;
}
};
const runSearch = async searchTerm => {
const url = `https://scholar.google.com/scholar?q=${encodeURI(searchTerm)}`;
const {data} = await axios.get(url, {headers: {"User-Agent": ua}});
const $ = cheerio.load(data);
const result = [];
for (const el of [...$("div.gs_ri")]) {
const link = $(el).find(".gs_rt a").attr("href");
const year = $(el).find("div.gs_a").text().match(/\d{4}/);
const title = $(el).find("h3.gs_rt a").text().trim();
result.push({
title: title.includes("…") ?
await tryFindingFullTitle(title, link) : title,
link,
year: year ? parseInt(year[0]) : null,
});
}
return result;
};
runSearch("AI")
.then(result => console.info(result))
.catch(err => console.error(err.message));
Основная часть работы — это tryFindingFullTitle
, который берет сокращенный заголовок и URL-адрес, переходит к URL-адресу и пытается найти первый элемент с текстовым содержимым, который имеет сокращенный заголовок в качестве префикса. Другой подход может состоять в том, чтобы найти текст с наименьшим расстоянием Левенштейна.
Это работает нормально для нескольких списков ScienceDirect в тестовом образце, но, вероятно, потерпит неудачу в других случаях, так что считайте это доказательством концепции. Я не знаком с этим сайтом, поэтому вполне возможно, что он полностью доступен в предсказуемом формате на другой странице Академии Google.
Кстати, ваш прокси, похоже, неправильно добавлен в вызов axios.get
. Я думаю, что это должно быть что-то вроде:
axios.get(url, {proxy: {host: "xxxx", port: 80}})
Я редактирую его с полной функцией запроса, которую использую для получения прокси. Вы также можете запустить его без прокси-объекта, если хотите.