我可以简化此代码以避免读取属性的类型错误吗?
Can I simplify this code to avoid the type error for reading properties?
我正在编写这段代码来抓取网页。我需要从网站上获取具体信息,需要抓取的信息很多。
我编写的代码可以工作,但是当重复执行时,某些行会遇到错误,例如第 20 行,第 24 行。
下面是代码
const browser = await puppeteer.launch()
const page = await browser.newPage();
await page.goto("https://startupjobs.asia/job/search?q=&job-list-dpl-page=1", {timeout: 3000000})
const b = (await page.$x("/html/body/div[1]/div[3]/div[1]/div/div[1]/ul/li[1]/div/div[1]/div/h5/a"))[0]
b.click()
//const elm = await page.$('//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[1]/h5');
//const text = await page.evaluate(elm => elm.textContent, elm[0]);
const [el1] = await page.$x('//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[1]/h5');
const job_name = await (await el1.getProperty('textContent')).jsonValue();
const [el2] = await page.$x('//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[2]/div/h6[1]/a');
const company = await (await el2.getProperty('textContent')).jsonValue();
const [el3] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[3]/p');
const job_type= await (await el3.getProperty('textContent')).jsonValue();
const [el4] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[1]/p');
const salary = await (await el4.getProperty('textContent')).jsonValue();
const [el5] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[4]/p');
const skills = await (await el5.getProperty('textContent')).jsonValue();
我需要抓取大约 13 个数据。
我得到的错误是
const salary = await (await el4.getProperty('textContent')).jsonValue();
TypeError: Cannot read properties of undefined (reading 'getProperty')
快速解决方法是在尝试调用 getProperty
之前检查解构的 ElementHandle 是否确实存在,例如:
const [el4] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[1]/p');
const salary = !el4 ? 'Not Found' : await (await el4.getProperty('textContent')).jsonValue();
重复性较低的脚本看起来更像:
const elementsToFind = [
{ xpath: '//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[1]/h5', propName: 'job_name' },
{ xpath: '//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[2]/div/h6[1]/a', propName: 'company' },
// ...
];
const results = {};
for (const { xpath, propName } of elementsToFind) {
const [el] = await page.$x(xpath);
results[propName] = !el ? 'Not Found' : await (await el.getProperty('textContent')).jsonValue();
}
然后遍历 results
对象。
我正在编写这段代码来抓取网页。我需要从网站上获取具体信息,需要抓取的信息很多。
我编写的代码可以工作,但是当重复执行时,某些行会遇到错误,例如第 20 行,第 24 行。
下面是代码
const browser = await puppeteer.launch()
const page = await browser.newPage();
await page.goto("https://startupjobs.asia/job/search?q=&job-list-dpl-page=1", {timeout: 3000000})
const b = (await page.$x("/html/body/div[1]/div[3]/div[1]/div/div[1]/ul/li[1]/div/div[1]/div/h5/a"))[0]
b.click()
//const elm = await page.$('//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[1]/h5');
//const text = await page.evaluate(elm => elm.textContent, elm[0]);
const [el1] = await page.$x('//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[1]/h5');
const job_name = await (await el1.getProperty('textContent')).jsonValue();
const [el2] = await page.$x('//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[2]/div/h6[1]/a');
const company = await (await el2.getProperty('textContent')).jsonValue();
const [el3] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[3]/p');
const job_type= await (await el3.getProperty('textContent')).jsonValue();
const [el4] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[1]/p');
const salary = await (await el4.getProperty('textContent')).jsonValue();
const [el5] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[4]/p');
const skills = await (await el5.getProperty('textContent')).jsonValue();
我需要抓取大约 13 个数据。
我得到的错误是
const salary = await (await el4.getProperty('textContent')).jsonValue(); TypeError: Cannot read properties of undefined (reading 'getProperty')
快速解决方法是在尝试调用 getProperty
之前检查解构的 ElementHandle 是否确实存在,例如:
const [el4] = await page.$x('/html/body/div[1]/div[3]/div[2]/div[2]/div[1]/div[2]/div[1]/div[1]/p');
const salary = !el4 ? 'Not Found' : await (await el4.getProperty('textContent')).jsonValue();
重复性较低的脚本看起来更像:
const elementsToFind = [
{ xpath: '//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[1]/h5', propName: 'job_name' },
{ xpath: '//*[@id="suj-single-jobdetail-wrapper"]/div[1]/div[2]/div/h6[1]/a', propName: 'company' },
// ...
];
const results = {};
for (const { xpath, propName } of elementsToFind) {
const [el] = await page.$x(xpath);
results[propName] = !el ? 'Not Found' : await (await el.getProperty('textContent')).jsonValue();
}
然后遍历 results
对象。