如何使用Cheerio从Google Scholar获得标题的全文?



我使用axios在google scholar上发送get请求。我用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.log(err);
});
});

是否有办法获得完整的标题,而不是截断的一个?

这有点棘手。完整的标题似乎没有在静态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.log(result))
.catch(err => console.error(err.message));

大部分工作是tryFindingFullTitle,它接受缩写标题和URL,导航到URL并尝试查找具有缩写标题作为前缀的文本内容的第一个元素。另一种方法可能是找到具有最小Levenstein距离的文本。

这在样本测试中的几个ScienceDirect列表上工作得很好,但在其他情况下可能会失败,因此将其视为概念证明。我对这个网站不熟悉,所以完全有可能在另一个Google Scholar页面上以可预测的格式提供完整的内容。

顺便说一下,您的代理似乎没有正确地添加到axios.get调用中。我觉得应该是这样的:
axios.get(url, {proxy: {host: "xxxx", port: 80}})

最新更新