반응형

개요

 

이번에는 쿠팡의 상품정보들을 이미지와 제목 가격 링크들을 크롤링해 온후 그 정보를 통해 Json 파일을 만들어 보도록 하겠습니다

 

지난번에는 Switch case 구문으로 원하는 정보를 뽑아 왔지만 이번에는 오직 제이쿼리만 사용해서

나타내 보도록 하겠습니다.

쿠팡 : https://www.coupang.com/np/categories/306749?channel=plp_C2

 


순서

 

우선 Product.json이라는 빈 파일을 그냥 만들어 줍니다.

 

 

 

이런식으로 값들을 바로바로 data에 던져 주는 걸 볼 수 있습니다.

그렇게 된다면 product.json 파일은 

다음과 같이 나오게 되는 것을 볼 수 있습니다.

 

그리고 여기서 index가 왜 7이상 이나면 원하는 값들은 아이템의 7번째부터 가져오고 싶어서 다음과 같이 작성을 하였습니다.

 


그리고 서버파일로 이동해줍니다.. 

 

 

이와 같이 서버를 작성하게 되면 우리가 crawlProduct.js에서 크롤링해온 정보를 Json파일에 넣어주고 그렇게 만들어진 

Json파일을 위의 코드를 통해 /api/product로 전송해 줍니다. 그렇게 하면 서버에 우리가 크롤링해온 정보를 담고 있는 product.json의 정보가 전송이 된 것입니다.

 

그리고 그 서버에서 전송된 정보를 가지고 React의 프런트에 뿌려주는 방법도 알아보도록 하겠습니다.

 


서버의 정보를 Front로 뿌려주기

 

 

 

/api/product에서 가져온 정보를 Product_Data에 set 하는 과정입니다.

 

 

그리고 set 한 Product_Data의 정보를 map함수를 통해 다음과 같이 뿌려주고 있습니다.

 

여기서 Product_option은 하나의 테이블 셀 모듈로 

 

다음과 같이 작성이 되어 있습니다.

그렇게 실행을 하게 된다면...

 


결과

 

 

다음과 같이 나오는 것 을 볼 수 있습니다.

 


crawlProduct.js

 

const axios = require("axios");
const cheerio = require("cheerio");
const fs = require("fs");

let html = "";

async function getHtml() {
  try {
    return await axios.get("https://www.coupang.com/np/categories/306749?channel=plp_C2");
  } catch (error) {
    console.error(error);
  }
}

async function getProduct() {
  if (!html) {
    html = await getHtml();
  }

  const dataArr = [];
  const dataPath = "./product.json";
  const $ = cheerio.load(html.data);

  $(".newcx-container .newcx-body .newcx-main .newcx-list ul li")
  .each(async function (index, item) {
    var src ='http:'+ $(item).find("dl").find("img").attr("src");
    var title = $(item).find("dl").find("img").attr("alt");
    var price = $(item).find("dl").find("dd").find(".sale")
    .find(".price-value").first().text();
    var a ='https://www.coupang.com/'+$(item).find("a").attr("href");
    
      var data = {
        src: src,
        title: title,
        price:price,
        a:a
      };
      if (index > 7) {
        dataArr.push(data);
        fs.writeFileSync(dataPath, JSON.stringify(dataArr));
        console.log("product on json file");
      }
    }
  );
}
module.exports = { getProduct };

 


server.js

 

const express = require("express");
const { getProduct } = require("./crawlProduct.js");
const fs = require("fs");

const bodyParser = require("body-parser");
const app = express();
const port = process.env.PORT || 5000;
const cron = require("node-cron");

const ProudctJSON = fs.readFileSync("./product.json");
const newsData = JSON.parse(newsJSON);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));



async function getProductAsync() {
  const Product_data = await getProduct();
  console.log("Product = ", Product_data);
  console.log(ProudctJSON.text);
}


cron.schedule("*/1 * * * *", async () => {
  console.log("running a task every two minutes");
  await getProductAsync();
});


app.get("/api/product",async(req,res)=> {
  res.send(ProudctJSON);
})



app.listen(port, () => console.log(`Listening on port ${port}`));

 


product_option.js

 

import React from 'react'
import TableRow from '@material-ui/core/TableRow'
import TableCell from '@material-ui/core/TableCell'

class Product_option extends React.Component {
    render() {
        return (
            <TableRow>
                <TableCell><img src={this.props.src} width="80px" height="80px"/></TableCell>
                <TableCell>{this.props.title}</TableCell>
                <TableCell>{this.props.price}</TableCell>
                <TableCell><a href={this.props.a}>구매</a></TableCell>
            </TableRow>
        )
    }
}

export default Product_option;

 


product.js

 

import React, { Component } from 'react';
import { withStyles, makeStyles } from "@material-ui/core/styles";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import Product_option from './Product_option'

const StyledTableCell = withStyles((theme) => ({
    head: {
      backgroundColor: theme.palette.common.black,
      color: theme.palette.common.white,
    },
    body: {
      fontSize: 16,
    },
  }))(TableCell);

  const StyledTableContainer2 = withStyles((theme)=> ({
    root: {
      opacity:'80%',
      width:'auto',
      marginLeft:'5%',
      marginRight:'5%',
      height:'500px',
    }
  }))(TableContainer)

 
class Product extends Component {
    constructor(props) {
        super(props);
        this.state = {
            Product_Data: [],
        };
      }
    
      componentWillMount() {
        this.callApi().then((res) => {
          this.setState({
            Product_Data: res,
          });
        });
      }
    
      callApi = async () => {
        const response = await fetch("/api/product");
        const body = await response.json();
        return body;
      };
      
      render() {
        const { Product_Data } = this.state;
        
        return (
            
            <div>
                <br></br>
                <br></br><br></br>
                <h2 style={{ color: "white", textAlignLast: "center" }}>
                ※ 면역력 증가 상품
              </h2>
              <br></br>
                <StyledTableContainer2 component={Paper}>
                <Table>
                    <TableHead>
                    <TableRow>
                        
                        <StyledTableCell align="center">상품</StyledTableCell>
                        <StyledTableCell align="center">제목</StyledTableCell>
                        <StyledTableCell align="center">가격</StyledTableCell>
                        <StyledTableCell align="center">구매</StyledTableCell>
                    </TableRow>
                    </TableHead>
                    <TableBody>
                        {Product_Data.map(post=> {
                            return <Product_option src ={post.src} title={post.title} price={post.price} a={post.a}/>
                        })
                    }
                    
                    </TableBody>
                </Table>
                </StyledTableContainer2>
            </div>
           
        );
    }
}

export default Product
반응형

+ Recent posts