Escáner de libros n8n

Avanzado

Este es unContent Creation, Multimodal AIflujo de automatización del dominio deautomatización que contiene 16 nodos.Utiliza principalmente nodos como Set, Code, Webhook, HttpRequest, OpenAi. Usar GPT-4o y Google Books para extraer y verificar los títulos de libros a partir de fotos de estanterías

Requisitos previos
  • Punto final de HTTP Webhook (n8n generará automáticamente)
  • Pueden requerirse credenciales de autenticación para la API de destino
  • Clave de API de OpenAI
Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "n1UbcJnl7I5rMDIe",
  "meta": {
    "instanceId": "7d302cb44fba0420b6a4deb04edff9d7c47e83ef1f3f66f89fe519337b882186",
    "templateCredsSetupCompleted": true
  },
  "name": "n8n submission book scanner",
  "tags": [],
  "nodes": [
    {
      "id": "8fc53cb4-d7bc-4fcb-8c6d-1ee90b4ad5b4",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -896,
        1376
      ],
      "webhookId": "365ea003-fe66-4211-ae03-69f1456d768e",
      "parameters": {
        "path": "365ea003-fe66-4211-ae03-69f1456d768e",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "a140d496-9098-43b2-97df-089a811a909d",
      "name": "Responder a Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        592,
        1376
      ],
      "parameters": {
        "options": {
          "responseCode": 200,
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "application/json"
              }
            ]
          }
        },
        "respondWith": "json",
        "responseBody": "={{$json}}"
      },
      "typeVersion": 1.4
    },
    {
      "id": "050a5432-4d7e-4855-b09f-5ca40a9e0999",
      "name": "Analizar imagen",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        -448,
        1376
      ],
      "parameters": {
        "text": "=You are a STRICT transformer. Analyze the image of book spines and return only clearly readable titles and authors. \nDo NOT guess. If the author isn't clearly visible, set \"author\": null.\nNormalize capitalization. Deduplicate by title. \nOutput STRICT JSON only:\n{\"books\":[{\"title\":\"string\",\"author\":\"string|null\"}]}\n",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "resource": "image",
        "imageUrls": "={{$json.image}}\n",
        "operation": "analyze"
      },
      "credentials": {
        "openAiApi": {
          "id": "iJ4uczBur5RBMvV4",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "50c4d4b8-b164-47fb-b9c6-2234f3cb5952",
      "name": "Nota adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -992,
        1280
      ],
      "parameters": {
        "height": 80,
        "content": "Webhook connects to front end that passes on JSON with imageURL (string)"
      },
      "typeVersion": 1
    },
    {
      "id": "d245e1df-a5a2-487c-bd8f-41601be2f05c",
      "name": "Nota adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -736,
        1520
      ],
      "parameters": {
        "height": 80,
        "content": "Input is normalized"
      },
      "typeVersion": 1
    },
    {
      "id": "2c44a9af-f395-45ff-bf4f-91a55c829d3e",
      "name": "Nota adhesiva2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        1280
      ],
      "parameters": {
        "height": 80,
        "content": "Image is analyzed and transformed."
      },
      "typeVersion": 1
    },
    {
      "id": "1ec82294-d70b-4ff6-ab34-c7ef156a41b2",
      "name": "Nota adhesiva3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -288,
        1520
      ],
      "parameters": {
        "content": "Splits the output (in this case, books) into individual items in preparation for the next step which is to verify the book against a known source to confirm the title and author."
      },
      "typeVersion": 1
    },
    {
      "id": "44f65fae-f829-4b6b-976b-001d071b82ee",
      "name": "Nota adhesiva4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        1280
      ],
      "parameters": {
        "height": 80,
        "content": "Confirms each title against Google Books"
      },
      "typeVersion": 1
    },
    {
      "id": "917a2da3-3691-4904-8cbc-4c00ee4ed72e",
      "name": "Nota adhesiva5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        112,
        1536
      ],
      "parameters": {
        "height": 80,
        "content": "Normalizes data"
      },
      "typeVersion": 1
    },
    {
      "id": "62b507e0-5b7d-48a3-9e44-aa4ccf339331",
      "name": "Nota adhesiva6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        1280
      ],
      "parameters": {
        "height": 80,
        "content": "Reaggregates book list and dedupes"
      },
      "typeVersion": 1
    },
    {
      "id": "94b96cbc-3bd4-4db8-83ff-eb57b4e516c3",
      "name": "Nota adhesiva7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        1520
      ],
      "parameters": {
        "height": 80,
        "content": "Returns list back to frontend."
      },
      "typeVersion": 1
    },
    {
      "id": "c4796062-4c64-474a-85b9-8306585c18b1",
      "name": "Entrada normalizada",
      "type": "n8n-nodes-base.set",
      "position": [
        -672,
        1376
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "94b88376-fed9-46cf-882f-d4c0d7670350",
              "name": "image",
              "type": "string",
              "value": "={{ ($json.body?.imageUrl || $json.body?.image || $json.imageUrl || $json.image || '').trim() }}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "dbe25007-44da-403b-89bf-bcbf57591d58",
      "name": "División de lista de elementos",
      "type": "n8n-nodes-base.code",
      "position": [
        -240,
        1376
      ],
      "parameters": {
        "jsCode": "const items = await $input.all();\nconst out = [];\n\nfunction stripCodeFence(s) {\n  return String(s || '')\n    .replace(/^```json\\s*/i, '')\n    .replace(/^```\\s*/i, '')\n    .replace(/```$/, '')\n    .trim();\n}\n\nfunction firstAuthor(a) {\n  if (!a) return null;\n  // keep a single name for better \"inauthor:\" matching\n  const s = String(a);\n  const parts = s.split(/\\s*(?:,| and |&)\\s*/i);\n  return (parts[0] || '').trim() || null;\n}\n\nfor (const item of items) {\n  let books = null;\n\n  // Case 1: you already have an object with books[]\n  if (Array.isArray(item.json?.books)) {\n    books = item.json.books;\n  }\n\n  // Case 2: you have a string in `content` with ```json ... ```\n  if (!books && typeof item.json?.content === 'string') {\n    const cleaned = stripCodeFence(item.json.content);\n    try {\n      const parsed = JSON.parse(cleaned);\n      if (Array.isArray(parsed.books)) books = parsed.books;\n    } catch (e) {\n      // ignore; we'll fall back\n    }\n  }\n\n  if (!books) continue;\n\n  for (const b of books) {\n    out.push({\n      json: {\n        title: b.title,\n        author: b.author ?? null,\n        // helper field only for the search query:\n        searchAuthor: firstAuthor(b.author)\n      }\n    });\n  }\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2017d011-6d85-4844-a08a-0a7e88ae052d",
      "name": "Validación de título",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -32,
        1376
      ],
      "parameters": {
        "url": "https://www.googleapis.com/books/v1/volumes",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "=q",
              "value": "={{ \n  'intitle:\"' + $json.title.replace(/\"/g,'') + '\"' +\n  ($json.searchAuthor ? ' inauthor:\"' + $json.searchAuthor.replace(/\"/g,'') + '\"' : '')\n}}\n"
            },
            {
              "name": "maxResults",
              "value": "5"
            },
            {
              "name": "printType",
              "value": "books"
            },
            {
              "name": "orderBy",
              "value": "relevance"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "7d94ce36-fc7c-44cb-8df6-6f13293160a4",
      "name": "Datos normalizados",
      "type": "n8n-nodes-base.set",
      "position": [
        176,
        1376
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "67464bb0-8615-41a5-8408-11a95708d200",
              "name": "=title",
              "type": "string",
              "value": "={{ $json.items?.[0]?.volumeInfo?.title || $prevNode('Code').json.title }}\n"
            },
            {
              "id": "8db9c2f0-3193-428e-adab-2745f397233c",
              "name": "author",
              "type": "string",
              "value": "={{ $json.items?.[0]?.volumeInfo?.authors?.[0] || $prevNode('Code').json.author || null }}\n"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "99d74571-f35d-4086-93ce-f7f67768a8f0",
      "name": "Reagrupar lista",
      "type": "n8n-nodes-base.code",
      "position": [
        384,
        1376
      ],
      "parameters": {
        "jsCode": "const items = await $input.all();\nconst seen = new Set();\nconst books = [];\n\nfor (const it of items) {\n  const t = (it.json.title || '').toLowerCase().trim();\n  if (t && !seen.has(t)) {\n    seen.add(t);\n    books.push({ title: it.json.title, author: it.json.author ?? null });\n  }\n}\n\nreturn [{ json: { books } }];\n"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "5f454fe8-f8b7-4302-820e-ec24a00f13bd",
  "connections": {
    "8fc53cb4-d7bc-4fcb-8c6d-1ee90b4ad5b4": {
      "main": [
        [
          {
            "node": "c4796062-4c64-474a-85b9-8306585c18b1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "050a5432-4d7e-4855-b09f-5ca40a9e0999": {
      "main": [
        [
          {
            "node": "dbe25007-44da-403b-89bf-bcbf57591d58",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7d94ce36-fc7c-44cb-8df6-6f13293160a4": {
      "main": [
        [
          {
            "node": "99d74571-f35d-4086-93ce-f7f67768a8f0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "dbe25007-44da-403b-89bf-bcbf57591d58": {
      "main": [
        [
          {
            "node": "2017d011-6d85-4844-a08a-0a7e88ae052d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c4796062-4c64-474a-85b9-8306585c18b1": {
      "main": [
        [
          {
            "node": "050a5432-4d7e-4855-b09f-5ca40a9e0999",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2017d011-6d85-4844-a08a-0a7e88ae052d": {
      "main": [
        [
          {
            "node": "7d94ce36-fc7c-44cb-8df6-6f13293160a4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "99d74571-f35d-4086-93ce-f7f67768a8f0": {
      "main": [
        [
          {
            "node": "a140d496-9098-43b2-97df-089a811a909d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Avanzado - Creación de contenido, IA Multimodal

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Avanzado
Número de nodos16
Categoría2
Tipos de nodos7
Descripción de la dificultad

Adecuado para usuarios avanzados, flujos de trabajo complejos con 16+ nodos

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34