소스 검색

Start scraping lauras recipes

Tati 7 년 전
부모
커밋
bfa06abc82
9개의 변경된 파일148개의 추가작업 그리고 8개의 파일을 삭제
  1. 19 0
      .vscode/launch.json
  2. 2 0
      .vscode/settings.json
  3. 4 4
      ktchn/nodemon.json
  4. 5 1
      ktchn/package.json
  5. 32 0
      ktchn/src/recipes/index.ts
  6. 30 0
      ktchn/src/recipes/routes.ts
  7. 45 0
      ktchn/src/recipes/scrape.ts
  8. 7 1
      ktchn/src/routes/root.ts
  9. 4 2
      ktchn/src/server.ts

+ 19 - 0
.vscode/launch.json

@@ -0,0 +1,19 @@
+{
+  // Use IntelliSense to learn about possible attributes.
+  // Hover to view descriptions of existing attributes.
+  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+  "version": "0.2.0",
+  "configurations": [
+    {
+      "name": "Launch via npm",
+      "type": "node",
+      "request": "launch",
+      "cwd": "${workspaceFolder}",
+      "runtimeExecutable": "npm",
+      "runtimeArgs": [
+          "run-script", "debug"
+      ],
+      "port": 9229,
+    }
+  ]
+}

+ 2 - 0
.vscode/settings.json

@@ -0,0 +1,2 @@
+{
+}

+ 4 - 4
ktchn/nodemon.json

@@ -1,6 +1,6 @@
 {
-  "watch": "src/**/*.ts",
-  "execMap": {
-    "ts": "ts-node"
-  }
+  "ignore": ["**/*.test.ts", "**/*.spec.ts", ".git", "node_modules"],
+  "watch": ["src"],
+  "exec": "npm start",
+  "ext": "ts"
 }

+ 5 - 1
ktchn/package.json

@@ -3,13 +3,17 @@
   "version": "0.0.0",
   "private": true,
   "scripts": {
-    "start": "npm run build:live",
+    "start": "ts-node --inspect-brk=9229 src/server.ts",
+    "dev": "nodemon",
     "build": "tsc -p .",
     "build:live": "nodemon --watch 'src/**/*.ts' --exec ts-node src/server.ts"
   },
   "dependencies": {
+    "@types/cheerio": "^0.22.9",
     "@types/cookie-parser": "^1.4.1",
     "@types/express": "^4.16.0",
+    "@types/request": "^2.48.0",
+    "@types/request-promise": "^4.1.42",
     "cheerio": "^1.0.0-rc.2",
     "cookie-parser": "~1.4.3",
     "debug": "~2.6.9",

+ 32 - 0
ktchn/src/recipes/index.ts

@@ -0,0 +1,32 @@
+interface QtyMetric {
+  qty: Number;
+  unit: String;
+}
+
+interface Ingredient {
+  name: String;
+  qtyMetric: QtyMetric;
+  qtyCups: Number;
+  note: String;
+}
+
+interface Temperature {
+  celsius: Number;
+  farenheid: Number;
+}
+
+class Recipe {
+  public name: String;
+  tags!: String[];
+  ingredients!: Ingredient[];
+  servings!: Number;
+  cookTime!: Number;
+  preparationTime!: Number;
+  directions!: String[];
+
+  constructor(name:string) {
+    this.name = name;
+  }
+}
+
+export default Recipe;

+ 30 - 0
ktchn/src/recipes/routes.ts

@@ -0,0 +1,30 @@
+import { Request, Response, Router } from "express";
+import Scrape from "./scrape";
+
+class RecipeRoutes {
+  public router: Router;
+  public constructor() {
+    this.router = Router();
+    this.init();
+  }
+
+  private init() {
+    this.router.get("/", (req, res, next) => {
+      res.json({
+        message: 'hey recipes bb'
+      });
+    })
+    this.router.post("/scrape", (req, res, next) => {
+       console.log("body", req.body);
+       return Scrape(req.body.url).then((x)=>{
+         console.log('x', x);
+         res.json({
+           message: 'thx'
+         })
+       });
+    })
+  }
+}
+
+const recipeRoutes = new RecipeRoutes();
+export default recipeRoutes.router;

+ 45 - 0
ktchn/src/recipes/scrape.ts

@@ -0,0 +1,45 @@
+import RequestPromise from "request-promise";
+import Cheerio from "cheerio";
+import Recipe from "./index";
+import { json } from "body-parser";
+import { stringify } from "querystring";
+import { UriOptions } from "request";
+
+function getIngredients($:CheerioSelector): Recipe {
+  let r = new Recipe('');
+  const ingredientsScrape = $('.cs-ingredients-check-list > ul').children();
+  console.log(ingredientsScrape.length);
+
+  return r;
+}
+
+function lauraInTheKitchen($:CheerioSelector):Recipe {
+  let recipe = new Recipe($('.cs-page-title>h1').text().trim());
+  const recipeDetails = $('.cs-recipe-details').find('div');
+  
+  const recipeMap = ['preparationTime', 'cookTime', 'servings'];
+  recipeDetails.each((i:any, el:any) => {
+    if (i > 2) return false;
+    var x = $(el).contents().toArray();
+    recipe = {
+      ...recipe,
+      [recipeMap[i]]: $(x).not('span').text().replace(/\D/g,''),
+    } 
+  })
+  
+  getIngredients($);
+  return recipe;
+}
+
+function scrape(url:string) {
+  const options = {
+    uri: url,
+    transform: (body: any) => Cheerio.load(body),
+  };
+  return RequestPromise(options).then(($) => {
+    return lauraInTheKitchen($);
+  });
+
+}
+
+export default scrape;

+ 7 - 1
ktchn/src/routes/root.ts

@@ -9,7 +9,13 @@ class Root {
   private init() {
     this.router.get("/", (req, res, next) => {
       res.json({
-        message: 'hello world'
+        message: 'hello recipes'
+      });
+    })
+    this.router.post("/scrape", (req, res, next) => {
+      console.log("scrape", req.body);
+      res.json({
+        message: 'thx'
       });
     })
   }

+ 4 - 2
ktchn/src/server.ts

@@ -5,19 +5,21 @@ import logger from "morgan";
 import express from "express";
 
 import rootRouter from "./routes/root";
+import recipeRouter from "./recipes/routes";
 
 class App {
   public express: express.Application;
 
   constructor() {
     this.express = express();
-    this.routes();
     this.middleware();
+    this.routes();
     this.launchConf();
   }
 
   private routes(): void {
     this.express.use("/", rootRouter);
+    this.express.use("/recipes", recipeRouter);
   }
 
   private middleware(): void {
@@ -35,7 +37,7 @@ class App {
     console.log('port', port);
     this.express.listen(port, () => {
       console.log(
-        ("App is running at http://localhost:%d in %s mode"),
+        ("App is runnnning at http://localhost:%d in %s mode"),
         port,
         this.express.get("env")
       );