用 puppeteer 抓取字典网站
scraping a dictionary website with puppeteer
我正在尝试抓取一个字典网站(这个“http://rjecnik.hr/”),其中包含所有字母中的所有单词。设法做到了部分。我设法遍历页面,但无法实现遍历每个字母然后将该信息保存在文档中。在整个互联网上搜索,只是看不到我的问题的解决方案。补充一点,我是编程的初学者,还在学习东西。可能是一个我看不到的简单解决方案。
这是代码,也不是我自己写的代码,但是我能理解每一部分的作用。
// Browser
const puppeteer = require('puppeteer');
// funkcija se odnosi na puppeteer
(async () => {
// Izvlačenje riječi sa stranice, pomoću rekurzije provjerit iduće stranice.
const izvuciRijeci = async (url) =>
{
// Izvlačenje (Scraping) podataka koje želimo. // Scraping data we want.
const page = await browser.newPage()
await page.goto(url)
//console.log(`Scraping: ${url}`); // Debugging
const rijeciNaStranici = await page.evaluate(() => Array.from(document.querySelectorAll('.word')).map((rijeci) => rijeci.innerText.trim())); // Getting the words from a page.
await page.close();
// Provjera iduće stranice pomoću rekurzije. // Checkin next page using recursion.
if (rijeciNaStranici.length < 1)
{
// Prekidanje ako nema riječi. // Stop if no more words.
//console.log (`Terminate recursion on: ${url}`) // Debugging
return rijeciNaStranici
}
else
{
// Dohvati iduću stranicu načinom "?page=X+1". // Get next page using "?page=X+1".
const nextPageNumber = parseInt(url.match(/page=(\d+)$/)[1], 10) + 1;
const nextUrl = `http://rjecnik.hr/?letter=a&page=${nextPageNumber}`;
return rijeciNaStranici.concat(await izvuciRijeci(nextUrl))
}
}
const browser = await puppeteer.launch();
const url = "http://rjecnik.hr/?letter=a&page=1";
const rijec = await izvuciRijeci(url);
// Todo: Ažurirati bazu s riječima
console.log(rijec);
// Spremanje u datoteku. // Save to file.
const content = rijec.toString();
var fs = require('fs');
fs.writeFile("rijeci.txt", content, function (err){
if (err) {
console.log(err);
} else {
console.log("File saved");
}
});
await browser.close();
})();
如果您认为此解决方案有用且有帮助,请select将其作为正确答案。
首先,您不需要在每次加载新内容时都打开和关闭页面 URL。
当浏览器启动时,您可以简单地使用已经打开的页面。
// const page = await page.newPage() // <= this is also not efficient enough
// await page.close() // <= this is unnecessary and way too heavy
// == You can use these method instead
const page = (await browser.pages())[0] // <= this way is lot better and lighter
然后您需要在一个数组中列出所有可用的字母:
const getLettersArray = async (url) => {
const page = (await browser.pages())[0] // Use the first page already opened, to keep it light
await page.goto(url)
return await page.evaluate(() => Array.from(document.querySelectorAll('.alphabet ul > li')).map(element => element.innerText))
}
然后要定义 selected 或活动字母,您可以使用如下正则表达式进行检查,(注意:由于字典使用了一些 non-English QWERTY 字符,我添加了 {1.6}
在参数中)
const letterInUse = url.match(/letter=(.{1,6})&page=(\d+)$/)[1] // Get the letter used in the page
我添加了更多方法,因此您可以 运行 下面这个完整的功能脚本:
// Browser
const puppeteer = require('puppeteer')
const fs = require('fs')
// funkcija se odnosi na puppeteer
;(async () => {
const getLettersArray = async (url) => {
const page = (await browser.pages())[0] // Use the first page already opened, to keep it light
await page.goto(url)
return await page.evaluate(() => Array.from(document.querySelectorAll('.alphabet ul > li')).map(element => element.innerText))
}
// Izvlačenje riječi sa stranice, pomoću rekurzije provjerit iduće stranice.
const izvuciRijeci = async (url, allLetters) => {
// Izvlačenje (Scraping) podataka koje želimo. // Scraping data we want.
const page = (await browser.pages())[0] // Use the first page already opened, to keep it light
await page.goto(url)
//console.log(`Scraping: ${url}`); // Debugging
const rijeciNaStranici = await page.evaluate(() => Array.from(document.querySelectorAll('.word')).map((rijeci) => rijeci.innerText.trim())) // Getting the words from a page.
// await page.close() // Don't close page when it can be reused for efficiency and effectivity
// Provjera iduće stranice pomoću rekurzije. // Checkin next page using recursion.
if (rijeciNaStranici.length < 1) {
// Prekidanje ako nema riječi. // Stop if no more words.
// console.log (`Terminate recursion on: ${url}`) // Debugging
return rijeciNaStranici
} else {
// Dohvati iduću stranicu načinom "?page=X+1". // Get next page using "?page=X+1".
const nextPageNumber = parseInt(url.match(/page=(\d+)$/)[1], 10) + 1
const letterInUse = url.match(/letter=(.{1,6})&page=(\d+)$/)[1] // Get the letter used in the page
const letterIndexed = allLetters.findIndex(value => value === letterInUse.toUpperCase()) + 1
if (letterIndexed > allLetters.length) {
return []
}
const nextLetter = allLetters.at(letterIndexed) // Get the next letter after this letter
const nextLetterUrl = `http://rjecnik.hr/?letter=${nextLetter}&page=1`
const nextUrl = `http://rjecnik.hr/?letter=${letterInUse}&page=${nextPageNumber}`
const nextPageArray = await izvuciRijeci(nextUrl, allLetters)
if (nextPageArray.length) {
return rijeciNaStranici.concat(nextPageArray)
} else {
const nextLetterArray = await izvuciRijeci(nextLetterUrl, allLetters)
return rijeciNaStranici.concat(nextLetterArray)
}
}
}
const browser = await puppeteer.launch({headless: true})
const url = "http://rjecnik.hr/?letter=a&page=1"
const allLetters = await getLettersArray(url)
const rijec = await izvuciRijeci(url, allLetters)
// Todo: Ažurirati bazu s riječima
console.log(rijec)
// Spremanje u datoteku. // Save to file.
const content = rijec.toString()
fs.writeFile('rijeci.txt', content, function (error) {
if (error) {
console.log(error)
} else {
console.log('File saved')
}
});
await browser.close()
})()
我正在尝试抓取一个字典网站(这个“http://rjecnik.hr/”),其中包含所有字母中的所有单词。设法做到了部分。我设法遍历页面,但无法实现遍历每个字母然后将该信息保存在文档中。在整个互联网上搜索,只是看不到我的问题的解决方案。补充一点,我是编程的初学者,还在学习东西。可能是一个我看不到的简单解决方案。 这是代码,也不是我自己写的代码,但是我能理解每一部分的作用。
// Browser
const puppeteer = require('puppeteer');
// funkcija se odnosi na puppeteer
(async () => {
// Izvlačenje riječi sa stranice, pomoću rekurzije provjerit iduće stranice.
const izvuciRijeci = async (url) =>
{
// Izvlačenje (Scraping) podataka koje želimo. // Scraping data we want.
const page = await browser.newPage()
await page.goto(url)
//console.log(`Scraping: ${url}`); // Debugging
const rijeciNaStranici = await page.evaluate(() => Array.from(document.querySelectorAll('.word')).map((rijeci) => rijeci.innerText.trim())); // Getting the words from a page.
await page.close();
// Provjera iduće stranice pomoću rekurzije. // Checkin next page using recursion.
if (rijeciNaStranici.length < 1)
{
// Prekidanje ako nema riječi. // Stop if no more words.
//console.log (`Terminate recursion on: ${url}`) // Debugging
return rijeciNaStranici
}
else
{
// Dohvati iduću stranicu načinom "?page=X+1". // Get next page using "?page=X+1".
const nextPageNumber = parseInt(url.match(/page=(\d+)$/)[1], 10) + 1;
const nextUrl = `http://rjecnik.hr/?letter=a&page=${nextPageNumber}`;
return rijeciNaStranici.concat(await izvuciRijeci(nextUrl))
}
}
const browser = await puppeteer.launch();
const url = "http://rjecnik.hr/?letter=a&page=1";
const rijec = await izvuciRijeci(url);
// Todo: Ažurirati bazu s riječima
console.log(rijec);
// Spremanje u datoteku. // Save to file.
const content = rijec.toString();
var fs = require('fs');
fs.writeFile("rijeci.txt", content, function (err){
if (err) {
console.log(err);
} else {
console.log("File saved");
}
});
await browser.close();
})();
如果您认为此解决方案有用且有帮助,请select将其作为正确答案。
首先,您不需要在每次加载新内容时都打开和关闭页面 URL。
当浏览器启动时,您可以简单地使用已经打开的页面。
// const page = await page.newPage() // <= this is also not efficient enough
// await page.close() // <= this is unnecessary and way too heavy
// == You can use these method instead
const page = (await browser.pages())[0] // <= this way is lot better and lighter
然后您需要在一个数组中列出所有可用的字母:
const getLettersArray = async (url) => {
const page = (await browser.pages())[0] // Use the first page already opened, to keep it light
await page.goto(url)
return await page.evaluate(() => Array.from(document.querySelectorAll('.alphabet ul > li')).map(element => element.innerText))
}
然后要定义 selected 或活动字母,您可以使用如下正则表达式进行检查,(注意:由于字典使用了一些 non-English QWERTY 字符,我添加了 {1.6}
在参数中)
const letterInUse = url.match(/letter=(.{1,6})&page=(\d+)$/)[1] // Get the letter used in the page
我添加了更多方法,因此您可以 运行 下面这个完整的功能脚本:
// Browser
const puppeteer = require('puppeteer')
const fs = require('fs')
// funkcija se odnosi na puppeteer
;(async () => {
const getLettersArray = async (url) => {
const page = (await browser.pages())[0] // Use the first page already opened, to keep it light
await page.goto(url)
return await page.evaluate(() => Array.from(document.querySelectorAll('.alphabet ul > li')).map(element => element.innerText))
}
// Izvlačenje riječi sa stranice, pomoću rekurzije provjerit iduće stranice.
const izvuciRijeci = async (url, allLetters) => {
// Izvlačenje (Scraping) podataka koje želimo. // Scraping data we want.
const page = (await browser.pages())[0] // Use the first page already opened, to keep it light
await page.goto(url)
//console.log(`Scraping: ${url}`); // Debugging
const rijeciNaStranici = await page.evaluate(() => Array.from(document.querySelectorAll('.word')).map((rijeci) => rijeci.innerText.trim())) // Getting the words from a page.
// await page.close() // Don't close page when it can be reused for efficiency and effectivity
// Provjera iduće stranice pomoću rekurzije. // Checkin next page using recursion.
if (rijeciNaStranici.length < 1) {
// Prekidanje ako nema riječi. // Stop if no more words.
// console.log (`Terminate recursion on: ${url}`) // Debugging
return rijeciNaStranici
} else {
// Dohvati iduću stranicu načinom "?page=X+1". // Get next page using "?page=X+1".
const nextPageNumber = parseInt(url.match(/page=(\d+)$/)[1], 10) + 1
const letterInUse = url.match(/letter=(.{1,6})&page=(\d+)$/)[1] // Get the letter used in the page
const letterIndexed = allLetters.findIndex(value => value === letterInUse.toUpperCase()) + 1
if (letterIndexed > allLetters.length) {
return []
}
const nextLetter = allLetters.at(letterIndexed) // Get the next letter after this letter
const nextLetterUrl = `http://rjecnik.hr/?letter=${nextLetter}&page=1`
const nextUrl = `http://rjecnik.hr/?letter=${letterInUse}&page=${nextPageNumber}`
const nextPageArray = await izvuciRijeci(nextUrl, allLetters)
if (nextPageArray.length) {
return rijeciNaStranici.concat(nextPageArray)
} else {
const nextLetterArray = await izvuciRijeci(nextLetterUrl, allLetters)
return rijeciNaStranici.concat(nextLetterArray)
}
}
}
const browser = await puppeteer.launch({headless: true})
const url = "http://rjecnik.hr/?letter=a&page=1"
const allLetters = await getLettersArray(url)
const rijec = await izvuciRijeci(url, allLetters)
// Todo: Ažurirati bazu s riječima
console.log(rijec)
// Spremanje u datoteku. // Save to file.
const content = rijec.toString()
fs.writeFile('rijeci.txt', content, function (error) {
if (error) {
console.log(error)
} else {
console.log('File saved')
}
});
await browser.close()
})()