from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import csv from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import csv from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException import pandas as pd import requests from bs4 import BeautifulSoup import time import unicodedata import re import ast import torch from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import ElementClickInterceptedException def fetch_clinical_trials( disease_name="", freeword="", include_not_yet_recruiting=False, include_suspended=False, specific_clinical_research=True, corporate_clinical_trial=True, physician_initiated_clinical_trial=True, ): """ 指定された条件に基づいてjRCTから臨床試験情報を取得します。 Args: disease_name (str): 対象疾患名(例: "がん 神経膠腫 骨髄腫") freeword (str): フリーワード検索(例: "免疫療法") include_not_yet_recruiting (bool): 募集前の試験も含める場合はTrue。 include_suspended (bool): 募集中断を含める場合はTrue。 specific_clinical_research (bool): 特定臨床研究を含める場合はTrue。 corporate_clinical_trial (bool): 企業治験を含める場合はTrue。 physician_initiated_clinical_trial (bool): 医師主導治験を含める場合はTrue。 Returns: list: 検索結果のリスト([試験ID, タイトル, 対象疾患, 進捗状況, 日付, リンク]) """ # WebDriverを初期化 driver = webdriver.Chrome() # 必要に応じてChromeDriverを設定 all_results = [] try: # jRCTの検索ページにアクセス driver.get("https://jrct.niph.go.jp/search") # 対象疾患名を入力 if disease_name: disease_field = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "reg-plobrem-1")) ) disease_field.send_keys(disease_name) # 対象疾患名の条件を「or」に設定 condition_select = driver.find_element(By.ID, "reg-plobrem-type") condition_select.find_element(By.CSS_SELECTOR, "option[value='1']").click() # フリーワード検索を入力 if freeword: freeword_field = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.ID, "demo-1")) ) freeword_field.send_keys(freeword) # フリーワード検索の条件を「or」に設定 condition_select = driver.find_element(By.ID, "others") condition_select.find_element(By.CSS_SELECTOR, "option[value='1']").click() # 募集中を選択 recruitment_checkbox = driver.find_element(By.ID, "reg-recruitment-2") recruitment_checkbox.click() # 募集前も含める場合 if include_not_yet_recruiting: not_yet_checkbox = driver.find_element(By.ID, "reg-recruitment-1") not_yet_checkbox.click() # 募集中断を選択 if include_suspended: suspended_checkbox = driver.find_element(By.ID, "reg-recruitment-3") suspended_checkbox.click() # 特定臨床研究を選択 if specific_clinical_research: specific_checkbox = driver.find_element(By.ID, "is-specific1") specific_checkbox.click() # 企業治験を選択 if corporate_clinical_trial: corporate_checkbox = driver.find_element(By.ID, "is-specific3") corporate_checkbox.click() # 医師主導治験を選択 if physician_initiated_clinical_trial: physician_checkbox = driver.find_element(By.ID, "is-specific7") physician_checkbox.click() # 検索ボタンをクリック try: search_button = driver.find_element(By.NAME, "button_type") driver.execute_script("arguments[0].scrollIntoView();", search_button) # ボタンを画面内にスクロール WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.NAME, "button_type"))).click() except ElementClickInterceptedException: print("検索ボタンがクリックできないため、JavaScriptでクリックします。") driver.execute_script("arguments[0].click();", search_button) # ページネーション対応ループ while True: # 現在のページの結果がロードされるのを待機 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, "table tbody tr")) ) # 現在のページの結果を取得 rows = driver.find_elements(By.CSS_SELECTOR, "table tbody tr") for row in rows: columns = row.find_elements(By.TAG_NAME, "td") if len(columns) > 4: # 試験情報をリストに追加 trial_id = columns[0].text title = columns[1].text condition = columns[2].text status = columns[3].text date = columns[4].text # リンクを取得(エラー処理を追加) try: link = columns[1].find_element(By.TAG_NAME, "a").get_attribute("href") except Exception: link = "リンク取得エラー" all_results.append([trial_id, title, condition, status, date, link]) # ページネーションの確認 try: current_page = driver.find_element(By.CSS_SELECTOR, "ul.pagination li.active").text print(f"{current_page} ページ目を処理しました。") except Exception: print("ページネーションが存在しません。全ての結果を取得しました。") break # 次ページボタンのリストを取得 pagination_buttons = driver.find_elements(By.CSS_SELECTOR, "ul.pagination li a") next_button = None for button in pagination_buttons: if button.text.isdigit() and int(button.text) > int(current_page): next_button = button break if next_button: try: driver.execute_script("arguments[0].scrollIntoView();", next_button) # ボタンを画面内にスクロール WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.LINK_TEXT, next_button.text))).click() except ElementClickInterceptedException: print("次ページボタンがクリックできないため、JavaScriptでクリックします。") driver.execute_script("arguments[0].click();", next_button) WebDriverWait(driver, 10).until(EC.staleness_of(rows[0])) # ページが変わるまで待機 else: print("次のページはありません。全ての結果を取得しました。") break finally: # ブラウザを閉じる driver.quit() return all_results def scrape_jrct_all_details(url): """ 指定されたjRCT URLから必要なすべての情報を抽出します。 """ def normalize_text(text): if not text: return "" # Unicode正規化 + 余分な空白除去 text = unicodedata.normalize('NFKC', text) return " ".join(text.split()) # リクエストを送信 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } try: response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() except requests.RequestException as e: print(f"URLリクエストに失敗しました: {url} - エラー: {e}") return {"URL": url, "エラー": "リクエスト失敗"} soup = BeautifulSoup(response.text, 'html.parser') data = {"URL": url} def extract_label_data(label_text, label_en=None): """ 特定のラベルに対応するデータを抽出するヘルパー関数 複数の候補があった場合は、すべて取得してからフィルタする方式をとる。 """ results = [] # 日本語ラベルと英語ラベルが両方指定されていれば、両方含む行を優先的に探す combined_search = None if label_en: combined_search = f"{label_text} / {label_en}" # ページ内のすべての