feat: add new router for cell journal (#4159)

This commit is contained in:
Chang Y 2020-03-08 01:15:45 +08:00 committed by GitHub
parent 36b8405afe
commit d76ea0936a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 147 additions and 1108 deletions

View File

@ -8,10 +8,20 @@ pageClass: routes
<RouteEn author="yech1990" example="/cell/cell/current" path="/cell/cell/:category" supportScihub="1" />
| `:category` | Query Type | Route |
| :---------: | :---------------------: | ---------------------------------------- |
| current | Current Issue (default) | [/cell/cell/current](/cell/cell/current) |
| inpress | Articles in press | [/cell/cell/inpress](/cell/cell/inpress) |
| `:category` | Query Type | Route |
| :---------: | :---------------------: | ---------------------------------------------------------- |
| current | Current Issue (default) | [/cell/cell/current](https://rsshub.app/cell/cell/current) |
| inpress | Articles in press | [/cell/cell/inpress](https://rsshub.app/cell/cell/inpress) |
</RouteEn>
### Cover Story
<RouteEn author="yech1990" example="/cell/cover" path="/cell/cover" />
Subscribe to the cover images of the Cell journals, and get the latest publication updates in time.
Including 'cell', 'cancer-cell', 'cell-chemical-biology', 'cell-host-microbe', 'cell-metabolism', 'cell-reports', 'cell-reports-physical-science', 'cell-stem-cell', 'cell-systems', 'chem', 'current-biology', 'developmental-cell', 'immunity', 'joule', 'matter', 'molecular-cell', 'neuron', 'one-earth' and 'structure'.
</RouteEn>
@ -151,7 +161,7 @@ Subscribe to the cover images of the Nature journals, and get the latest publica
### Cover Story
<RouteEn author="yech1990" example="/science/cover" path="/science/cover" />
<RouteEn author="yech1990" example="/sciencemag/cover" path="/sciencemag/cover" />
Subscribe to the cover images of the Science journals, and get the latest publication updates in time.

View File

@ -10,10 +10,20 @@ pageClass: routes
<Route author="yech1990" example="/cell/cell/current" path="/journals/cell/cell/:category" supportScihub="1"/>
| `:category` | 类型说明 | 路由 |
| :---------: | :-----------------: | ---------------------------------------- |
| current | 本期刊物 (默认选项) | [/cell/cell/current](/cell/cell/current) |
| inpress | 在线发表 | [/cell/cell/inpress](/cell/cell/inpress) |
| `:category` | 类型说明 | 路由 |
| :---------: | :-----------------: | ---------------------------------------------------------- |
| current | 本期刊物 (默认选项) | [/cell/cell/current](https://rsshub.app/cell/cell/current) |
| inpress | 在线发表 | [/cell/cell/inpress](https://rsshub.app/cell/cell/inpress) |
</Route>
### 封面故事
<Route author="yech1990" example="/cell/cover" path="/cell/cover" />
订阅 Cell 系列杂志的封面图片,并及时获取刊物更新状态。
包含了: 'cell'、 'cancer-cell'、 'cell-chemical-biology'、 'cell-host-microbe'、 'cell-metabolism'、 'cell-reports'、 'cell-reports-physical-science'、 'cell-stem-cell'、 'cell-systems'、 'chem'、 'current-biology'、 'developmental-cell'、 'immunity'、 'joule'、 'matter'、 'molecular-cell'、 'neuron'、 'one-earth' 和 'structure'。
</Route>
@ -124,7 +134,7 @@ pageClass: routes
### 封面故事
<Route author="yech1990" example="/science/cover" path="/science/cover" />
<Route author="yech1990" example="/sciencemag/cover" path="/sciencemag/cover" />
订阅 Science 系列杂志的封面图片,并及时获取刊物更新状态。
@ -140,9 +150,9 @@ _仅支持 Science 主刊_
</Route>
## X-MOL
## X-MOL 平台
### 平台-期刊
### 期刊
<Route author="cssxsh" example="/x-mol/paper/0/9" path="/x-mol/paper/:type/:magazine" :paramsDesc="['类别','机构两个参数都可从期刊URL获取。']" />

View File

@ -1962,8 +1962,8 @@ router.get('/kzfeed/topic/:id', require('./routes/kzfeed/topic'));
router.get('/factcheck', require('./routes/tencent/factcheck'));
// X-MOL化学资讯平台
router.get('/x-mol/news/:tag?', require('./routes/journals/x-mol/news.js'));
router.get('/x-mol/paper/:type/:magazine', require('./routes/journals/x-mol/paper'));
router.get('/x-mol/news/:tag?', require('./routes/x-mol/news.js'));
router.get('/x-mol/paper/:type/:magazine', require('./routes/x-mol/paper'));
// 知识分子
router.get('/zhishifenzi/news/:type?', require('./routes/zhishifenzi/news'));
@ -1991,19 +1991,20 @@ router.get('/kaggle/discussion/:forumId/:sort?', require('./routes/kaggle/discus
router.get('/kaggle/competitions/:category?', require('./routes/kaggle/competitions'));
// PubMed Trending
router.get('/pubmed/trending', require('./routes/journals/pubmed/trending'));
router.get('/pubmed/trending', require('./routes/pubmed/trending'));
// 领科 (linkresearcher.com)
router.get('/linkresearcher/:params', require('./routes/linkresearcher/index'));
// eLife [Sci Journal]
router.get('/elife/:tid', require('./routes/journals/elife/index'));
router.get('/elife/:tid', require('./routes/elife/index'));
// PNAS [Sci Journal]
router.get('/pnas/:topic?', require('./routes/pnas/index'));
// cell [Sci Journal]
router.get('/cell/cell/:category', require('./routes/journals/cell/cell/index'));
router.get('/cell/cell/:category', require('./routes/cell/cell/index'));
router.get('/cell/cover', require('./routes/cell/cover'));
// nature + nature 子刊 [Sci Journal]
router.get('/nature/research/:journal?', require('./routes/nature/research'));

109
lib/routes/cell/cover.js Normal file
View File

@ -0,0 +1,109 @@
// The content is generateed by undocumentated resource of Cell journals
const got = require('@/utils/got');
const cheerio = require('cheerio');
const url = require('url');
module.exports = async (ctx) => {
const baseURL = 'https://www.cell.com';
const journals = [
'cell',
'cancer-cell',
'cell-chemical-biology',
'cell-host-microbe',
'cell-metabolism',
'cell-reports',
'cell-reports-physical-science',
'cell-stem-cell',
'cell-systems',
'chem',
'current-biology',
'developmental-cell',
'immunity',
'joule',
'matter',
'molecular-cell',
'neuron',
'one-earth',
'structure',
];
const out = await Promise.all(
journals.map(async (journal) => {
// get the lastest volumn and issue id
const pageURL = `${baseURL}/${journal}/current`;
const pageMeta = await ctx.cache.tryGet(
pageURL,
async () => {
const cookieData = await got
.extend({
followRedirect: false,
})
.get(`https://secure.jbs.elsevierhealth.com/action/getSharedSiteSession?redirect=${encodeURI(pageURL)}`)
.then((response) => {
const cookieString = response.headers['set-cookie'].join(' ');
const server = cookieString.match(/SERVER=(\S+);/)[1];
const jsession = cookieString.match(/JSESSIONID=(\S+);/)[1];
return `SERVER=${server}; JSESSIONID=${jsession};`;
});
const pageResponse = await got.get(pageURL, {
headers: {
cookie: cookieData,
},
followRedirect: false,
});
const $ = cheerio.load(pageResponse.data);
const coverImg = url.resolve('https://', $('#fullCover > img').attr('src'));
const coverDescription = $('#fullCover > img').attr('alt');
const issueDate = $('h1.toc-header__issue-date').text();
const issueNum = $('.toc-header__details span')
.contents()
.map(function() {
return this.type === 'text' ? $(this).text() : '';
})
.get()
.slice(0, 2)
.join(', ');
const issueName =
$('meta[name="name"]')
.attr('content')
.replace('Issue: ', '') || `Cell ...`;
const m = $('meta[name="pbContext"]')
.attr('content')
.match(/issue:issue:pii\\:(S\d{4})(\d{4})(\d{2})(X\d{4})(\w)/);
const issueID = `${m[1]}-${m[2]}(${m[3]})${m[4]}-${m[5]}`;
return {
coverImg: coverImg,
coverDescription: coverDescription,
issueName: issueName,
issueDate: issueDate,
issueNum: issueNum,
issueID: issueID,
};
},
12 * 60 * 60 // set cache timeout to 12h
);
const address = `${baseURL}/${journal}/issue?pii=${pageMeta.issueID}`;
const contents = `<div align="center"><img src="${pageMeta.coverImg}" alt="${pageMeta.coverDescription}"></div>`;
const single = {
title: `${pageMeta.issueName} | ${pageMeta.issueNum} (${pageMeta.issueDate})`,
author: '@yech1990',
description: contents,
link: address,
guid: address,
pubDate: new Date(pageMeta.issueDate).toUTCString(),
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: 'Cell Covers Story',
description: 'Find out the cover story of some Cell journals.',
link: baseURL,
item: out,
};
};

View File

@ -1,123 +0,0 @@
// cell.com is extremely slow, and redirect too many times.
// Thus, the content page are replaced by www.sciencedirect.com.
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const baseURL = 'https://www.cell.com';
const category = ctx.params.category;
let pageURL = `${baseURL}/cell/current.rss`;
let categoryTitle = 'Latest issue';
if (category === 'inpress') {
pageURL = `${baseURL}/cell/inpress.rss`;
categoryTitle = 'Articles in press';
}
const alternativeURL = 'https://www.sciencedirect.com/science/article/pii/';
const pageResponse = await got.get(pageURL);
const pageCapture = cheerio.load(pageResponse.data);
const list = pageCapture('item')
.get()
.filter(function(item) {
const $ = cheerio.load(item);
const section = $('prism\\:section').text();
return ['Article', 'Resource'].includes(section);
});
const out = await Promise.all(
list.map(async (item) => {
const $ = cheerio.load(item);
const section = $('prism\\:section').text();
const address =
alternativeURL +
$('item')
.attr('rdf:about')
.replace('?rss=yes', '')
.split('/')
.pop();
const title = $('dc\\:title').text();
const author = $('dc\\:creator').text();
const pubDate = new Date($('dc\\:date').text()).toUTCString();
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const itemPage = await got.get(address);
const itemCapture = cheerio.load(itemPage.data);
// section + keywords content
const keywords = itemCapture('div.keywords-section > div.keyword')
.map(function(i, el) {
return $(el).text();
})
.get()
.join('; ');
const sectionContents = `
<div id="content-section">
<span style="color: #007dbc; text-transform: uppercase; font-weight: 700;">${section}</span>
<br>
<p style="color: grey; font-weight: 700;">[${keywords}]</p>
</div>
`;
// graphical content
const brief = $('description').text();
const graphical = itemCapture('div.abstract.graphical')
.find('img')
.attr('src');
let graphicalContents = '';
if (graphical !== '') {
graphicalContents = `
<div id="content-graphical">
<h2 style="color: #007dbc; font-weight: 700;">Graphical Abstract</h2>
<center>
<figure>
<img src="${graphical}" height="400" alt="">
</figure>
</center>
<span>${brief}</span>
</div>`;
}
// highlight content
const highlight = itemCapture('div.abstract.author-highlights dl').html();
let highlightContents = '';
if (highlight !== '') {
highlightContents = `
<div id="content-highlight">
<h2 style="color: #007dbc; font-weight: 700;">Highlights</h2>
${highlight}
</div>`;
}
// summary content
const summary = itemCapture('div.abstract.author p').html();
let summaryContents = '';
if (summary !== '') {
summaryContents = `
<div id="content-summary">
<h2 style="color: #007dbc; font-weight: 700;">Summary</h2>
${summary}
</div>`;
}
const contents = sectionContents + graphicalContents + highlightContents + summaryContents;
const single = {
title: title,
author: author,
description: contents,
link: address,
guid: address,
doi: $('dc\\:identifier').text(),
pubDate: pubDate,
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: `Cell | ${categoryTitle}`,
description: `Cell, a research journal`,
link: baseURL,
item: out,
};
};

View File

@ -1,69 +0,0 @@
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const baseUrl = `https://elifesciences.org`;
const tid = ctx.params.tid;
let url = baseUrl;
if (tid !== 'latest') {
url = `${baseUrl}/subjects/${ctx.params.tid}`;
}
const res = await got.get(url);
const $ = cheerio.load(res.data);
$('.grid-secondary-column').remove();
let topic = 'latest';
if (tid !== 'latest') {
topic = $('h1.content-header__title.content-header__title--xx-short').text();
}
const list = $('li.listing-list__item').get();
const out = await Promise.all(
list.map(async (item) => {
const $ = cheerio.load(item);
const title = $('a.teaser__header_text_link').text();
const partial = $('a.teaser__header_text_link').attr('href');
const address = `${baseUrl}${partial}`;
const time = $('time').text();
const description = $('div.teaser__body').text();
const author = $('div.teaser__secondary_info')
.text()
.trim();
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const res = await got.get(address);
const capture = cheerio.load(res.data);
const abstract = capture('#abstract .article-section__body').html();
let contents;
if (description !== '') {
contents = `${description}<br /><br /><h2 style="font-size: 14pt"><center>Abstract</center></h2>${abstract}`;
} else {
contents = `<h2"><center>Abstract</center></h2>${abstract}`;
}
const single = {
title,
author: author,
description: contents,
link: address,
guid: address,
doi: capture('meta[name="dc.identifier"]')[0].attribs.content,
pubDate: new Date(time).toUTCString(),
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: `eLife | ${topic}`,
link: url,
item: out,
};
};

View File

@ -1,60 +0,0 @@
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const base = `https://www.nature.com`;
const url = `${base}/nature/articles?type=research-highlight`;
const res = await got.get(url);
const $ = cheerio.load(res.data);
const list = $('.border-bottom-1.pb20').get();
const out = await Promise.all(
list.slice(0, 2).map(async (item) => {
const $ = cheerio.load(item);
const title = $('h3 > a').text();
const partial = $('h3 > a').attr('href');
const address = `${base}${partial}`;
const time = $('time').text();
let author;
if ($('.js-list-authors-3 li').length > 3) {
author =
$('.js-list-authors-3 li')
.slice(0, 1)
.text() + ' et al.';
} else {
author = $('.js-list-authors-3 li').text();
}
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const res = await got.get(address);
const capture = cheerio.load(res.data);
let figure = capture('figure .figure--bleed').html();
if (figure === null) {
figure = '';
}
let contents = capture('.article-item--open .article-item__body').html();
if (contents === null) {
contents = '';
}
const single = {
title,
author: author,
description: figure + contents,
link: address,
guid: address,
pubDate: new Date(time).toUTCString(),
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: `Nature | Research Highlight`,
description: `Nature, a nature research journal`,
link: url,
item: out,
};
};

View File

@ -1,80 +0,0 @@
// example usage: `/nature/news-and-comment/ng`
// The journals from NPG are run by different group of people,
// and the website of may not be consitent for all the journals
//
// This router has **just** been tested in:
// nbt: Nature Biotechnology
// neuro: Nature Neuroscience
// ng: Nature Genetics
// ni: Nature Immunology
// nmeth: Nature Method
// nchem: Nature Chemistry
// nmat: Nature Materials
// natmachintell: Nature Machine Intelligence
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const baseURL = `https://www.nature.com`;
const journal = ctx.params.journal;
const pageURL = `${baseURL}/${journal}/news-and-comment`;
const pageResponse = await got.get(pageURL);
const pageCapture = cheerio.load(pageResponse.data);
const pageDescription = pageCapture('meta[name="description"]').attr('content') || `Nature, a nature research journal`;
const pageTitleName = pageCapture('meta[name="WT.cg_n"]').attr('content') || `Nature (${journal})`;
const pageTitleSub = pageCapture('meta[name="WT.cg_s"]').attr('content') || 'News & Comment';
const list = pageCapture('.border-bottom-1.pb20').get();
const items = await Promise.all(
list.map(async (el) => {
const $ = cheerio.load(el);
const title = $('h3 > a').text();
const partial = $('h3 > a').attr('href');
const address = `${baseURL}${partial}`;
const brief = $('.hide-overflow.inline').text();
const time = $('time').text();
const author = $('.js-list-authors-3 li').text();
const articleType = $('p > span').attr('data-class');
const headerContents = `
<div>
<p style="color: #666">
<span>${articleType}</span>
<span>| </span>
<span>${author}</span>
</p>
</div>
`;
let briefContents = '';
if (brief !== '') {
briefContents = `
<div>
<h2 align="left">Brief</h2>
<p>${brief}</p>
</div>
`;
}
const contents = headerContents + briefContents;
const item = {
title,
author: author,
description: contents,
link: address,
guid: address,
pubDate: new Date(time).toUTCString(),
};
return Promise.resolve(item);
})
);
ctx.state.data = {
title: `${pageTitleName} | ${pageTitleSub}`,
description: pageDescription,
link: pageURL,
item: items,
};
};

View File

@ -1,54 +0,0 @@
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const base = `https://www.nature.com`;
const url = `${base}/nature/articles?type=news`;
const res = await got.get(url);
const $ = cheerio.load(res.data);
const list = $('.border-bottom-1.pb20').get();
const out = await Promise.all(
list.map(async (item) => {
const $ = cheerio.load(item);
const title = $('h3 > a').text();
const partial = $('h3 > a').attr('href');
const address = `${base}${partial}`;
const time = $('time').text();
let author;
if ($('.js-list-authors-3 li').length > 3) {
author =
$('.js-list-authors-3 li')
.slice(0, 1)
.text() + ' et al.';
} else {
author = $('.js-list-authors-3 li').text();
}
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const res = await got.get(address);
const capture = cheerio.load(res.data);
const contents = capture('.content .article__body').html();
const single = {
title,
author: author,
description: contents,
link: address,
guid: address,
pubDate: new Date(time).toUTCString(),
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: `Nature | Latest News`,
description: `Nature, a nature research journal`,
link: url,
item: out,
};
};

View File

@ -1,187 +0,0 @@
// example usage: `/nature/research/ng`
// The journals from NPG are run by different group of people,
// and the website of may not be consitent for all the journals
//
// This router has **just** been tested in:
// nature: Nature
// nbt: Nature Biotechnology
// neuro: Nature Neuroscience
// ng: Nature Genetics
// ni: Nature Immunology
// nmeth: Nature Method
// nchem: Nature Chemistry
// nmat: Nature Materials
// natmachintell: Nature Machine Intelligence
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const baseURL = `https://www.nature.com`;
const journal = ctx.params.journal || 'nature';
const pageURL = `${baseURL}/${journal}/research`;
const pageResponse = await got.get(pageURL);
const pageCapture = cheerio.load(pageResponse.data);
const pageDescription = pageCapture('meta[name="description"]').attr('content') || `Nature, a nature research journal`;
const pageTitleName = pageCapture('meta[name="WT.cg_n"]').attr('content') || `Nature (${journal})`;
const pageTitleSub = pageCapture('meta[name="WT.cg_s"]').attr('content') || 'Latest Research';
const list = pageCapture('.border-bottom-1.pb20').get();
const items = await Promise.all(
list.map(async (el) => {
const $ = cheerio.load(el);
const title = $('h3 > a').text();
const partial = $('h3 > a').attr('href');
const address = `${baseURL}${partial}`;
const brief = $('.hide-overflow.inline').text();
const time = $('time').text();
let author;
if ($('.js-list-authors-3 li').length > 3) {
author =
$('.js-list-authors-3 li')
.slice(0, 1)
.text() + ' et al.';
} else {
author = $('.js-list-authors-3 li').text();
}
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const itemResponse = await got.get(address);
const itemCapture = cheerio.load(itemResponse.data);
// Brief [obtain from entry of each item]
let briefContents = '';
if (brief !== '') {
briefContents = `
<div id="rss-journal-brief">
<h2 class="rss-journal-paragraph-title">Brief</h2>
<p class="rss-journal-paragraph-text">${brief}</p>
</div>
`;
}
// Abstract [obtain form address of each page]
const abs = itemCapture('div#Abs1-content.c-article-section__content > p').html();
let absContents = '';
if (abs !== null) {
absContents = `
<div id="rss-journal-abs">
<h2 class="rss-journal-paragraph-title">Abstract</h2>
<p class="rss-journal-paragraph-text">${abs}</p>
</div>
`;
}
// Info [obtain form address of each page]
const subject = itemCapture('li.c-article-subject-list__subject > a')
.map(function() {
const link = $(this).attr('href');
const name = $(this).text();
if (name !== '') {
return `<li class="rss-journal-tag-topic"><a href="${link}">${name}</a></li>`;
} else {
return '';
}
})
.get()
.join('');
const subjectContents = subject !== '' ? `<ul>${subject}</ul>` : '';
const citation = itemCapture('p.c-bibliographic-information__download-citation > a').attr('href');
const citationContents = citation !== undefined ? `<a href="${baseURL}${citation}">Download citation</a>` : '';
const doi = itemCapture('meta[name="DOI"]').attr('content');
const doiContents = doi !== undefined ? `<a href="https://doi.org/${doi}">DOI: ${doi}</a>` : '';
const pdf = itemCapture('meta[name="citation_pdf_url"]').attr('content');
const pdfContents = pdf !== undefined ? `<a href="${pdf}">Offical PDF</a>` : '';
const linkContents = '<ul>' + [citationContents, doiContents, pdfContents].filter((x) => x !== '').map((x) => `<li class="rss-journal-tag-icon">${x}</li>`) + '</ul>';
const infoContents = `
<div id="rss-journal-info">
<h2 class="rss-journal-paragraph-title">About this article</h2>
<p>Subjects:</p>
${subjectContents}
<br>
<p>Links:</p>
${linkContents}
</div>
`;
// Add style
const contentStyle = `
<style>
.rss-journal-paragraph-title {
color: #222;
padding: 0;
margin: 12px 0 12px;
font-family: "Harding","Lora",Palatino,Times,"Times New Roman",serif;
font-size: 1.8rem;
line-height: 1.4;
border-bottom: 1px solid #d5d5d5;
font-weight: 200;
}
.rss-journal-paragraph-text {
color: #222;
font-size: 1.2em;
font-family: Lora,Palatino,Times,"Times New Roman",serif;
padding: 0;
margin: 0 0 28px;
line-height: 1.5;
word-wrap: break-word;
}
.rss-journal-tag-topic {
line-height: 1.5;
color: #222;
font-size: 0.8rem;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
background-color: #dae5ea;
border-radius: 15px;
padding: 6px 6px;
font-weight: 700;
margin: 8px 4px 8px;
display:inline-block;
}
.rss-journal-tag-icon {
line-height: 1.5;
color:#fff;
font-size: 0.8rem;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
background-color:#ffb74d;
border-radius: 3px;
padding: 2px 4px;
font-weight: 700;
margin: 8px 4px 8px;
display:inline-block;
}
a:link.rss-journal-tag-topic, a:link.rss-journal-tag-icon {
color: white;
}
a:visited.rss-journal-tag-topic, a:link.rss-journal-tag-icon {
color: grey;
}
a:active.rss-journal-tag-topic, a:link.rss-journal-tag-icon {
color: hotpink;
}
</style>
`;
const contents = briefContents + absContents + infoContents + contentStyle;
const item = {
title,
author: author,
description: contents,
link: address,
guid: address,
pubDate: new Date(time).toUTCString(),
};
ctx.cache.set(address, JSON.stringify(item));
return Promise.resolve(item);
})
);
ctx.state.data = {
title: `${pageTitleName} | ${pageTitleSub}`,
description: pageDescription,
link: pageURL,
item: items,
};
};

View File

@ -1,66 +0,0 @@
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const baseUrl = `https://www.pnas.org`;
const tid = ctx.params.tid;
let url = `${baseUrl}/content/early/recent`;
if (tid !== 'latest') {
url = `${baseUrl}/content/by/section/${ctx.params.tid}`;
} else {
ctx.params.tid = 'Latest Research';
}
const res = await got.get(url);
const $ = cheerio.load(res.data);
const list = $('.highwire-citation-pnas-list-complete').get();
const out = await Promise.all(
list.map(async (item) => {
const $ = cheerio.load(item);
const title = $('.highwire-cite-title').text();
const partial = $('.highwire-cite-linked-title').attr('href');
const address = `${baseUrl}${partial}`;
let author;
if ($('.highwire-citation-authors span').length > 3) {
author = $('.highwire-citation-author.first').text() + ' et al.';
} else {
author = $('.highwire-citation-authors span').text();
}
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
const res = await got.get(address);
const capture = cheerio.load(res.data);
const significance = capture('.executive-summary').html();
const abstract = capture('.section.abstract').html();
let contents;
if (abstract !== null) {
contents = significance + abstract;
} else {
contents = significance;
}
const single = {
title,
author: author,
description: contents,
link: address,
guid: address,
doi: capture('meta[name="DC.Identifier"]')[0].attribs.content,
pubDate: new Date(capture('meta[name="DC.Date"]')[0].attribs.content).toUTCString(),
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: `PNAS | ${ctx.params.tid}`,
link: url,
item: out,
};
};

View File

@ -1,73 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const url = require('url');
const date = require('@/utils/date');
const base = 'https://www.ncbi.nlm.nih.gov';
module.exports = async (ctx) => {
const link = `${base}/pubmed/trending/`;
const response = await got.get(encodeURI(link));
const pageCapture = cheerio.load(response.data);
const list = pageCapture('.content div.rprt > div.rslt').get();
const out = await Promise.all(
list.map(async (elem) => {
const $ = cheerio.load(elem);
const title = $('p > a').text();
const partial = $('p > a').attr('href');
const address = url.resolve(base, partial);
const author = $('div.supp > p.desc').text();
const pubDate = date(
$('div.supp > p.details')
.text()
.split('. ')[1]
);
const item = {
title,
author,
pubDate,
link: encodeURI(address),
};
const value = await ctx.cache.get(address);
if (value) {
item.description = value;
} else {
const detail = await got.get(item.link);
const detailCapture = cheerio.load(detail.data);
let authorContents = '';
if (author !== '') {
authorContents = `
<div id="author-content">
<span style="color: grey">${author}</span>
</div>
`;
}
const abs = detailCapture('div.abstr > div').html();
let absContents = '';
if (abs !== null) {
absContents = `
<div id="abstract-content">
<h2 align="left">Abstract</h2>
<p>${abs}</p>
</div>
`;
}
item.description = authorContents + absContents;
ctx.cache.set(address, item.description);
}
return Promise.resolve(item);
})
);
ctx.state.data = {
title: 'PubMed | Trending Articles',
description: 'Trending Articles from PubMed Website',
link: link,
item: out,
};
};

View File

@ -1,125 +0,0 @@
// journals form AAAS publishing group
//
// science: Science
// advances: Science Advances
// immunology: Science Immunology
// robotics: Science Robotics
// stke: Science Signaling
// stm: Science Translational Medicine
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const journal = ctx.params.journal || 'science';
const baseURL = `https://${journal}.sciencemag.org`;
const pageURL = baseURL;
const pageResponse = await got.get(pageURL);
const pageCapture = cheerio.load(pageResponse.data);
const pageTitleName = pageCapture('head > title').text() || `Science (${journal})`;
// just select paper relative sections
const sectionList = ['research-articles', 'review', 'reports'];
const list = [].concat.apply(
[],
sectionList.map((section) => {
const sectionContent = pageCapture(`ul > li.issue-toc-section.issue-toc-section-${section}`).html();
if (sectionContent !== null) {
const sec = cheerio.load(sectionContent);
const sectionName = sec('h2').text();
const sectionList = sec('ul > li > div > div > article > div')
.append(`<div class="toc-section-type">${sectionName}</div>`)
.get();
return sectionList;
}
return [];
})
);
const out = await Promise.all(
list.map(async (item) => {
const $ = cheerio.load(item);
const title = $('h3').text();
const partial = $('h3 > a').attr('href');
const address = `${baseURL}${partial}`;
const section = $('div .toc-section-type').text();
let author;
const authorList = $('span.highwire-citation-authors > span.highwire-citation-author')
.map((_, el) => $(el).text())
.get();
if (authorList.length > 5) {
author = authorList.slice(0, 5).join(', ') + ' et al.';
} else {
author = authorList.join(', ');
}
const time = new Date($('p.highwire-cite-metadata > time').text()).toUTCString();
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
// contents
// section content
let sectionContents = '';
if (section !== '') {
sectionContents = `
<div id="content-section">
<span style="color: #d40016; text-transform: uppercase; font-weight: 700;">${section}</span>
</div>
`;
}
// brief content
const brief = $('div.highwire-cite-snippet > div > div > p').text();
let briefContents = '';
if (brief !== '') {
briefContents = `
<div id="content-brief">
<p>${brief}</p>
</div>
`;
}
const itemPage = await got.get(address);
const itemCapture = cheerio.load(itemPage.data);
const abs = itemCapture('div > div.article > div.section')
.map((_, el) => $(el).html())
.get()
.join('<br>');
// abs content
let absContents = '';
if (abs !== null) {
absContents = `
<div id="content-abs">
${abs}
</div>
`;
}
const contents = sectionContents + briefContents + absContents;
const single = {
title: title,
author: author,
description: contents,
link: address,
guid: address,
pubDate: time,
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: `${pageTitleName} | Current Issue`,
description: `Current Issue of ${pageTitleName}`,
link: baseURL,
item: out,
};
};

View File

@ -1,101 +0,0 @@
// only support Science journal
const cheerio = require('cheerio');
const got = require('@/utils/got');
module.exports = async (ctx) => {
const base = `https://science.sciencemag.org/content/early/recent`;
const res = await got.get(base);
const pageCapture = cheerio.load(res.data);
const list = pageCapture('ul > li > div > article > div').get();
const out = await Promise.all(
list.map(async (item) => {
const $ = cheerio.load(item);
const title = $('h3').text();
const partial = $('h3 > a').attr('href');
const address = `${base}${partial}`;
let author;
const authorList = $('span.highwire-citation-authors > span.highwire-citation-author')
.map(function(i, el) {
return $(el).text();
})
.get();
if (authorList.length > 5) {
author = authorList.slice(0, 5).join(', ') + ' <i>et al.</i>';
} else {
author = authorList.join(', ');
}
const time = new Date($('p.highwire-cite-metadata > time').text()).toUTCString();
const cache = await ctx.cache.get(address);
if (cache) {
return Promise.resolve(JSON.parse(cache));
}
// contents
// brief content
const brief = $('div.highwire-cite-snippet > div > div > p').text();
let briefContents = '';
if (brief !== '') {
briefContents = `
<div id="content-brief">
<p>${brief}</p>
</div>
`;
}
const itemPage = await got.get(address);
const itemCapture = cheerio.load(itemPage.data);
// section content
const section = itemCapture('header > div.overline').text();
let sectionContents = '';
if (section !== '') {
sectionContents = `
<div id="content-section">
<span style="color: #d40016; text-transform: uppercase; font-weight: 700;">${section}</span>
<span style="color: grey; text-transform: uppercase; font-weight: 700;">[Published Online]</span>
</div>
`;
}
// abs content
const abs = itemCapture('div > div.abstract-view > div.section')
.map(function(i, el) {
return $(el).html();
})
.get()
.join('<br>');
let absContents = '';
if (abs !== null) {
absContents = `
<div id="content-abs">
${abs}
</div>
`;
}
const contents = sectionContents + briefContents + absContents;
const single = {
title: title,
author: author,
description: contents,
link: address,
guid: address,
pubDate: time,
};
ctx.cache.set(address, JSON.stringify(single));
return Promise.resolve(single);
})
);
ctx.state.data = {
title: `Science | First Release`,
description: `Science, a research journal. For papers that published online.`,
link: base,
item: out,
};
};

View File

@ -1,58 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const utils = require('./utils');
module.exports = async (ctx) => {
const tag = ctx.params.tag;
const path = tag ? `news/tag/${tag}` : 'news/index';
const response = await got(path, {
method: 'GET',
prefixUrl: utils.host,
});
const data = response.data;
const $ = cheerio.load(data);
const title = $('title').text();
const description = $('meta[name="description"]').attr('content');
const newsitem = $('.newsitem');
const item = newsitem
.map((index, element) => {
const title = $(element)
.find('h3')
.find('a')
.text();
const a = $(element)
.find('p')
.find('a');
const link = utils.host + a.attr('href');
const image = $(element)
.find('img')
.attr('src');
const description = utils.setDesc(image, a.text());
const span = $(element).find('.space-right-m30');
const author = span
.text()
.replace('来源:', '')
.trim();
const date = utils.getDate(span.next().text());
const pubDate = utils.transDate(date);
const single = {
title: title,
link: link,
description: description,
author: author,
pubDate: pubDate,
};
return single;
})
.get();
ctx.state.data = {
title: title,
link: response.url,
description: description,
item: item,
};
};

View File

@ -1,79 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const utils = require('./utils');
const queryString = require('query-string');
module.exports = async (ctx) => {
const type = ctx.params.type;
const magazine = ctx.params.magazine;
const path = `paper/${type}/${magazine}`;
const response = await got(path, {
method: 'GET',
prefixUrl: utils.host,
headers: {
Cookie: 'closeFloatWindow=true; journalIndexViewType=list; journalSort=publishDate',
},
});
const data = response.data;
const $ = cheerio.load(data);
const title = $('title').text();
const description = $('meta[name="description"]').attr('content');
const newsitem = $('.magazine-text');
const item = await Promise.all(
newsitem
.map(async (index, element) => {
const news = $(element);
const a = news.find('.magazine-text-title').find('a');
const title = a.text();
const link = utils.host + a.attr('href');
const picId = news.find('.magazine-pic').attr('id');
const noPic = utils.host + '/css/images/nothesispic.jpg';
let imageUrl = noPic;
if (picId) {
const imageId = picId.substring(9);
const getLink = utils.host + '/attachment/getImgUrl';
imageUrl =
(await ctx.cache.tryGet(getLink, async () => {
const result = await got.get(getLink, {
searchParams: queryString.stringify({
attachmentId: imageId,
}),
});
return result.data;
})) || noPic;
}
const image = imageUrl;
const text = $(element)
.find('.magazine-description')
.text();
const description = utils.setDesc(image, text);
const span = news.find('.magazine-text-atten');
const arr = span.map((index, element) => $(element).text()).get();
const author = arr[1];
const date = utils.getDate(arr[0]);
const pubDate = utils.transDate(date);
const single = {
title: title,
link: link,
description: description,
author: author,
pubDate: pubDate,
};
return Promise.resolve(single);
})
.get()
);
ctx.state.data = {
title: title,
link: response.url,
description: description,
item: item,
};
};

View File

@ -1,16 +0,0 @@
const XmolUtils = {
host: 'https://www.x-mol.com',
transDate: (date) => new Date(`${date} GMT+0800`).toUTCString(),
getDate: (text) => {
const reg = /[1-9]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/;
if (typeof text === 'string') {
const arr = text.match(reg);
return arr && text.match(reg)[0];
} else {
return null;
}
},
setDesc: (image, text) => `<p><img src="${image}"></p><p>${text}</p>`,
};
module.exports = XmolUtils;