Javascript 用木偶手刮网+;Next.js和Express

Javascript 用木偶手刮网+;Next.js和Express,javascript,web-scraping,puppeteer,next.js,Javascript,Web Scraping,Puppeteer,Next.js,试图找出我的scrape函数运行两次的原因。我正试图创建一个SSR应用程序,点击一个网站并抓取数据。它确实可以工作并正确地获取我需要的数据,但我将headless设置为false,我可以看到浏览器正确打开,然后再次打开并搜索术语[object] 我需要它只在服务器上运行,这就是为什么我选择了express+next.js组合 server.js const express = require("express"); const next = require("next"); const scra

试图找出我的scrape函数运行两次的原因。我正试图创建一个SSR应用程序,点击一个网站并抓取数据。它确实可以工作并正确地获取我需要的数据,但我将headless设置为false,我可以看到浏览器正确打开,然后再次打开并搜索术语
[object]

我需要它只在服务器上运行,这就是为什么我选择了express+next.js组合

server.js

const express = require("express");
const next = require("next");
const scraper = require("./utils/scraper");

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== "production";
const nextApp = next({ dev });
const nextHandle = nextApp.getRequestHandler();

nextApp.prepare().then(() => {
  const server = express();

  server.get("/search/:query", async (req, res) => {
    const { query } = req.params;

    const listings = await scraper.scrape(query);

    return nextApp.render(req, res, "/search", { search: query, listings });
  });

  server.get("*", (req, res) => {
    return nextHandle(req, res);
  });

  server.listen(port, err => {
    if (err) {
      throw err;
    }
    console.log(`> Ready on http://localhost:${port}`);
  });
});
scraper.js

const puppeteer = require("puppeteer");

const scrape = async term => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto(`https://...&query=${term}`);

  const scrapedData = await page.evaluate(() => {
    const items = document.querySelectorAll(".results");
    return Array.from(items).map(listing => {
      return { ... build up my obj here };
    });
  });

  await browser.close();
  return scrapedData;
};

module.exports.scrape = scrape;
Search.jsx(下一个.js页面)

import React,{Component}来自“React”;
导出默认类扩展组件{
静态异步getInitialProps(ctx){
返回{
搜索:ctx.query.search,
清单:ctx.query.listings
};
}
render(){
const{search,listings}=this.props;
日志(列表,“客户端”);
返回(
{搜索}搜索!
{…listings.map()}
);
}
}
更新1
我注意到,如果我不将我的
列表
数组传递到
nextap.render
并在服务器上注销结果,那么傀儡玩家只能正确打开一次。但是,当我将它传递到页面to
getInitialProps
时,我就体验到了如上所述的双重加载。

为什么不直接使用
server.get(“/search/:query”),async(req,res)=>{
然后只是
const scraped=wait scraper.scrape(query)
scraper.scraper(query)。然后(…)
?我用你的简化建议更新了我的代码。没有区别。如果你在
const listings=wait scraper.scrape(query);
之前使用console.log(query)你会得到什么?第一次运行是我的查询,就像我说的那样,它使用字符串
[object]再次运行浏览器
我注意到,如果我不将列表结果传递给
nextap.render
,它就会正常工作并只运行一次……但显然我需要将结果传递给组件。为什么不直接使用
server.get(“/search/:query”),async(req,res)=>{
然后只使用
const scraped=wait scraper.scrape(query)
scraper.scrape(query).然后(…)
?我用您的简化建议更新了我的代码。没有区别。如果您在
console.log(query)
之前执行
const listings=wait scraper.scrape(query);
第一次运行是我的查询,就像我说的,它使用字符串
[对象对象]
我注意到,如果我没有将列表结果传递给
nextap.render
,那么它会正常工作,并且只运行一次……但显然我需要将结果传递给组件。
import React, { Component } from "react";

export default class extends Component {
  static async getInitialProps(ctx) {
    return {
      search: ctx.query.search,
      listings: ctx.query.listings
    };
  }

  render() {
    const { search, listings } = this.props;
    console.log(listings, "client");
    return (
      <div>
        <h1>{search} search!</h1>
        { ...listings.map() }
      </div>
    );
  }
}