Merge pull request 'feat: integrate Google Scholar alerts and improve paper filtering pipeline' (#1) from feature/googlescholar into main
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
+6
-5
@@ -3,6 +3,7 @@ app:
|
|||||||
lookback_days: 14
|
lookback_days: 14
|
||||||
max_papers_per_source_per_query: 20
|
max_papers_per_source_per_query: 20
|
||||||
min_relevance: 2
|
min_relevance: 2
|
||||||
|
google_scholar_min_relevance: 3
|
||||||
output_dir: ./data/outbox
|
output_dir: ./data/outbox
|
||||||
database_path: ./data/papers.db
|
database_path: ./data/papers.db
|
||||||
log_level: INFO
|
log_level: INFO
|
||||||
@@ -55,18 +56,18 @@ sources:
|
|||||||
base_url: https://api.semanticscholar.org/graph/v1/paper/search
|
base_url: https://api.semanticscholar.org/graph/v1/paper/search
|
||||||
|
|
||||||
crossref:
|
crossref:
|
||||||
enabled: true
|
enabled: true
|
||||||
mailto_env: CROSSREF_MAILTO
|
mailto_env: CROSSREF_MAILTO
|
||||||
base_url: https://api.crossref.org/works
|
base_url: https://api.crossref.org/works
|
||||||
|
|
||||||
google_scholar_alert:
|
google_scholar_alert:
|
||||||
enabled: false
|
enabled: true
|
||||||
gmail_address_env: GMAIL_ADDRESS
|
gmail_address_env: GOOGLE_SCHOLAR_GMAIL_ADDRESS
|
||||||
gmail_app_password_env: GMAIL_APP_PASSWORD
|
gmail_app_password_env: GOOGLE_SCHOLAR_GMAIL_APP_PASSWORD
|
||||||
imap_host: imap.gmail.com
|
imap_host: imap.gmail.com
|
||||||
mailbox: INBOX
|
mailbox: INBOX
|
||||||
sender_contains: scholaralerts-noreply
|
sender_contains: scholaralerts-noreply
|
||||||
subject_contains: Google Scholar
|
subject_contains: ""
|
||||||
|
|
||||||
ai:
|
ai:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ services:
|
|||||||
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
|
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
|
||||||
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
||||||
GROQ_API_KEY: ${GROQ_API_KEY}
|
GROQ_API_KEY: ${GROQ_API_KEY}
|
||||||
GMAIL_ADDRESS: ${GMAIL_ADDRESS:-}
|
GOOGLE_SCHOLAR_GMAIL_ADDRESS: ${GOOGLE_SCHOLAR_GMAIL_ADDRESS}
|
||||||
GMAIL_APP_PASSWORD: ${GMAIL_APP_PASSWORD:-}
|
GOOGLE_SCHOLAR_GMAIL_APP_PASSWORD: ${GOOGLE_SCHOLAR_GMAIL_APP_PASSWORD}
|
||||||
|
|
||||||
# Existing Joplin WebDAV sync target
|
# Existing Joplin WebDAV sync target
|
||||||
JOPLIN_WEBDAV_URL: ${JOPLIN_WEBDAV_URL}
|
JOPLIN_WEBDAV_URL: ${JOPLIN_WEBDAV_URL}
|
||||||
|
|||||||
+154
-39
@@ -1,11 +1,43 @@
|
|||||||
# Paper Monitor 프로젝트 - 남은 작업 및 검토 TODO
|
# Paper Monitor 프로젝트 - 남은 작업 및 검토 TODO
|
||||||
|
|
||||||
최종 업데이트: 2026-08-15
|
최종 업데이트: 2026-08-21
|
||||||
|
|
||||||
이 문서는 지금까지 구축한 Synology NAS 기반 논문 자동 모니터링 시스템에서 **아직 미정이거나 수행하지 못한 항목**, 그리고 **운영 전에 변경 또는 추가 검토가 필요한 항목**을 정리한 TODO 목록이다.
|
이 문서는 지금까지 구축한 Synology NAS 기반 논문 자동 모니터링 시스템에서 **아직 미정이거나 수행하지 못한 항목**, 그리고 **운영 전에 변경 또는 추가 검토가 필요한 항목**을 정리한 TODO 목록이다.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## P0 - 다음 즉시 처리
|
||||||
|
|
||||||
|
### [ ] 최종 보고서 필터링 수정
|
||||||
|
현재 run 결과 예시:
|
||||||
|
- collected: 229
|
||||||
|
- merged: 207
|
||||||
|
- accepted: 28
|
||||||
|
- new: 0
|
||||||
|
- report_count: 86
|
||||||
|
|
||||||
|
`report_count`에 Scholar 관련성 임계값 변경 이전에 삽입된 논문이 포함되어 있음.
|
||||||
|
|
||||||
|
보고서 생성 시 현재 최종 관련성 기준을 반영하도록 수정 필요.
|
||||||
|
|
||||||
|
### [ ] 최종 보고서 선택에 Gemini 관련성 적용
|
||||||
|
현재 문제:
|
||||||
|
- rule-based 필터링이 Gemini 이전에 실행됨
|
||||||
|
- rule-based에서 accepted된 논문이 이후 Gemini 관련성 1~2를 받아도 보고서에 잔류함
|
||||||
|
- 자동차 레이더 보고서에 무관한 일반 MIMO/C-band/5G 안테나 논문이 포함됨
|
||||||
|
|
||||||
|
정책 정의 필요 (예):
|
||||||
|
- Gemini 분석 완료: AI 관련성 >= 3인 논문만 포함
|
||||||
|
- AI 분석 미수행/불가: rule-based 관련성으로 fallback
|
||||||
|
|
||||||
|
### [ ] Unpaywall HTTP 404 처리 수정
|
||||||
|
- 현재 404 응답이 traceback 예외로 처리됨
|
||||||
|
- `not_found`로 처리해야 함 (정상 케이스)
|
||||||
|
- `exc.response is not None` 조건으로 수정
|
||||||
|
- 누락된 DOI 레코드에 대한 불필요한 traceback 없이 파이프라인 계속 실행
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 1. 즉시 처리 권장
|
## 1. 즉시 처리 권장
|
||||||
|
|
||||||
### [ ] Semantic Scholar 차단 해제 후 재활성화
|
### [ ] Semantic Scholar 차단 해제 후 재활성화
|
||||||
@@ -101,10 +133,52 @@ sources:
|
|||||||
- 불필요한 중복 감소
|
- 불필요한 중복 감소
|
||||||
- IEEE와 Semantic Scholar 차단 가능성 감소
|
- IEEE와 Semantic Scholar 차단 가능성 감소
|
||||||
|
|
||||||
|
### [ ] Google Scholar 관련성 임계값 검토
|
||||||
|
수회 스케줄 실행 후 확인 필요.
|
||||||
|
|
||||||
|
현재 설정:
|
||||||
|
- Scholar 관련성 임계값: 3
|
||||||
|
- 전역 임계값: 2
|
||||||
|
|
||||||
|
확인:
|
||||||
|
- 관련 자동차 레이더 논문이 임계값 3으로 인해 누락되는지 여부
|
||||||
|
- 누락이 발견되면 임계값 2로 낮출지 검토
|
||||||
|
|
||||||
|
### [ ] Scholar 파서 개선 (필요 시)
|
||||||
|
현재 collector가 여전히 광범위한 알림 결과를 수집함.
|
||||||
|
|
||||||
|
권장 접근:
|
||||||
|
- 알림/쿼리 설정 개선 및 하위 관련성 점수 개선을 우선 시도
|
||||||
|
- 공격적인 제목 키워드 필터링보다 쿼리 수준에서 범위 조정
|
||||||
|
- 새로운 비논문 항목이 나타나면 UI 링크 제외 목록 추가
|
||||||
|
|
||||||
|
### [ ] `classify_and_score()` 점수 규칙 검토
|
||||||
|
다음 항목에 대해 자동차 레이더 관련성이 명확하지 않으면 낮은 관련성 점수 부여:
|
||||||
|
- 일반 MIMO
|
||||||
|
- 일반 안테나
|
||||||
|
- 통신 전용 ISAC
|
||||||
|
- C/X/sub-6 GHz 논문
|
||||||
|
- 비레이더 DOA 논문
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Gemini AI 운영 설정
|
## 4. Gemini AI 운영 설정
|
||||||
|
|
||||||
|
### [x] Gemini 13초 요청 간격 추가
|
||||||
|
무료 5 RPM 한도 보호를 위해 요청 간 13초 대기 적용 완료.
|
||||||
|
|
||||||
|
### [x] Gemini 무료 5 RPM 한도에서 429 오류 없음 확인
|
||||||
|
13초 간격 적용 후 실제 운영에서 429 발생 없음 확인.
|
||||||
|
|
||||||
|
### [x] 이전 실패 Gemini 논문 재시도 구현
|
||||||
|
`ai_status=failed`인 논문을 다음 run에서 자동 재시도하는 로직 구현 완료.
|
||||||
|
|
||||||
|
### [ ] Gemini 429 RetryInfo/backoff 명시적 처리
|
||||||
|
13초 간격이 주 보호 수단.
|
||||||
|
그러나 임시 quota/rate-limit 응답에 대한 방어 처리 추가 검토:
|
||||||
|
- `RetryInfo` 헤더를 파싱하여 대기 시간 준수
|
||||||
|
- 429 발생 시 지수 백오프 fallback
|
||||||
|
|
||||||
### [ ] Gemini 무료 quota 실제 사용량 모니터링
|
### [ ] Gemini 무료 quota 실제 사용량 모니터링
|
||||||
확인 항목:
|
확인 항목:
|
||||||
- full-text 요청 수
|
- full-text 요청 수
|
||||||
@@ -192,6 +266,16 @@ Groq는 인증 정상화 후 `pyproject.toml`에 추가.
|
|||||||
|
|
||||||
Semantic Scholar가 다시 활성화된 뒤 실제 논문에서 `pdf_url`이 정상 채워지는지 확인 필요.
|
Semantic Scholar가 다시 활성화된 뒤 실제 논문에서 `pdf_url`이 정상 채워지는지 확인 필요.
|
||||||
|
|
||||||
|
### [ ] Unpaywall HTTP 404 처리 수정
|
||||||
|
현재 상태:
|
||||||
|
- 404 응답이 traceback 예외로 처리됨
|
||||||
|
- DOI가 없는 정상 케이스인데도 불필요한 오류 로그 발생
|
||||||
|
|
||||||
|
수정 사항:
|
||||||
|
- `exc.response is not None` 조건으로 404 여부 판별
|
||||||
|
- 404는 `not_found`로 처리, 파이프라인 중단 없이 계속 진행
|
||||||
|
- traceback 없이 조용히 처리
|
||||||
|
|
||||||
### [ ] Unpaywall 실제 신규 논문 경로 검증
|
### [ ] Unpaywall 실제 신규 논문 경로 검증
|
||||||
standalone 테스트는 성공했지만 실제 신규 논문 run에서 다음 로그를 아직 충분히 확인하지 못함:
|
standalone 테스트는 성공했지만 실제 신규 논문 run에서 다음 로그를 아직 충분히 확인하지 못함:
|
||||||
|
|
||||||
@@ -363,28 +447,35 @@ OA PDF
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Source 추가
|
## 10. Source 추가 / Google Scholar 운영
|
||||||
|
|
||||||
### [ ] Google Scholar Alert 연동
|
### [x] Google Scholar Alert Gmail IMAP 연동 구현
|
||||||
아직 보류 중.
|
구현 완료:
|
||||||
|
- Google Scholar Alert -> Gmail -> IMAP -> ScholarGmailCollector -> paper-monitor 파이프라인
|
||||||
|
- Gmail App Password 인증 동작 확인
|
||||||
|
- Scholar UI/alert-label 필터링 추가
|
||||||
|
|
||||||
계획:
|
### [ ] Gmail IMAP 수집 최적화
|
||||||
```text
|
현재 구현이 최근 메시지를 가져온 후 필터링.
|
||||||
Google Scholar Alert
|
|
||||||
-> Gmail
|
|
||||||
-> IMAP
|
|
||||||
-> ScholarGmailCollector
|
|
||||||
-> paper-monitor
|
|
||||||
```
|
|
||||||
|
|
||||||
웹 scraping 대신 Google Scholar Alert 메일을 사용하는 방식 권장.
|
개선 검토:
|
||||||
|
- 서버 측 `SINCE` + `FROM` 필터링으로 IMAP 트래픽 및 실행 시간 감소
|
||||||
|
|
||||||
필요:
|
### [ ] 알림 쿼리 품질 평가
|
||||||
- Google Scholar Alert 생성
|
- 관련 없는 MIMO/DOA/안테나 논문을 과다 생성하는 Scholar 알림 쿼리 검토
|
||||||
- Gmail App Password
|
- 중요 자동차 레이더 논문을 놓치지 않는 선에서 알림 범위 축소
|
||||||
- NAS `.env`
|
|
||||||
- Gmail collector 활성화
|
### [ ] Semantic Scholar 연결/접근 안정화 후 재활성화
|
||||||
- sender/subject filter 테스트
|
(기존 섹션 1 참조)
|
||||||
|
|
||||||
|
### [ ] IEEE 웹사이트/API 접근 확인 후 재활성화
|
||||||
|
(기존 섹션 1 참조)
|
||||||
|
|
||||||
|
### [ ] provider circuit breaker 지속 운용
|
||||||
|
현재 circuit breaker 정상 동작 중. 계속 유지.
|
||||||
|
|
||||||
|
### [ ] Crossref 간헐적 네트워크 타임아웃 모니터링
|
||||||
|
간헐적 타임아웃 발생 여부 실행 로그에서 주기적 확인.
|
||||||
|
|
||||||
### [ ] IEEE 복구 후 source 우선순위 재정의
|
### [ ] IEEE 복구 후 source 우선순위 재정의
|
||||||
장기 목표 예:
|
장기 목표 예:
|
||||||
@@ -511,30 +602,44 @@ lookback: 14일
|
|||||||
|
|
||||||
# 우선순위 요약
|
# 우선순위 요약
|
||||||
|
|
||||||
## P0 - 운영 전에 확인
|
## P0 - 다음 즉시 처리
|
||||||
- [ ] Semantic Scholar `enabled: false`
|
- [ ] 최종 보고서 필터링 수정 (report_count에 이전 기준 논문 포함 문제)
|
||||||
- [ ] IEEE `enabled: false`
|
- [ ] 최종 보고서 선택에 Gemini 관련성 적용 (관련성 1~2 논문 제외)
|
||||||
- [ ] `.env` secret 권한 및 IEEE key rotation 여부 확인
|
- [ ] Unpaywall HTTP 404 처리 수정 (traceback 대신 not_found로 처리)
|
||||||
|
|
||||||
## P1 - 접근 복구 후
|
## P1 - 필터링 품질
|
||||||
- [ ] Semantic Scholar 재활성화 + 429 상태 확인
|
- [ ] 수회 스케줄 실행 후 Google Scholar 관련성 임계값 검토 (현재: 3, 전역: 2)
|
||||||
- [ ] IEEE 웹사이트 403 해제 확인
|
- [ ] Scholar 파서 개선 (필요 시)
|
||||||
- [ ] IEEE API 승인 상태 확인
|
- [ ] `classify_and_score()` 점수 규칙 검토 (일반 MIMO/안테나/통신 전용 논문 처리)
|
||||||
- [ ] IEEE 1-query 테스트 후 재활성화
|
|
||||||
|
|
||||||
## P2 - 기능 보강
|
## P1 - AI
|
||||||
- [ ] Google Scholar Alert + Gmail collector
|
- [ ] Gemini 429 RetryInfo/backoff 명시적 처리 (13초 간격이 주 보호, 방어 처리 추가)
|
||||||
- [ ] Groq 인증 해결 + Gemini fallback
|
- [ ] Gemini AFC 경고 정리 (현재 동작에 문제 없음, 낮은 우선순위)
|
||||||
- [ ] `skipped` 재평가 정책
|
- [ ] Gemini -> Groq fallback (인증 문제 미해결, 파이프라인 차단하지 않음)
|
||||||
- [ ] AI retry count / provider / model / processed_at DB 저장
|
|
||||||
- [ ] PDF section-aware extraction
|
|
||||||
|
|
||||||
## P3 - 장기 운영
|
## P1 - 소스
|
||||||
- [ ] DB backup
|
- [ ] Semantic Scholar 연결/접근 안정화 후 재활성화
|
||||||
- [ ] scheduler timestamp 로그 보관기간/정리 정책(예: 8주)
|
- [ ] IEEE 웹사이트/API 접근 확인 후 재활성화
|
||||||
- [ ] dependency version pinning
|
- [ ] provider circuit breaker 지속 운용
|
||||||
|
- [ ] Crossref 간헐적 네트워크 타임아웃 모니터링
|
||||||
|
|
||||||
|
## P2 - Google Scholar
|
||||||
|
- [ ] Gmail IMAP 수집 최적화 (서버 측 SINCE + FROM 필터링 검토)
|
||||||
|
- [ ] 알림 쿼리 품질 평가 (관련 없는 MIMO/DOA/안테나 논문 과다 생성 쿼리 검토)
|
||||||
|
|
||||||
|
## P2 - 데이터베이스 / 보고서
|
||||||
|
- [ ] 수집 관련성과 최종 AI 관련성을 DB에서 명확히 분리
|
||||||
|
- [ ] 관련성 점수 출처 저장/보고 (rule-based / Gemini abstract / Gemini full-text)
|
||||||
|
- [ ] `ai_status=skipped` 처리 정책 결정
|
||||||
|
- [ ] 기준 변경 시 같은 날 기존 논문을 재생성 보고서에서 제거할지 결정
|
||||||
|
- [ ] DB backup/보존 정책 추가
|
||||||
|
- [ ] scheduler.log 로그 로테이션 추가
|
||||||
|
|
||||||
|
## P3 - 운영
|
||||||
|
- [ ] Docker Hub / Crossref / IEEE / Semantic Scholar 연결 문제 모니터링
|
||||||
|
- [ ] 파이프라인 안정화 후 주요 Python dependency 버전 고정
|
||||||
- [ ] query/source 최적화
|
- [ ] query/source 최적화
|
||||||
- [ ] Joplin report layout 개선
|
- [ ] Joplin 보고서 레이아웃 개선
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -554,3 +659,13 @@ scheduler-YYYY-MM-DD_HH-MM-SS.log
|
|||||||
|
|
||||||
## Gemini 운영값
|
## Gemini 운영값
|
||||||
- [x] `max_papers_per_run` 운영값 확정: `20`
|
- [x] `max_papers_per_run` 운영값 확정: `20`
|
||||||
|
|
||||||
|
## Google Scholar Alert 연동 (2026-08-21)
|
||||||
|
- [x] Google Scholar Alert Gmail IMAP 연동 구현
|
||||||
|
- [x] Gmail App Password 인증 동작 확인
|
||||||
|
- [x] Scholar UI/alert-label 필터링 추가
|
||||||
|
|
||||||
|
## Gemini AI 개선 (2026-08-21)
|
||||||
|
- [x] Gemini 13초 요청 간격 추가 (무료 5 RPM 한도 보호)
|
||||||
|
- [x] Gemini 무료 5 RPM 한도에서 429 오류 없음 확인
|
||||||
|
- [x] 이전 실패(`ai_status=failed`) Gemini 논문 재시도 구현
|
||||||
|
|||||||
@@ -1,5 +1,21 @@
|
|||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
_GEMINI_MIN_INTERVAL = 13.0
|
||||||
|
_GEMINI_LAST_CALL = 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def _wait_for_gemini_rate_limit():
|
||||||
|
global _GEMINI_LAST_CALL
|
||||||
|
|
||||||
|
now = time.monotonic()
|
||||||
|
elapsed = now - _GEMINI_LAST_CALL
|
||||||
|
wait = _GEMINI_MIN_INTERVAL - elapsed
|
||||||
|
|
||||||
|
if wait > 0:
|
||||||
|
time.sleep(wait)
|
||||||
|
|
||||||
|
_GEMINI_LAST_CALL = time.monotonic()
|
||||||
|
|
||||||
SYSTEM = '''You are a technical literature triage assistant for an automotive radar engineer.
|
SYSTEM = '''You are a technical literature triage assistant for an automotive radar engineer.
|
||||||
|
|
||||||
@@ -111,6 +127,8 @@ def enrich_with_gemini(paper, api_key, model):
|
|||||||
+ json.dumps(payload, ensure_ascii=False)
|
+ json.dumps(payload, ensure_ascii=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_wait_for_gemini_rate_limit()
|
||||||
|
|
||||||
response = client.models.generate_content(
|
response = client.models.generate_content(
|
||||||
model=model,
|
model=model,
|
||||||
contents=prompt,
|
contents=prompt,
|
||||||
@@ -172,6 +190,8 @@ contribution, and relevance to automotive radar when supported by the text.
|
|||||||
+ json.dumps(payload, ensure_ascii=False)
|
+ json.dumps(payload, ensure_ascii=False)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_wait_for_gemini_rate_limit()
|
||||||
|
|
||||||
response = client.models.generate_content(
|
response = client.models.generate_content(
|
||||||
model=model,
|
model=model,
|
||||||
contents=prompt,
|
contents=prompt,
|
||||||
|
|||||||
@@ -49,9 +49,31 @@ class ScholarGmailCollector:
|
|||||||
if html_body:
|
if html_body:
|
||||||
soup=BeautifulSoup(html_body,'html.parser')
|
soup=BeautifulSoup(html_body,'html.parser')
|
||||||
for a in soup.find_all('a',href=True):
|
for a in soup.find_all('a',href=True):
|
||||||
title=clean_text(a.get_text(' ',strip=True)); href=a['href']
|
title = clean_text(a.get_text(' ', strip=True))
|
||||||
if len(title)<15: continue
|
href = a['href']
|
||||||
if any(x in title.lower() for x in ['create alert','cancel alert','view all','unsubscribe']): continue
|
|
||||||
|
if len(title) < 15:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if any(
|
||||||
|
x in title.lower()
|
||||||
|
for x in [
|
||||||
|
'create alert',
|
||||||
|
'cancel alert',
|
||||||
|
'view all',
|
||||||
|
'unsubscribe',
|
||||||
|
'update alert',
|
||||||
|
'receive fewer',
|
||||||
|
'more relevant results',
|
||||||
|
'manage alert',
|
||||||
|
]
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Skip Google Scholar alert/query labels such as:
|
||||||
|
# [automotive radar]
|
||||||
|
if re.fullmatch(r'\[[^\]]+\]', title):
|
||||||
|
continue
|
||||||
context=clean_text(a.parent.get_text(' ',strip=True) if a.parent else title)
|
context=clean_text(a.parent.get_text(' ',strip=True) if a.parent else title)
|
||||||
doi_match=DOI_RE.search(context+' '+href)
|
doi_match=DOI_RE.search(context+' '+href)
|
||||||
papers.append(Paper(title=title,abstract=context if context!=title else '',doi=normalize_doi(doi_match.group(0) if doi_match else ''),url=href,publication_date=date,source='Google Scholar Alert'))
|
papers.append(Paper(title=title,abstract=context if context!=title else '',doi=normalize_doi(doi_match.group(0) if doi_match else ''),url=href,publication_date=date,source='Google Scholar Alert'))
|
||||||
|
|||||||
@@ -34,7 +34,11 @@ class UnpaywallResolver:
|
|||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as exc:
|
except requests.exceptions.HTTPError as exc:
|
||||||
status = exc.response.status_code if exc.response else None
|
status = (
|
||||||
|
exc.response.status_code
|
||||||
|
if exc.response is not None
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
# DOI not present in Unpaywall is not fatal.
|
# DOI not present in Unpaywall is not fatal.
|
||||||
if status == 404:
|
if status == 404:
|
||||||
|
|||||||
@@ -259,7 +259,20 @@ def run(config_path, dry_run=False):
|
|||||||
merged[k] = merge_paper(merged[k], p) if k in merged else p
|
merged[k] = merge_paper(merged[k], p) if k in merged else p
|
||||||
|
|
||||||
papers = [classify_and_score(p, search_cfg) for p in merged.values()]
|
papers = [classify_and_score(p, search_cfg) for p in merged.values()]
|
||||||
papers = [p for p in papers if p.relevance >= int(app.get('min_relevance', 1))]
|
|
||||||
|
min_rel = int(app.get("min_relevance", 1))
|
||||||
|
scholar_min_rel = int(
|
||||||
|
app.get("google_scholar_min_relevance", min_rel)
|
||||||
|
)
|
||||||
|
|
||||||
|
papers = [
|
||||||
|
p for p in papers
|
||||||
|
if p.relevance >= (
|
||||||
|
scholar_min_rel
|
||||||
|
if p.source == "Google Scholar Alert"
|
||||||
|
else min_rel
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
db_path = resolve_path(cfg, app.get('database_path', './data/papers.db'))
|
db_path = resolve_path(cfg, app.get('database_path', './data/papers.db'))
|
||||||
db = PaperDB(db_path)
|
db = PaperDB(db_path)
|
||||||
|
|||||||
@@ -5,5 +5,12 @@
|
|||||||
"strikes": {
|
"strikes": {
|
||||||
"http_403": 1
|
"http_403": 1
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"crossref": {
|
||||||
|
"open_until": 1787231271.0746372,
|
||||||
|
"reason": "network_error",
|
||||||
|
"strikes": {
|
||||||
|
"network_error": 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user