├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── lib ├── arex.js ├── data │ ├── AFINN-zh_cn.json │ ├── AFINN-zh_cn.txt │ ├── D_U_protection.json │ ├── index.js │ ├── summary.json │ └── user-words.txt ├── httprequest.js ├── isummary.js ├── levenshtein.js ├── node-summary.js ├── pagerank.js └── sentiment.js ├── package.json ├── server.js └── test ├── compare-summary.js ├── echart-line.html ├── summary-comparation.csv ├── test-summarize.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.17.0-alpine 2 | WORKDIR /app 3 | COPY . /app 4 | CMD ["sh", "-c", "node server.js"] 5 | EXPOSE 3824 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Cherokee 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # arex 2 | node.js实现自动提取文章正文, 标题, 发布日期。自动生成文章摘要. 3 | 4 | # Node版本 5 | 建议v6.17.0 6 | 7 | 8 | # Http 服务 9 | 10 | 运行 11 | ```bash 12 | node server.js 13 | ``` 14 | 15 | 客户端链接 16 | 17 | ```bash 18 | curl -X POST -d '{"url":"https://export.shobserver.com/baijiahao/html/411796.html","size":100,"smooth":false}' http://localhost:3824|jq -r . 19 | ``` 20 | 21 | #安装 22 | ```shell 23 | npm install arex 24 | ``` 25 | 26 | #使用例子: 27 | ```javascript 28 | var arex = require('arex'); 29 | //example 1, 给定网址自动抓取,提取正文,生成摘要 30 | arex.get_article('http://finance.sina.com.cn/consume/puguangtai/2016-03-15/doc-ifxqhmve9227502.shtml',120,(err,result)=>{ 31 | //120: 摘要长度为120,如果不需要生成摘要此参数传入false. 32 | //result: {"title":"...","content":"....", "summary":"...", "pubdate":"..."} 33 | console.log(result['content']); 34 | }); 35 | 36 | //example 2, 给html内容,提取正文,生成摘要 37 | result = arex.get_article_sync('',120);//result: {"title":"...","content":"....", "summary":"...", "pubdate":"..."} 38 | 39 | //example 3, 给html内容,生成摘要 40 | //summarize(content, exptd_len=120, shingle=false, min=150, max=350, filter=[], title) 41 | //shingle的意义: 以摘要长度的句子组合为单位计算权重,shingle为false则以自然句为单位计算权重, filter是过滤规则,符合规则的段落都会被过滤不作为摘要 42 | var summary = arex.summarize('.......', 120, true); 43 | var summary = arex.summarize('.......', 0.04, true, 100, 300);//摘要长度比例 4%, 最短 100, 最长 300 44 | ``` 45 | 46 | #测试 47 | 48 | ##获取源码 49 | ```shell 50 | git clone https://github.com/ahkimkoo/arex.git 51 | ``` 52 | 53 | ##测试某个网页的抽取 54 | ```shell 55 | cd arex 56 | npm install 57 | node test/test.js http://finance.sina.com.cn/consume/puguangtai/2016-03-15/doc-ifxqhmve9227502.shtml 120 58 | ``` 59 | 120表示期望文摘的长度 60 | 61 | ##算法说明 62 | * 正文抽取: 基于行块密度分布来抽取正文, 每个行块由若干自然段落组成。 63 | * 标题抽取: 分别从正文附近抽取h1标签,从title标签取值,取最可能是标题的那一个。 64 | * 发布日期抽取: 用正则表达式抽取正文附近的日期。(有误差)。 65 | * 自动文摘: sentense rank算法,参照pagerank算法的实现,可以指定期望的文摘长度。优化点:加入了神经网络模型判断一句话是否适合作为摘要。 66 | 67 | 68 | 69 | 70 | # arex 71 | node.js article extractor, automatic summarization. 72 | 73 | #Install 74 | ```shell 75 | npm install arex 76 | ``` 77 | 78 | #Usage: 79 | ```javascript 80 | var arex = require('arex'); 81 | //example 1 82 | arex.get_article('http://finance.sina.com.cn/consume/puguangtai/2016-03-15/doc-ifxqhmve9227502.shtml',120,(err,result)=>{ 83 | //120: summary limited, if you do not need summary set it to false. 84 | //result: {"title":"...","content":"....", "summary":"...", "pubdate":"..."} 85 | console.log(result['content']); 86 | }); 87 | 88 | //example 2 89 | result = arex.get_article_sync('',120);//result: {"title":"...","content":"....", "summary":"...", "pubdate":"..."} 90 | 91 | //example 3 92 | //summarize(content, exptd_len=120, shingle=false, min=150, max=350, filter=[], title) 93 | var summary = arex.summarize('.......', 120, true); 94 | var summary = arex.summarize('.......', 0.04, true, 100, 300);//summary ratio 4%, min length 100, max length 300 95 | ``` 96 | 97 | #Test 98 | 99 | ##get source 100 | ```shell 101 | git clone https://github.com/ahkimkoo/arex.git 102 | ``` 103 | 104 | ##test link 105 | ```shell 106 | cd arex 107 | npm install 108 | node test/test.js http://finance.sina.com.cn/consume/puguangtai/2016-03-15/doc-ifxqhmve9227502.shtml 120 109 | ``` 110 | 111 | ##About algorithm 112 | * article extractor: based density of article blocks, a bock consists of a number of natual lines. 113 | * title extracor: h1 tag or title tag, choose the best one. 114 | * pubdate extractor: regex extraction nearby the begging or article. 115 | * summarizer: based sentense rank, similar pagerank. Optimization: neural network model to determine whether a sentence is suitable as a summary. 116 | -------------------------------------------------------------------------------- /lib/arex.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const httpreq = require('./httprequest.js'); 3 | const sentiment_zh = require('./sentiment.js'); 4 | const Summarizer = require('./node-summary.js'); 5 | const summarizer = new Summarizer(true); 6 | 7 | /** 8 | * get page html via http.get 9 | * @param {[string]} url [link] 10 | * @param {Function} callback [description] 11 | * @return {[string]} [html string] 12 | */ 13 | const get_page = function(url,callback){ 14 | http.get(url, (res) => { 15 | var body = ''; 16 | res.on('data', function(d) { 17 | body += d; 18 | }); 19 | res.on('end', function() { 20 | callback(null,body); 21 | }); 22 | }).on('error', (e) => { 23 | console.error(`Got error: ${e.message}`); 24 | callback(e); 25 | }); 26 | } 27 | 28 | /** 29 | * get blocks that split by block tag 30 | * @param {[string]} html [html string] 31 | * @return {[array]} [blolck array] 32 | */ 33 | const get_blocks = function(html){ 34 | const line_break_tags = ['address','article','aside','audio','blockquote','canvas', 35 | 'dd','div','dl','fieldset','figcaption','figure','footer','form', 36 | 'h1','h2','h3','h4','h5','h6','header','hgroup','hr','noscript','ol','output','p','pre','section', 37 | 'table','tr','tfoot','ul','video','img','br']; 38 | const splter = line_break_tags.join('|'); 39 | html = html.replace(//igm,''); 40 | html = html.replace(//igm,''); 41 | html = html.replace(//igm,''); 42 | html = html.replace(/[\n\t\r]+/igm,''); 43 | let split_regx = new RegExp('(<(?:'+splter+')[^>]*?>)','ig'); 44 | html = html.replace(split_regx,'\n$1'); 45 | html = html.replace(/<\/?[^>]*?>/ig,''); 46 | html = html.replace(/&[a-z]+;/ig,''); 47 | html = html.replace(/&#(\d+);/g, function(match, dec) { 48 | return String.fromCharCode(dec); 49 | }); 50 | let paragraphs = html.split('\n'); 51 | return paragraphs.map(line=>{ 52 | return line.replace(/\s{2,}/gm,' ').replace(/^\s+$/gm,''); 53 | }); 54 | } 55 | 56 | /** 57 | * Specify deepth n, block score is the length from the block to the following n block. 58 | * @param {[type]} blocks [description] 59 | * @param {[type]} deep [description] 60 | * @return {[Array]} [score of each block] 61 | */ 62 | const get_block_score = function(blocks, deep){ 63 | let block_score = []; 64 | for(let i=0;i{ 81 | let fs = require('fs'); 82 | let path = require('path'); 83 | let filepath = path.resolve(__dirname,'..','test','line-data.js'); 84 | fs.writeFileSync(filepath, `var blocks = ${JSON.stringify(blocks)};\n`,{'encoding':'utf-8', 'flag':'w+'}); 85 | let blocks_length = blocks.map(function(x) { 86 | return x.length; 87 | }); 88 | fs.writeFileSync(filepath, `var blocks_length = ${JSON.stringify(blocks_length)};\n`,{'encoding':'utf-8', 'flag':'a+'}); 89 | fs.writeFileSync(filepath, `var blocks_score = ${JSON.stringify(blocks_score)};\n`,{'encoding':'utf-8', 'flag':'a+'}); 90 | fs.writeFileSync(filepath, `var position = ${JSON.stringify(position)};\n`,{'encoding':'utf-8', 'flag':'a+'}); 91 | } 92 | 93 | /** 94 | * Block group that split by tripple blank block 95 | * @param {[type]} block_score [description] 96 | * @return {[array]} block group[start pisition, end position, rate] 97 | */ 98 | const jedge_article_block = function(block_score){ 99 | // for(let i=0;i${blocks[i].substring(0,20)}#`); 103 | // } 104 | let block_groups = []; 105 | let seek_start = true; 106 | let start_point = 0; 107 | let total_length = 0; 108 | let max_block_length = 0; 109 | for(let i=0;i0){ 112 | if(seek_start){ 113 | start_point = i; 114 | seek_start = false; 115 | } 116 | total_length += block_score[i]; 117 | }else{ 118 | if(!seek_start){ 119 | let rate = Math.pow(max_block_length,2) / (total_length/(i-start_point)); 120 | block_groups.push([start_point,i,rate]); 121 | seek_start = true; 122 | total_length = 0; 123 | max_block_length = 0; 124 | } 125 | } 126 | } 127 | block_groups.sort((a,b)=>{ 128 | return b[2]-a[2]; 129 | }) 130 | return block_groups; 131 | } 132 | 133 | /** 134 | * get article title 135 | * @param {[type]} html [description] 136 | * @return {[type]} [description] 137 | */ 138 | const get_title = function(html){ 139 | let h1_regex = new RegExp(']*?>([^<]+)','i'); 140 | let h1_matched = h1_regex.exec(html); 141 | 142 | let title_regex = new RegExp(']*?>([^<]+)','i'); 143 | let title_matched = title_regex.exec(html); 144 | 145 | let title = (h1_matched && h1_matched.length>1) ? h1_matched[1] : ((title_matched && title_matched.length)>1 ? title_matched[1] : ''); 146 | 147 | if(h1_matched&&h1_matched.length>1&&title_matched && title_matched.length){ 148 | var tmch = title_matched[1].replace(/(?:\n|\r)/gm,''); 149 | var hmch = h1_matched[1].replace(/(?:\n|\r)/gm,''); 150 | if(tmch && tmch.indexOf(hmch.substring(0,10))<0)title = tmch; 151 | } 152 | return title.replace(/(?:\n|\r)/gm,'').trim(); 153 | } 154 | 155 | /** 156 | * get pubdate by regex 157 | * @param {[type]} html [description] 158 | * @return {[type]} [description] 159 | */ 160 | const get_pubdate = function(html){ 161 | let pubdate = ''; 162 | html = html.replace(//igm,''); 163 | html = html.replace(//igm,''); 164 | html = html.replace(//igm,''); 165 | let pb_regex = new RegExp('([\\d\\-\u5e74\u6708\u65e5]{8,15}\\s?\\d{1,2}(?:\:|\:)\\d{1,2})','img'); 166 | let matched = pb_regex.exec(html); 167 | if(matched&&matched.length>1)pubdate = matched[1]; 168 | return pubdate; 169 | } 170 | 171 | /** 172 | * get pubdate that closed to article. 173 | * @param {[type]} blocks [description] 174 | * @param {[type]} start_pos [description] 175 | * @return {[type]} [description] 176 | */ 177 | const get_pubdate_base_block = function(blocks,start_pos){ 178 | let pubdate = ''; 179 | let pb_regex = new RegExp('(\\d{4}(?:\\-|\\u5e74)\\d{1,2}(?:\\-|\\u6708)\\d{1,2}[\\s\\u65e5\\d\\:]*)','img'); 180 | for(let i=start_pos;i>=0;i--){ 181 | let matched = pb_regex.exec(blocks[i]); 182 | if(matched&&matched.length>1){ 183 | pubdate = matched[1]; 184 | break; 185 | } 186 | } 187 | return pubdate; 188 | } 189 | 190 | /** 191 | * filter none content tags 192 | * @param {[type]} html [description] 193 | * @return {[type]} [description] 194 | */ 195 | const filterNoneContentTags = function(html){ 196 | return html 197 | .replace(//img,'') 198 | .replace(//img,'') 199 | .replace(//img,'') 200 | .replace(/]+?>/ig,'') 201 | .replace(//igm, ''); 17 | html = html.replace(//igm, ''); 18 | html = html.replace(//igm, ''); 19 | html = html.replace(/<\/?[^>]*?>/ig, ''); 20 | html = html.replace(/&[a-zA-Z]+;/ig, ''); 21 | html = html.replace(/[\n\t\r]+/igm, ''); 22 | html = html.replace(/[\s]+/igm, ''); 23 | return html; 24 | } 25 | 26 | 27 | if(process.argv.length>2){ 28 | let id = parseInt(process.argv[2]); 29 | let sql = `SELECT 30 | a.id, 31 | b.title, 32 | b.url, 33 | b.summary, 34 | b.content, 35 | a.score 36 | FROM 37 | fe_avnews a, 38 | fe_articles b 39 | WHERE 40 | a.id = ${id} 41 | AND a.article_id = b.id 42 | LIMIT 1;`; 43 | pool.query(sql, (err, ret) => { 44 | if(err)throw err; 45 | if(ret.length>0){ 46 | let article = ret[0]; 47 | console.log('TITLE:::',article['title']); 48 | console.log('SUMMARY:::',article['summary']); 49 | console.log('NEW SUMMARY:::',arex.summarize(article['content'], 0.04, false, 50, 80,[],article['title'])); 50 | } 51 | process.exit(); 52 | }); 53 | }else{ 54 | let sql = `SELECT 55 | a.id, 56 | b.title, 57 | b.url, 58 | b.summary, 59 | b.content, 60 | a.score 61 | FROM 62 | fe_avnews a, 63 | fe_articles b 64 | WHERE 65 | a.create_time > SUBSTR(NOW() FROM 1 FOR 10) 66 | AND b.origin <> '交易所' 67 | AND a.article_id = b.id 68 | ORDER BY score DESC 69 | LIMIT 500;`; 70 | 71 | pool.query(sql, (err, ret) => { 72 | if(err)throw err; 73 | async.mapLimit( 74 | ret, 75 | 10, 76 | (article, cb)=>{ 77 | let new_summary = arex.summarize(article['content'], 0.04, false, 50, 80,[],article['title']).replace(/\"/ig,'“'); 78 | boson.summarize( 79 | article['title'], 80 | getTextFromHtml(article['content']), 81 | 80, 82 | (err,smy)=>{ 83 | console.log(article['id']); 84 | console.log(article['title']); 85 | console.log(new_summary); 86 | console.log('\n'); 87 | if(err)console.error(err); 88 | cb(null, [ 89 | article['id'], 90 | article['title'].replace(/\"/ig,'“'), 91 | article['summary'] ? article['summary'].replace(/\"/ig,'“') : '', 92 | new_summary, 93 | smy, 94 | article['url'] 95 | ]); 96 | } 97 | ); 98 | }, 99 | (err, paragraphs)=>{ 100 | paragraphs.unshift(['ID','标题','摘要(V2)','摘要(V3)','摘要(Boson)','网址']); 101 | fs.writeFile('summary-comparation.csv', paragraphs.join(new Buffer('\xEF\xBB\xBF', 'binary')+'\n'), (err) => { 102 | if(err)throw err; 103 | else console.log('dump to summary-comparation.csv'); 104 | process.exit(); 105 | }); 106 | } 107 | ); 108 | }); 109 | } 110 | -------------------------------------------------------------------------------- /test/echart-line.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 文章行块密度 8 | 9 | 10 |

文章行块密度

11 |
12 |
13 |
14 | 15 |
16 | 60 | 61 | -------------------------------------------------------------------------------- /test/test-summarize.js: -------------------------------------------------------------------------------- 1 | const arex = require('../lib/arex.js'); 2 | 3 | const html = `

  专题:2020年诺贝尔奖

  新浪科技讯 北京时间10月5日消息,2020年诺贝尔生理学或医学奖揭晓:美国科学家Harvey J。 Alter,英国科学家 Michael Houghton 和美国科学家Charles M。 Rice 三人 获奖,获奖理由:发现丙型肝炎病毒。

  有史以来的第一次,丙型肝炎病毒现在可以被治愈。2020年诺贝尔生理学或医学奖获奖者们的发现,揭示了慢性肝炎其余病例的病因,并使得血液检查成为可能,新的药物也拯救了数百万人的生命。

  今年的诺贝尔生理学和医学奖授予为抗击血源性肝炎做出决定性贡献的三位科学家。血源性肝炎是一种主要的全球健康问题,会导致世界各地的人罹患肝硬化和肝癌。

  Harvey J。 Alter、Michael Houghton和Charles M。 Rice的重大发现使我们能够鉴定一种新的病毒——丙型肝炎病毒。在他们的工作之前,尽管甲型肝炎和乙型肝炎病毒的发现至关重要,但大多数血源性肝炎病例仍然无法解释。丙型肝炎病毒的发现揭示了其余慢性肝炎病例的原因,并使验血和新药物成为可能,从而挽救了数百万人的生命。

  详细解读:

肝炎主要有两种形式。其一是由甲型肝炎病毒引起的急性疾病,该病毒通过被污染的水和食物传播。另一种是有乙型肝炎病毒或丙型肝炎病毒(今年的诺贝尔奖)引起的。这种血源性肝炎通常是一种慢性疾病,可能会发展为肝硬化和肝细胞癌。  肝炎主要有两种形式。其一是由甲型肝炎病毒引起的急性疾病,该病毒通过被污染的水和食物传播。另一种是有乙型肝炎病毒或丙型肝炎病毒(今年的诺贝尔奖)引起的。这种血源性肝炎通常是一种慢性疾病,可能会发展为肝硬化和肝细胞癌。

  肝炎——人类健康的全球威胁

  肝炎(hepatitis),是希腊语中的“肝”和“炎症”一词的组合。肝炎主要由病毒感染引起,但酗酒、环境毒素和自身免疫疾病等也是重要的原因。二十世纪四十年代,人们发现主要有两种类型的传染性肝炎。第一种成为甲型肝炎(hepatitis A),其通过被污染的水或事物传播,但对患者几乎没有长期影响。第二种类型主要通过血液和体液传播。因为可以导致慢性疾病,并发展为肝硬化和肝癌(图1),这种类型的肝炎威胁更严重。这种类型的肝炎是隐性的,因为健康个体在感染之后,可能会经过许多年才会显现出严重的并发症。血源性肝炎与高发病率和高死亡率相关,每年在全球范围内造成一百多万人死亡,从而使其成为与HIV感染和结核病相当的全球性健康问题。

  传染源未知

  成功干预传染病的关键在于确定病原体。二十世纪六十年代,巴鲁克·布伦伯格(Baruch Blumberg)确定,一种形式的血源性肝炎由被称为乙型肝炎病毒的病毒所致,这一发现促进了诊断检测和有效疫苗的开发。布伦伯格也因此获得了1976年的诺贝尔生理学或医学奖。

  当时,Harvey J。 Alter正在美国国家卫生研究院(NIH)研究接受输血的患者中患上肝炎的情况。尽管针对新发现的乙型肝炎病毒的血液检测确实减少了输血相关的肝炎病例数,但Alter及其同事仍证明,还有大量肝炎病例存在。在此期间,甲型肝炎病毒感染的检测也已经开发了出来。但很明显,甲型肝炎病毒无法解释这些原因不明病例。

  令人担忧的是,大量输血者由于未知的传染原而患上慢性肝炎。Alter及其同事发现,这些肝炎患者的血液可以将疾病传染给黑猩猩,这是人类之外唯一的易感宿主。随后的研究还表明,未知的传染原具有病毒的特征。Alter的系统研究定义了一种新型的、独特的慢性病毒性肝炎。这种神秘的疾病被称为“非甲型、非乙型”肝炎。

  丙型肝炎病毒的鉴定

  这种新型病毒的鉴定具有重要的意义,研究者使用了所有传统的病毒搜索技术,但在十多年的时间里,该病毒依然无法分离出来。在制药公司Chiron工作的Michael Houghton承担了分离病毒基因序列的艰巨工作。他和同事从一只被感染的黑猩猩的血液中采集了核酸,从中收集了一组DNA片段。这些片段大部分来自黑猩猩自身的基因组,但研究人员估计,一些片段可能来自这种未知的病毒。假设肝炎患者的血液中含有抗病毒抗体,研究人员就可以利用患者的血清来鉴定编码病毒蛋白的克隆病毒DNA片段。经过全面的搜寻,他们发现了一个阳性的克隆。进一步的研究表明,该克隆来自一种新的属于黄病毒科的RNA病毒,被命名为丙型肝炎病毒。慢性肝炎患者中抗体的存在强烈暗示了这种病毒就是缺失的病原体。

  Harvey J。 Alter对输血相关性肝炎的系统研究表明,一种未知病毒是慢性肝炎的常见病因。Michael Houghton使用了一种未经验证的策略,分离出一种名为丙型肝炎病毒(Hepatitis C virus)的新病毒的基因组。Charles M。 Rice提供了最终的证据,表明仅丙型肝炎病毒就能导致肝炎。

  丙型肝炎病毒的发现是决定性的,但是这个谜题的另一关键部分尚未解答:单是病毒就能导致肝炎吗?为了回答这个问题,科学家们必须研究克隆的病毒是否能够复制并导致疾病。华盛顿大学圣路易斯分校的研究者Charles M。 Rice和其他研究RNA病毒的小组注意到,在丙型肝炎病毒基因组末端有一个此前未被识别的区域,他们怀疑该区域可能对病毒复制很重要。Charles M。 Rice还在分离的病毒样本中观察到遗传变异,并推测其中一些可能会阻碍病毒复制。通过基因工程,Charles M。 Rice获得了丙型肝炎病毒的RNA变异,其中包括新定义的病毒基因组区域,不存在失活基因变异。当这种RNA被注射到黑猩猩的肝脏时,在它们的血液中检测到了病毒,并观察到了与患有这种慢性疾病的人类相似的病理变化。这是最后的证据,证明单单丙型肝炎病毒就可以导致不明原因的输血介导型肝炎病例。

  今年诺奖发现的重要意义

  今年诺奖获得者对于丙型肝炎病毒的发现是人类与病毒对抗过程中取得的一场里程碑式胜利(图2)。由于他们的这项发现,我们才能拥有针对这一病毒的高灵敏血液测试,并在世界的很多地区基本消除输血性肝炎的发生,从而极大增进了全球健康。他们的发现同时也让直接作用于丙肝的抗病毒药物研发成为可能。历史上第一次,这项疾病现在可以被治愈,从而燃起了在全球范围内根除丙型肝炎的希望。而为了达成这项目标,国际社会需要采取更多措施,让全球各地的人们能够获得所需的血液检测和抗病毒药物。

  获奖人介绍:

  Harvey J。 Alter于1935年出生于纽约。他在罗切斯特大学医学院获得医学学位,并在斯特朗纪念医院和西雅图大学医院接受内科训练。1961年,他加入美国国家卫生研究院(NIH)担任临床助理。在乔治敦大学任职数年之后,他于1969年回到NIH,加入临床中心的输血医学系,担任高级研究员。

  Michael Houghton出生于英国。1977年,他在伦敦国王学院获得博士学位。1982年,他加入了G。 D。 Searle & Company公司,之后又在加利福尼亚州埃默里维尔的Chiron公司任职。他于2010年迁往加拿大阿尔伯塔大学,现为加拿大卓越研究教授,主攻病毒学;他还是阿尔伯塔大学的“李嘉诚教授”,并兼任李嘉诚应用病毒学研究所所长。

  Charles M。 Rice 1952年出生于萨克拉门托。1981年,他在加州理工学院获得博士学位,并在1981-1985年期间接受博士后培训。1986年,他在圣路易斯的华盛顿大学医学院建立了自己的研究小组,并于1995年成为全职教授。自2001年以来,他一直是纽约洛克菲勒大学的教授。2001年至2018年期间,他担任洛克菲勒大学丙型肝炎研究中心的科学和执行主任,目前仍在该中心工作。

`; 4 | var summary = arex.summarize(html, 200, true); 5 | 6 | console.log(summary); -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var arex = require('../lib/arex.js'); 2 | 3 | if(process.argv.length>2){ 4 | arex.get_article(process.argv[2],process.argv[3]?parseInt(process.argv[3]):200,(err,result)=>{ 5 | console.log(result); 6 | }); 7 | }else console.log('useage: node test.js [link]'); --------------------------------------------------------------------------------