Получить информацию со страницы лома с Cheerio - PullRequest
0 голосов
/ 07 ноября 2019

Я работаю над веб-сервером Node, реализованным с помощью Puppeteer и Cheerio.

У меня есть приложение React, использующее Soundcloud-widget для воспроизведения музыки, но дело в том, что API работает только с правильнымSoundcloud URL.

Итак, я делаю ввод с пользовательского интерфейса, чтобы отправить запрос на поиск SoundCloud через Scraper и получить оттуда результаты.

Поскольку все, что меня волнует, это URL иназвание песни, полученное из записки


$(a.soundTitle__title)

, которая содержит имя в дочернем теге span (в его атрибуте "class") и URL-адрес как href, этого достаточно.

Проблема в том, что я получаю


{
 options: {
  withDomLvl1: true,
  normalizeWhitespace: false,
  xml: false,
  decodeEntities: true
},
length: 0,
prevObject: {
  options: {
   withDomLvl1: true,
   normalizeWhitespace: false,
   xml: false,
   decodeEntities: true
  }
 }
}

, который является выводом cheerio по умолчанию для имени диапазона / песни и "undefined" для URL-адреса href.

, даже когда я пытаюсь использовать {.text () / .attr ("class") / etc ...}, resp - undefind / этот текст ответа / ошибки по умолчанию () не является функцией

это мой код -


... req

const addaptReq = req.text.replace(' ', '%20');  
const url = `https://soundcloud.com/search?q=${addaptReq}`;

let myBrowser;

puppeteer
 .launch()
 .then(browser => {
     myBrowser = browser;
     return myBrowser.newPage();
   })
 .then(page => {
     return page.goto(url).then(() => {
         return page.content();
      });
  })
 .then(html => {
      // console.log(html)
      $('a.soundTitle__title', html, ).each(result => {
        let songName = $('span', result)
        let songURL = $(result).attr('href')

        //  hopefuly name will give the span text (which is it class and href the URL)


          console.log(songName, songURL)

      })
   }).then(() => {
       myBrowser.close()
   })
  .catch(err => {
      console.log(err);
   });

Я прилагаю скриншот soundcloudс devtools, может я что-то там не так делаю?

спасибо заранее!

soundcloud screenshot

1 Ответ

0 голосов
/ 09 ноября 2019
  1. Вы не можете использовать cheerio для сканирования веб-приложения, такого как Soundcloud, так как этот веб-сайт в значительной степени работает по Javascript и XHR JSON Request (AJAX). Рекомендуемая альтернатива: PUPPETEER, потому что этот безголовый браузер может запускать практически любой Javascript (это просто Chrome без GUI и с некоторыми ограничениями, конечно).

  2. Генерация заголовка Soundcloud ТОЛЬКО производится при прокрутке страницы, поэтому вам нужна функция автопрокрутки, запускаемая с setInterval каждый раз.

  3. Вы можете запросить результаты, выбрав селектор или прослушав событие запроса страницы, и «шпионя» за результатами,Я предпочитаю выбирать второй, потому что он работает гладко, без какого-либо селектора.

  4. Поскольку вам нужны только URL-адреса и названия песен, я создал этот скрипт. Попробуйте и измените по своему усмотрению.

  5. Вы можете изменить поисковый запрос и максимальные результаты в верхних кодах. Даже вы можете запустить этот скрипт с поисковым запросом в качестве аргумента. Например: $ node search_soundcloud.js "iris goo goo dolls". Если вы не передадите аргумент здесь, он будет искать "goo goo dolls" в качестве сценария по умолчанию.

const puppeteer = require ('puppeteer')

;(async () => {
    const input = process.argv.length < 3 ? 'goo goo dolls' : process.argv[2]
    const maximumSongs = 100
    const titlesArray = []
    const searchquery = input.split(' ').join('%20')
    const url = `https://soundcloud.com/search?q=${searchquery}`

    const browser = await puppeteer.launch({
        headless: true,
        devtools: false
    })
    const [page] = await browser.pages()
    page.setDefaultNavigationTimeout(0)

    page.setRequestInterception(true)

    page.on('request', async request => {
        if (request.resourceType() === 'font' ||
            request.resourceType() === 'image' ||
            request.resourceType() === 'media' ){
            request.abort()
        } else {
            request.continue()
        }
    })

    page.on('requestfinished', async request => {
        if ( request.url().search('https://api-v2.soundcloud.com/search?') > -1 ) {
            const response = await request.response()
            const content = await response.json()
            const songs = content.collection
            for ( let num in songs ) {
                if (titlesArray.length < 100 && typeof songs[num].title !== 'undefined') {
                    console.log ( `[${titlesArray.length + 1}]  ${songs[num].title}` )
                    console.log ( `${songs[num].permalink_url}\n` )
                    titlesArray.push ( songs[num].title )
                } else if (typeof songs[num].title !== 'undefined') {
                    const exit = await browser.close()
                }
            }
        }
    })

    const search = await page.goto(url, {waitUntil: 'networkidle2'})

    const scroll = await page.evaluate ('const autoscroll = setInterval( () => {window.scrollBy(0,100)}, 250)')

})()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...