PubMed APIとGASで最新論文を取得する(メモ)

function searchAndSavePubMedArticles() {
  // 検索クエリのパラメータ
  // const searchTerms = [
    // '"acute heart failure"[title]', // タイトルに"acute heart failure"を含む
    // '"acute heart failure"[tiab]', // タイトルまたは要約に"acute heart failure"を含む
    // '"acute heart failure"[mesh]', // MeSHタグに"acute heart failure"を含む
    // '"acute heart failure"[majr]', // MeSHのメジャートピックとして"acute heart failure"を含む
    // '"acute heart failure"[abstract]', // 要約に"acute heart failure"を含む
    // '"acute heart failure"[text word]', // 論文の全文に"acute heart failure"を含む
    // '"acute heart failure"[other term]', // その他のフィールド(キーワードなど)に"acute heart failure"を含む
    // 'acute[All Fields] AND heart[All Fields] AND failure[All Fields]', // "acute"、"heart"、"failure"の各単語を含む
    // '"acute heart failure"[TW]', // テキストワード(タイトル、要約、MeSHタグ、その他のフィールドを含む)に"acute heart failure"を含む
    // '"acute heart failure"[NCASE]', // "acute heart failure"という語句を含む(大文字と小文字を区別しない)
    // '"acute heart failure"[AD]', // 著者のアフィリエーション(所属)に"acute heart failure"を含む
    // '"acute heart failure"[JOUR]', // ジャーナル名に"acute heart failure"を含む
  // ];

  const searchTerms = [
  '"developmental disability"[tiab]', // 発達障害
  '"intellectual isability"[tiab]', // 知的発達症
  '"dearning disorder"[tiab]', // 限局性学習症
  '"developmental coordination disorder"[tiab]', // DCD
  '"developmental disabilities"[tiab]', // 発達障害
  '"autism"[tiab]', // 自閉症スペクトラム障害
  '"attention deficit"[tiab]', // 注意欠陥多動性障害
  '"attachment"[mesh]', // 愛着障害
  '"special education"[tiab]', // 特別支援教育
  '"social skills"[mesh]', // 社会的スキル
  '"behavior therapy"[tiab]', // 行動療法
  '"down syndrome"[tiab]', // ダウン症候群
  '"neurodevelopmental disorders"[tiab]', // 神経発達障害
  ];


  //今日の日付をDateオブジェクトで取得
  let today = new Date();
  //日付フォーマットをyyyy年MM月dd日に変更
  today = Utilities.formatDate(today,'JST','yyyy/MM/dd');

  //現時刻を取得
  var yesterday = new Date();

  //昨日の日付を出力
  Logger.log(Utilities.formatDate(yesterday.setDate(today.getDate() - 1), 'JST', 'yyyy/MM/dd'));

  const combineWith = 'OR'; // 'AND' または 'OR' を指定
  const filters = 'AND hasabstract AND (japanese[lang] OR english[lang]) AND casereports[filter] AND humans[filter]';
  const minDate = '2023/01/01';
  const maxDate = '2023/12/31';
  const retMax = 50;

  // 検索用語の組み合わせ
  const combinedSearchTerm = searchTerms.join(` ${combineWith} `);

  // PubMed検索の実行
  const pubmedIds = searchPubMed(combinedSearchTerm + filters, minDate, maxDate, retMax);

  // 論文の詳細情報を取得し、スプレッドシートに保存
  const articleData = fetchArticleDetails(pubmedIds);
  saveToSpreadsheet(articleData);
}

function searchPubMed(term, minDate, maxDate, retMax) {
  const baseUrl = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi';
  const params = {
    db: 'pubmed',
    term: term,
    retmode: 'json',
    retstart: 0,
    retmax: retMax,
    datetype: 'pdat',
    mindate: minDate,
    maxdate: maxDate,
    apikey: ''
  };

  const response = UrlFetchApp.fetch(baseUrl + '?' + encodeParams(params));
  const data = JSON.parse(response.getContentText());
  return data.esearchresult.idlist;
}

function fetchArticleDetails(pubmedIds) {
  const baseUrl = 'https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi';
  const params = {
    db: 'pubmed',
    id: pubmedIds.join(','),
    retmode: 'xml',
    rettype: 'abstract'
  };

  const response = UrlFetchApp.fetch(baseUrl + '?' + encodeParams(params));
  const xml = response.getContentText();
  const document = XmlService.parse(xml);
  const articles = document.getRootElement().getChildren('PubmedArticle');


  const articleData = [];
  let pubmedText = ""

  for (const article of articles) {
    const pmid = article.getChild('MedlineCitation').getChild('PMID').getText();
    const title = article.getChild('MedlineCitation').getChild('Article').getChild('ArticleTitle').getText();
    const abstractText = article.getChild('MedlineCitation').getChild('Article').getChild('Abstract')?.getChild('AbstractText')?.getText() || '';
    const translatedTitle = LanguageApp.translate(title, 'en', 'ja');
    const translatedAbstract = LanguageApp.translate(abstractText, 'en', 'ja');
    const url = `https://pubmed.ncbi.nlm.nih.gov/${pmid}/`;

    const year = article.getChild('PubmedData').getChild('History').getChildren('PubMedPubDate').find(pubDate => pubDate.getAttribute('PubStatus').getValue() === 'pubmed')?.getChild('Year').getText() || '';
    const month = article.getChild('PubmedData').getChild('History').getChildren('PubMedPubDate').find(pubDate => pubDate.getAttribute('PubStatus').getValue() === 'pubmed')?.getChild('Month').getText() || '';
    const day = article.getChild('PubmedData').getChild('History').getChildren('PubMedPubDate').find(pubDate => pubDate.getAttribute('PubStatus').getValue() === 'pubmed')?.getChild('Day').getText() || '';

    const date = `${year}/${month}/${day}`;

    articleData.push([translatedTitle, translatedAbstract, date, pmid, url, title, abstractText]);
    pubmedText += `${translatedTitle}\n${translatedAbstract}\n${url}\n\n`;
  }

  if (articleData.length > 0) {
    sendChat(pubmedText)
  }

  return articleData;
}

function saveToSpreadsheet(data) {
  const sheetName = 'pubmed';
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName) || SpreadsheetApp.getActiveSpreadsheet().insertSheet(sheetName);
  
  // 既存のデータのPMIDを取得
  const existingData = sheet.getDataRange().getValues();
  const existingPMIDs = existingData.slice(1).map(row => row[3]);

  // 新しいデータをフィルタリングして、重複しないものだけを残す
  const newData = data.filter(row => !existingPMIDs.includes(row[3]));

  // 新しいデータがある場合のみ、スプレッドシートに追加
  if (newData.length > 0) {
    sheet.getRange(sheet.getLastRow() + 1, 1, newData.length, newData[0].length).setValues(newData);
  }
}

function encodeParams(params) {
  return Object.keys(params).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(params[key])).join('&');
}

この記事が気に入ったらサポートをしてみませんか?