0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Axivから文献一覧を被引用数を追加して取得

Posted at

概要

  • arXivから文献一覧を被引用数を追加して取得する方法を忘備録として記載する。取得にはPythonを使用
  • arXivのサイトだけでは引用数を確認できなかったため、Schemantic Scholarを活用する
  • なお、本内容は以下のサイトを主に参考にした。ただし、パッケージ等の更新により修正が必要であったために投稿する
  • 使用パッケージ(Python)
    • arxiv (arXiv APIのPythonラッパー)
    • requests
    • numpy
    • pandas
    • openpyxl

文献の抽出

arXivからの文献抽出

  • Pythonのarxivのパッケージを用いて文献を抽出する
  • Query(検索条件)の作成方法は以下を参照
    • 5.1. Details of Query Construction
    • ただし、上記ではスペースには"+"を使用する記載があるが、arxivのパッケージでは"+"を用いると想定した検索ができず
    • "+"ではなく普通にスペースを使用することで解決
  • 例として、以下の条件で検索したプログラムを示す
    • 検索条件:要約に"RAG"を含む。カテゴリは"AI"。期間は2021/1/1から2025/5/4

  • (補足) QueryのPrefix一覧

    prefix explanation
    ti Title
    au Author
    abs Abstract
    co Comment
    jr Journal Reference
    cat Subject Category
    rn Report Number
    id Id (use id_list instead)
    all All of the above

プログラム例

  • arxivから一覧の取得するプログラムの例を示す
  • resultsはジェネレータである点に注意する。pandasのDataFrameへの変換例は後述する
import arxiv


def set_client_search(query: str):
    client = arxiv.Client(
        page_size = 1000,   # 1リクエストでの抽出数。2000以下, default 100
        delay_seconds = 3.0,  # 遅延時間(秒)。rxivの規約上、1リクエスト以上/3秒はNG
    )

    search = arxiv.Search(
        query = query,  # 検索文字, str
        # id_list = [],   # 文献ID. List[str]
        max_results = 2000,  # 最大抽出数. 30000以下
        sort_by = arxiv.SortCriterion.Relevance,   # Relevance, LastUpdatedDate, SubmittedDate
        sort_order = arxiv.SortOrder.Descending,   # Ascending, Descending
    )
    return client, search

# 要約にRAGを含み、カテゴリ: AI、期間; 20210101-20250504で検索
query = "abs:RAG AND cat:cs.AI AND submittedDate:[202101010000 TO 202505042359]"  
client, search = set_client_search(query)
results = client.results(search)

DataFrame型に変換

  • 取得したresultsをDataFrame型に変換する
  • 結果項目の詳細はarXiv API User Manual: Details of Atom Results ReturnedarXivを参照のこと
  • 検索の関連度に関するパラメータが結果に含まれないため、"Relevance"として一致度を設定
  • 一致度(Relevance)は、arxivでの検索結果をRelevanceでDescendingとしてソートしていることを利用して、0-1となるようにした

プログラム例

import pandas as pd

def convert_to_str(vals):  # 文字列に変換
    if isinstance(vals, list):
        return list(map(str, vals))
    elif vals is None:
        return vals
    else:
        return str(vals)
        
def create_df(results):
    res0 = []
    for res in results:
        res_dict = dict(
            entry_id = res.entry_id,
            pdf_url = res.pdf_url,
            updated = res.updated, 
            published = res.published, 
            title = res.title, 
            authors = convert_to_str(res.authors),  # 文字列に変換
            summary = res.summary,
            comment = res.comment,
            journal_ref = res.journal_ref,
            doi = res.doi,
            primary_category = res.primary_category,
            categories = res.categories,
            links = convert_to_str(res.links),  # 文字列に変換
        )
        res0.append(res_dict)
    df = pd.DataFrame(res0)
    ndata = len(df)
    df['Relevance'] = [i/ndata for i in range(ndata, 0, -1)]  # 一致度を0~1の範囲で設定。検索がRelevanceでDescendingでソートしているため。
    return df

df = create_df(results)

Semantic Scholarによる引用数の取得

  • arxivには引用数に関連する項目がないため、Semantic ScholarのAPIを利用

  • Shemantic ScholarのAPIについては以下を参照のこと

  • 追加する項目は以下とした

    • citationCount: 被引用数
    • influentialCitationCount: 影響力があると判断された引用数
    • referenceCount: 参考文献数(参考用)

プログラム例

  • バッチ処理するための文献IDを"arxiv_id"として設定する
  • バッチ処理において、サーバ状況・リクエストの間隔によってエラーが生じやすい。再実行時に不都合が生じにくいようにデータ(DataFame)は結合(merge)ではなく、updateを使用
    • 一度に処理できる文献ID数は500件である点に注意する
import numpy as np

def create_url(aid: str):
    apath = aid.split("/")[-1].split("v")[0]
    arxiv_id = f'ARXIV:{apath}'
    search_url = f'{semantic_base_url}/{arxiv_id}' + '?fields=' + fields 
    return arxiv_id

semantic_base_url = 'https://api.semanticscholar.org/graph/v1/paper'  # Semantic ScholarのベースURL
fields = 'citationCount,influentialCitationCount,referenceCount'  # サイトから取得する追加項
df['arxiv_id'] = df['entry_id'].apply(create_url)
tcol = fields.split(",") 
df[tcol] = np.nan  # 初期化

  • バッチ処理
import requests
import time

def get_citation_batch(df, start=0, batch_size=500):
    ndata = len(df)
    nbatch = (ndata // batch_size) + 1
    data = df['arxiv_id'].tolist()
    for i in range(start, ndata, batch_size):
        batch = data[i:i+batch_size]  
        semantic_batch_url = semantic_base_url + '/batch'
        # ---
        print(f"{i+1}/{nbatch}  Processing batch: {i} to {i+batch_size}")
        r = requests.post(semantic_batch_url, params={'fields': fields}, json={"ids": batch})
        print(r.status_code)
        if r.status_code != 200:
            print('---')
            print('Error: ', r.status_code)
            if r.status_code == 429:
                print('Too many requests. Wait a while and try again.')
            return df
        # ---
        batch_output = dict(zip(batch, r.json()))
        batch_output = pd.DataFrame(batch_output).T
        df.set_index('arxiv_id', inplace=True)  # arxiv_idをキーとしてdfのデータを更新
        df.update(batch_output)
        df.reset_index(inplace=True)
        # ---
        time.sleep(5)  # 時間を空けるため
    return df


start = 0  # 開始行
batch_size = 500  # バッチ数。500以下
df = get_citation_batch(df, start=start, batch_size=batch_size)

データの整理(ソート、フィルタ)と出力

  • データをソートしてエクセル出力する
    • 本例ではinfluentialCitaionCount, citationCount, Relevanceの順に降順でソート
  • クリックして参照PDFに飛べるようにハイパーリンクを追加
    • リンク追加前: arxiv_list.xlsx として出力。csv出力しても良い
    • リンク追加後: add_link_arxiv_list.xlsx として出力
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
from openpyxl.styles import Font

outfilename = "arxiv_list.xlsx"
data = df.copy()

# データのソート
tcols = fields.split(",") + ['Relevance']
data[tcols] = data[tcols].apply(pd.to_numeric, errors='coerce')  # ignore, coerce
tcols = ['updated', 'published']
for t in tcols:
    data[t] = data[t].apply(lambda x: x.strftime('%Y-%m-%d'))
data = data.sort_values(by=['influentialCitationCount', 'citationCount', 'Relevance'], ascending=[False, False, False])
data.to_excel(outfilename, index=False)

# ハイパーリンクの追加
wb = load_workbook(outfilename)
ws = wb.active

hyperlink_colname = ['entry_id', 'pdf_url']
col_index = [data.columns.get_loc(s) for s in hyperlink_colname]
for row in range(2, ws.max_row + 1):  # Excelの行は1始まり
    for c in col_index:
        cell = ws[f"{get_column_letter(c+1)}{row}"]  # B列(2列目)
        cell.value = f'=HYPERLINK("{cell.value}", "{cell.value}")'  # Excelのハイパーリンク関数
        cell.font = Font(color="0563C1", underline="single")  # デフォルトの青色(#0563C1)+ アンダーライン
wb.save('add_link_' + outfilename)
wb.close()

参照サイト

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?