我如何 运行 多次使用一个脚本并存储值,然后使用 google-search-results-nodejs 客户端将其发送到前端

how can i run one script for multiple times and store value then send it to frontend using google-search-results-nodejs client

假设我有 10 个关键字 kewords1、keyword2。我想 运行 这个脚本用于所有带有 mern 堆栈的关键字,然后将这个响应发送到前端反应。请让我知道我该怎么做?

这是简单的代码。

const SerpApi = require('google-search-results-nodejs')
const search = new SerpApi.GoogleSearch("Your Private Key")
search.json({
 q: "Coffee", 
 location: "Austin, TX"
}, (result) => {
  console.log(result)
})

我不知道您要求帮助实现应用程序的哪一部分。以下是后端和前端部分。

后端

Try it on Replit.

const express = require("express");
const { GoogleSearch } = require("google-search-results-nodejs");
const search = new GoogleSearch(process.env.API_KEY);

const app = express();

app.set('json spaces', 2)
app.use(express.json());

// Set routes
app.get("/", (req, res) => {
  res.send("Make a request to /search?q=coffee&q=cake");
});

app.get("/search", (req, res) => {
  // The number of queries should be limited in a real application
  // but it's ommitted here in favor of simplicity
  const queries = Array.from(req.query.q);

  makeSearches(queries).then((results) => {
    res.send(results);
  });
});

// API

// Workaround to make it work with Promises
// https://github.com/serpapi/google-search-results-nodejs/issues/4
function promisifiedGetJson(params) {
  return new Promise((resolve, reject) => {
    try {
      search.json(params, resolve);
    } catch (e) {
      reject(e);
    }
  });
}

function makeSearches(queries) {
  const promises = queries.map((q) => {
    const params = {
      q,
      location: "Austin, TX",
    };

    return promisifiedGetJson(params);
  });

  return Promise.all(promises);
};

// Start server

app.listen(3000, () => {
  console.log(`Server is running on port: 3000`);
});

示例请求和响应:

$ curl -s 'https://mern-serpapi-nodejs.serpapi.repl.co/search?q=Whosebug&q=github&q=deno' | jq -r '.[].search_metadata'
{
  "id": "61fad426607393485726c241",
  "status": "Success",
  "json_endpoint": "https://serpapi.com/searches/582d9fcdfd66a739/61fad426607393485726c241.json",
  "created_at": "2022-02-02 18:57:42 UTC",
  "processed_at": "2022-02-02 18:57:42 UTC",
  "google_url": "https://www.google.com/search?q=Whosebug&oq=Whosebug&uule=w+CAIQICIdQXVzdGluLFRYLFRleGFzLFVuaXRlZCBTdGF0ZXM&sourceid=chrome&ie=UTF-8",
  "raw_html_file": "https://serpapi.com/searches/582d9fcdfd66a739/61fad426607393485726c241.html",
  "total_time_taken": 0.66
}
{
  "id": "61fad42617f923aa08188dfc",
  "status": "Success",
  "json_endpoint": "https://serpapi.com/searches/667255ede060a7ae/61fad42617f923aa08188dfc.json",
  "created_at": "2022-02-02 18:57:42 UTC",
  "processed_at": "2022-02-02 18:57:42 UTC",
  "google_url": "https://www.google.com/search?q=github&oq=github&uule=w+CAIQICIdQXVzdGluLFRYLFRleGFzLFVuaXRlZCBTdGF0ZXM&sourceid=chrome&ie=UTF-8",
  "raw_html_file": "https://serpapi.com/searches/667255ede060a7ae/61fad42617f923aa08188dfc.html",
  "total_time_taken": 0.96
}
{
  "id": "61fad4261baebbb454181a3a",
  "status": "Success",
  "json_endpoint": "https://serpapi.com/searches/ae665860b250fd5f/61fad4261baebbb454181a3a.json",
  "created_at": "2022-02-02 18:57:42 UTC",
  "processed_at": "2022-02-02 18:57:42 UTC",
  "google_url": "https://www.google.com/search?q=deno&oq=deno&uule=w+CAIQICIdQXVzdGluLFRYLFRleGFzLFVuaXRlZCBTdGF0ZXM&sourceid=chrome&ie=UTF-8",
  "raw_html_file": "https://serpapi.com/searches/ae665860b250fd5f/61fad4261baebbb454181a3a.html",
  "total_time_taken": 0.61
}

说明

答案由两部分组成:使用 SerpApi 发出 N 个请求和 return 响应。

发出 N 个请求

目前,google-search-results-nodejs 没有 Promise API 所以 the workaround to make it work with Promises is required. With callback API it's also possible but it requires the usage of Array#reduce.

function promisifiedGetJson(params) {
  return new Promise((resolve, reject) => {
    try {
      search.json(params, resolve);
    } catch (e) {
      reject(e);
    }
  });
}

使用 Promise API,关键字列表将映射到 Promise 数组。

function makeSearches(queries) {
  const promises = queries.map((q) => {
    const params = {
      q,
      location: "Austin, TX",
    };

    return promisifiedGetJson(params);
  });

  return Promise.all(promises);
};

API 到 return 响应的操作(路由)

它获取一个查询参数数组并调用一个 makeSearches 函数。

app.get("/search", (req, res) => {
  // The number of queries should be limited in a real application
  // but it's ommitted here in favor of simplicity
  const queries = Array.from(req.query.q);

  makeSearches(queries).then((results) => {
    res.send(results);
  });
});

Front-end部分

这里有两个 full-stack React 项目,它们使用上面的 API。

演示

https://user-images.githubusercontent.com/282605/155405202-50bceacb-57f6-4729-b950-ea6e5ef6c295.mp4

两个项目都部署到 Vercel。 Next.js 应用更简单,因为这是 Next.js 的价值主张。

Express.js 应用仅在开发模式下具有 SSR。它使用 Vite 在服务器上渲染 React 组件。 Next.js 应用在开发和生产中有 SSR。

React 组件本身在这两种情况下是相同的:

// App.jsx

import React from "react";
import ReactDOM from "react-dom";

import React, { useState } from "react";
import { SearchResults } from "./SearchResults";

export function App() {
  const [q, setQ] = useState("coffee, cats");
  const [searchResults, setSearchResults] = useState([]);
  const [isLoading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  function handleFormSubmit(event) {
    event.preventDefault();

    const params = new URLSearchParams({
      q,
    });

    setLoading(true);
    fetch(`/api/search?${params}`)
      .then((res) => res.json())
      .then(
        (results) => {
          setSearchResults(results);
          setLoading(false);
          setError(null);
        },
        (error) => {
          setError(error);
        }
      );
  }

  function handleQChange(event) {
    event.preventDefault();
    setQ(event.target.value);
  }

  return (
    <>
      <h1>SerpApi example in MERN stack</h1>

      <form action="/api/search" method="get" onSubmit={handleFormSubmit}>
        <label>
          <label>Queries (separated by comma):</label>&nbsp;
          <input name="q" value={q} placeholder={q} onChange={handleQChange} />
          <br />
          <input
            type="submit"
            value={isLoading ? "Loading..." : "Search"}
            disabled={isLoading} />
        </label>
      </form>

      <br />

      <SearchResults
        results={searchResults}
        isLoading={isLoading}
        error={error} />
    </>
  );
}

ReactDOM.hydrate(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

SearchResults.jsx

function SearchResults({ results, isLoading, error }) {
  if (isLoading)
    return (
      <p>
        Loading...
      </p>
    );

  if (!results || results.length === 0) {
    return <p>Click &quot;Search&quot; &uarr; to continue.</p>;
  }

  if (error) return <p>Error: {error}</p>;

  return (
    <section>
      <h3>Search results ({results.length})</h3>
      <ul>{results.map(r => (<li key={r.search_metadata.id}>{r.search_metadata.id}</li>))}</ul>
    </section>
  );
}

免责声明:我在 SerpApi 工作。


这个问题在 Github repository of google-search-results-nodejs 出现在这里的前一天被问到。