Este buscador ha sido creado mediante dos componentes principales:
Se usa un script en Python para recopilar artículos de revistas científicas veterinarias indexadas en PubMed, entre los años 1995 y 2025. Puedes consultar el programa aquí:
https://airsoto.github.io/vet/papers.py
El resultado es un archivo JSON con todos los artículos extraídos:
https://airsoto.github.io/vet/papers.json
El siguiente código HTML es el motor del buscador, que permite filtrar artículos por título, autor o revista, y visualizar los resultados junto con los resúmenes:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Buscador de Artículos Veterinarios</title>
<style>
body {
background-color: #121212;
color: #f0f0f0;
font-family: 'Georgia', serif;
margin: 0;
padding: 2em;
}
h1 {
text-align: center;
color: #90caf9;
cursor: pointer;
}
.search-section {
display: flex;
gap: 1em;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 2em;
}
input, select, button {
padding: 0.5em;
font-size: 1em;
border-radius: 5px;
border: none;
}
input, select {
width: 200px;
}
button {
background-color: #1e88e5;
color: white;
cursor: pointer;
}
.results {
margin-top: 2em;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5em;
}
.article {
background-color: #1e1e1e;
padding: 1.5em;
border-left: 4px solid #90caf9;
border-radius: 8px;
cursor: pointer;
transition: transform 0.3s ease, box-shadow 0.3s ease;
max-height: none;
overflow: hidden;
}
.article:hover {
transform: scale(1.03);
box-shadow: 0 0 10px #90caf9;
}
.article.expanded {
grid-column: span 3;
transform: scale(1.02);
z-index: 10;
}
.latex-style {
font-family: 'Times New Roman', serif;
background-color: #222;
padding: 1em;
border: 1px solid #555;
border-radius: 6px;
margin-top: 1em;
}
.abstract-text {
font-style: italic;
text-align: justify;
line-height: 1.6;
margin-top: 1em;
font-size: 1.05em;
}
.email-section {
margin-top: 1em;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
justify-content: center;
align-items: center;
}
.modal-content {
background-color: #1e1e1e;
padding: 2em;
border-radius: 8px;
max-width: 600px;
text-align: center;
color: #fff;
}
.close-btn {
background: #e53935;
border: none;
padding: 0.5em 1em;
color: white;
margin-top: 1em;
cursor: pointer;
border-radius: 5px;
}
</style>
</head>
<body>
<h1>
Buscador de Artículos de una selección de las principales revistas de Medicina Interna Veterinaria
<br>
<small>
<a href="javascript:void(0);" onclick="toggleModal()" style="color: #90caf9; text-decoration: underline;">
(pulsa aquí para ver las revistas indexadas)
</a>
</small>
</h1>
<h2 style="text-align: center;">
<span style="color: #ff9900;">Desarrollado por: Angel Soto</span>
</h2>
<p style="text-align: center; margin-top: -1em;">
<a href="https://airsoto.github.io/vet/howpapers.html" target="_blank" style="color: #90caf9; text-decoration: underline;">
(cómo está creada esta página)
</a>
</p>
<div class="modal" id="modal">
<div class="modal-content">
<h2>Revistas indexadas</h2>
<p>Journal of Veterinary Internal Medicine<br />Journal of the American Veterinary Medical Association<br />Journal of Veterinary Cardiology<br />Journal of Small Animal Practice</p>
<p><br />con más de 10600 artículos.</p>
<button class="close-btn" onclick="toggleModal()">Cerrar</button>
</div>
</div>
<div class="search-section">
<select id="search-type">
<option value="title">Título</option>
<option value="authors">Autor</option>
<option value="journal">Revista</option>
</select>
<input type="text" id="search-input" placeholder="Buscar...">
<input type="text" id="keyword-input" placeholder="Palabra clave...">
<button onclick="search()">Buscar</button>
</div>
<div id="result-count" style="text-align:center; font-size:1.2em; margin-top:1em; color:#90caf9;"></div>
<div id="results" class="results"></div>
<script>
let articles = [];
async function cargarArticulos() {
try {
const response = await fetch('papers.json');
if (!response.ok) throw new Error('No se pudo cargar el archivo JSON');
articles = await response.json();
} catch (error) {
document.getElementById('results').innerHTML = '<p>Error al cargar los artículos.</p>';
console.error(error);
}
}
function search() {
const type = document.getElementById('search-type').value;
const query = document.getElementById('search-input').value.toLowerCase();
const keywordQuery = document.getElementById('keyword-input').value.toLowerCase();
const resultsContainer = document.getElementById('results');
const countContainer = document.getElementById('result-count');
resultsContainer.innerHTML = '';
countContainer.innerHTML = '';
const filtered = articles.filter(article => {
const matchType = (type === 'authors')
? article.authors.some(a => a.toLowerCase().includes(query))
: article[type].toLowerCase().includes(query);
const matchKeyword = keywordQuery === "" || (
article.keywords &&
article.keywords.some(k => k.toLowerCase().includes(keywordQuery))
);
return matchType && matchKeyword;
});
countContainer.innerHTML = `Se encontraron <strong>${filtered.length}</strong> artículo(s).`;
if (filtered.length === 0) {
resultsContainer.innerHTML = "<p>No se encontraron resultados.</p>";
return;
}
filtered.forEach(article => {
const div = document.createElement('div');
div.className = 'article';
div.innerHTML = `
<div class="latex-style">
<h2 style="text-align: center;">${article.title}</h2>
<p style="text-align: center; font-style: italic;">${article.authors.join(', ')}</p>
<p style="text-align: center; font-size: 0.95em;">${article.journal}, Vol. ${article.volume}(${article.issue}), ${article.year}</p>
<h3 style="margin-top: 1.5em;">Resumen</h3>
<p class="abstract-text">${article.abstract}</p>
${article.keywords ? `<p style="font-size: 0.9em; margin-top: 1em;"><strong>Palabras clave:</strong> ${article.keywords.join(', ')}</p>` : ''}
</div>
<div class="email-section">
<input type="email" placeholder="Tu email..." id="email-${article.title}" style="margin-top: 1em;"/>
<button onclick="event.stopPropagation(); sendEmail('${article.title.replace(/'/g, "\\'")}')">Enviar por correo</button>
</div>
`;
div.addEventListener('click', () => {
div.classList.toggle('expanded');
});
resultsContainer.appendChild(div);
});
}
function sendEmail(title) {
const article = articles.find(a => a.title === title);
const email = document.getElementById(`email-${title}`).value;
if (!email || !email.includes('@')) {
alert("Introduce un email válido.");
return;
}
const subject = encodeURIComponent("Artículo Veterinario: " + article.title);
const body = encodeURIComponent(`Título: ${article.title}\nAutores: ${article.authors.join(', ')}\nRevista: ${article.journal}, Vol. ${article.volume}(${article.issue}), ${article.year}\n\nResumen:\n${article.abstract}`);
const mailto = `mailto:${email}?subject=${subject}&body=${body}`;
window.location.href = mailto;
}
function toggleModal() {
const modal = document.getElementById('modal');
modal.style.display = (modal.style.display === 'flex') ? 'none' : 'flex';
}
cargarArticulos();
</script>
</body>
</html>
Nota: El código completo con estilos y scripts detallados puede visualizarse directamente en tu editor favorito o implementarse como base de un visor web en tu servidor.