【问题标题】:Issues with request, and cheerio when web-scraping网络抓取时的请求问题和欢呼
【发布时间】:2019-10-21 00:12:37
【问题描述】:

我正在尝试编写一个向网站发出请求的代码,用于网页抓取

步骤如下:

代码的第一部分开始

  1. 程序向 ma​​inURL 发出请求
  2. 程序从 ma​​inURL 的 html 中选择一些对象,并将它们存储在对象数组(广告)中,在对象的属性中,它是链接,我们将调用numberURL,代码使用css选择器自动选择,对象的数量大概是80-90;
  3. 程序向每个 numberURL(80-90 个请求)发出请求, 并且对于它们中的每一个,它确实为同一个对象设置了另一个属性,并选择了另一个链接,我们称之为 accountURL
  4. 程序会创建一个 CSV 文件,将每个对象写入不同的行中

此处第一部分代码结束

所以实际上第一部分效果很好,没有任何问题,但是第二部分有

代码的第二部分开始

  1. 程序从前一个对象向每个 accountURL 发出请求
  2. 程序从 accountURL 的 html 中选择一些对象,并将它们存储在另一个对象(帐户)的另一个数组中,同样使用 CSS 选择器
  3. 程序应该 console.log() 所有 account 对象

此处代码的第二部分结束

但是第二部分确实有一些错误,因为当 console.logging 对象时,我们看到对象属性没有改变它们的默认值。

因此,出于调试目的,我采用了一个广告对象并从代码中手动输入它的值

post[0].link = 'https://999.md/ru/profile/denisserj'

最后,当运行这个对象的代码时,它实际上可以正常工作,所以它显示了更改的属性,但对于其余的则没有。

我尝试设置一些超时,认为代码在第二个请求完成之前尝试读取链接,但没有效果

我也试过console.log这个链接,看它是否存在于数组中,所以它确实存在那里,但也没有效果。

最后是代码:

// CLASSES
class advert {
    constructor() {
        this.id = 0;
        this.tile = new String();
        this.link = new String();
        this.phone = new String();
        this.account = new String();
        this.accountLink = new String();
        this.text = new String();
        this.operator = new String();
    }
    show() {
        console.log(this.id, this.title, this.link, this.phone, this.account, this.accountLink, this.text, this.operator);
    }

}
class account {
    constructor() {
        this.name = 0;
        this.createdAt = 0;
        this.phone = [];
        this.ads = [];
        this.adsNumber = 0;
    }
    show() {
        console.log(this.name, this.createdAt, this.phone, this.ads, this.adsNumber);
    }
}

// HEADERS
const mainRequest = require('request');
const auxRequest = require('request');
const cheerio1 = require('cheerio');
const cheerio2 = require('cheerio');
const fs = require('fs');
const fs2 = require('fs');
const adFile = fs.createWriteStream('anunturi.csv');
const accFile = fs2.createWriteStream('conturi.csv');

// SETTINGS
const host = 'https://999.md'
const category = 'https://999.md/ru/list/transport/cars'
const timeLimit = 60; //seconds

// VARIABLES
let post = [];
let postNumber = 0;
let acc = [];

// FUNCTIONS
function deleteFromArray(j) {
    post.splice(j, 1);
}

function number(i) {
    let category = post[i].link;
    auxRequest(category, (error, response, html) => {
        if (!error && response.statusCode == 200) {
            const $ = cheerio1.load(html);
            let phone;
            const siteTitle = $('strong').each((id, el) => {
                phone = $(el).text();
            });
            const txt = $('.adPage__content__description').html();
            const person = $('.adPage__header__stats').find('.adPage__header__stats__owner').text();
            const linkToPerson = host + $('.adPage__header__stats').find('.adPage__header__stats__owner').find('a').attr('href');
            post[i].phone = phone;
            post[i].account = person;
            post[i].accountLink = linkToPerson;
            post[i].text = txt;
            if (i == postNumber) {
                console.log('1. Number Putting done')
                writeToFileAd(accountPutter, writeToFileAccount);
            }
        }

    });
}

function writeToFileAd() {
    adFile.write('ID, Titlu, Link, Text, Cont, LinkCont, Operator\n')
    for (let i = 0; i <= postNumber; i++) {
        adFile.write(`${post[i].id}, ${post[i].title}, ${post[i].link}, ${post[i].phone}, ${post[i].account}, ${post[i].accountLink}, ${post[i].operator}\n`);
    }
    console.log('2. Write To File Ad done')
    accountPutter();
}

function accountAnalyzis(i) {
    let category = post[i].link;
    const mainRequest = require('request');
    category = category.replace('/ru/', '/ro/');
    mainRequest(category, (error, response, html) => {

        if (!error && response.statusCode == 200) {
            const $ = cheerio2.load(html);
            const name = $('.user-profile__sidebar-info__main-wrapper').find('.login-wrapper').text();
            let createdAt = $('.date-registration').text();
            createdAt = createdAt.replace('Pe site din ', '');
            const phones = $('.user-profile__info__data').find('dd').each((id, el) => {
                let phone = $(el).text();
                acc[i].phone.push(phone);
            });
            const ads = $('.profile-ads-list-photo-item-title').find('a').each((id, el) => {
                let ad = host + $(el).attr('href');
                acc[i].ads.push(ad);
                acc[i].adsNumber++;
            });
            acc[i].name = name;
            acc[i].createdAt = createdAt;
            console.log(name)
            if (i == postNumber) {
                console.log('3. Account Putting done')
                writeToFileAccount();
            }
        }
    });
}

function writeToFileAccount() {
    for (let i = 0; i <= postNumber; i++) {
        accFile.write(`${acc[i].name}, ${acc[i].createdAt}, ${acc[i].phone}, ${acc[i].ads}, ${acc[i].adsNumber}\n`);
    }
    console.log('4. Write to file Account done');
}

function numberPutter() {
    for (let i = 0; i <= postNumber; i++) {
        number(i);
    }
}

function accountPutter() {
    for (let i = 0; i <= postNumber; i++) {
        accountAnalyzis(i);
    }
}

// MAIN
mainRequest(category, (error, response, html) => {
    let links = [];
    for (let i = 0; i < 1000; i++) {
        post[i] = new advert();
    }
    for (let i = 0; i < 1000; i++) {
        acc[i] = new account();
    }
    if (!error && response.statusCode == 200) {
        const $ = cheerio2.load(html);
        const siteTitle = $('.ads-list-photo-item-title').each((id, el) => {
            const ref = host + $(el).children().attr('href');
            const title = $(el).text();
            post[id].id = id + 1;
            post[id].title = title;
            post[id].link = ref;
            links[id] = ref;
            postNumber = id;
        });
        post[0].link = 'https://999.md/ru/profile/denisserj'
        numberPutter()
    }

});

【问题讨论】:

  • 你真的需要处理你的最小工作示例

标签: javascript node.js web-scraping request cheerio


【解决方案1】:

你有一行错误

const siteTitle = $('.ads-list-photo-item-title').each((id, el) => {

你真正想要的是.find('a').each...

【讨论】:

  • 是的,但 id 不会改变结果
  • 你应该调试它(我不能)。也不要创建 for (let i = 0; i &lt; 1000; i++) { post[i] = new advert(); } - 创建并将其推送到 each 函数中 - 这样您就会看到找到了多少实际链接。
  • 没用,我试着把它们放在构造函数中,也没有用
  • 主要问题是,对于 post[0],我在代码中手动编写的那个链接,代码完成了他的工作,但对于其余的则没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
相关资源
最近更新 更多