feat: 手动上传绕防爬、下载错误诊断与健康检查工具;模块化重构 API 与批量同步
后端:
- 将 handlers.rs (1338行) 拆分为 helpers/papers/notes/sync 四模块
- 将 batch_sync.rs 拆分为 batch/{mod,meta,asset} 三模块
- 新增 POST /api/upload 多部件文件上传接口
- 新增 POST /api/no_resource 标记文献"无全文资源"
- 新增 GET/POST /api/active_bibcode 追踪活跃文献
- StandardPaper 结构体扩展 pdf_error / html_error 错误诊断字段
- download.rs 记录下载失败详情至数据库
- 新增 health_check 二进制工具,支持只读扫描与 --fix 自动修复
- 移除 scratch/ 目录、recovered_handlers.rs 及调试日志
前端:
- 新建 CustomSelect 可复用组件,替换全部原生 select
- LibraryPanel:同步按钮反馈动画、下载失败/无资源状态筛选与计数、
文献类型筛选、状态优先排序、搜索一键清空
- 详情弹窗:错误诊断展示、手动 PDF/HTML 上传区、无资源标记/恢复
- SearchPanel:扩展文献类型徽章、下载失败状态提示
- SyncPanel:同步启动乐观 UI 更新、日志容器内自动滚动
- Tab 状态 localStorage 持久化、弹窗 z-index 修复
This commit is contained in:
Binary file not shown.
@@ -1,321 +0,0 @@
|
||||
=== 403 FORBIDDEN ===
|
||||
### Monthly Notices of the Royal Astronomical Society (共 26 篇)
|
||||
- `2010MNRAS.401.1080A`
|
||||
- `2010MNRAS.401.1850K`
|
||||
- `2010MNRAS.406.2701K`
|
||||
- `2011MNRAS.412..487K`
|
||||
- `2011MNRAS.415.3042K`
|
||||
- `2012MNRAS.419..452Z`
|
||||
- `2012MNRAS.421.3238K`
|
||||
- `2013MNRAS.431..240O`
|
||||
- `2013MNRAS.436.1408Q`
|
||||
- `2014MNRAS.445.4247K`
|
||||
- `2015MNRAS.451.3986K`
|
||||
- `2015MNRAS.453.1879K`
|
||||
- `2016MNRAS.457..723K`
|
||||
- `2016MNRAS.459.4343K`
|
||||
- `2017MNRAS.467.3963K`
|
||||
- `2018MNRAS.481.2721B`
|
||||
- `2019MNRAS.482..758S`
|
||||
- `2019MNRAS.485.4330K`
|
||||
- `2019MNRAS.489.1556B`
|
||||
- `2019MNRAS.490.1283K`
|
||||
- `2020MNRAS.493.5162R`
|
||||
- `2021MNRAS.508..560K`
|
||||
- `2022MNRAS.516.1509K`
|
||||
- `2023MNRAS.525..183S`
|
||||
- `2023MNRAS.525.1342R`
|
||||
- `2026MNRAS.548ag689.`
|
||||
### American Astronomical Society Meeting Abstracts #242 (共 7 篇)
|
||||
- `2023AAS...24220105B`
|
||||
- `2023AAS...24230301D`
|
||||
- `2023AAS...24230501K`
|
||||
- `2023AAS...24230502S`
|
||||
- `2023AAS...24230503L`
|
||||
- `2023AAS...24233706D`
|
||||
- `2023AAS...24240003S`
|
||||
### International Conference on Binaries: in celebration of Ron Webbink's 65th Birthday (共 4 篇)
|
||||
- `2010AIPC.1314...67G`
|
||||
- `2010AIPC.1314...73W`
|
||||
- `2010AIPC.1314...85H`
|
||||
- `2010AIPC.1314...91S`
|
||||
### 17th European White Dwarf Workshop (共 4 篇)
|
||||
- `2010AIPC.1273..243S`
|
||||
- `2010AIPC.1273..255L`
|
||||
- `2010AIPC.1273..259B`
|
||||
- `2010AIPC.1273..263G`
|
||||
### American Astronomical Society Meeting Abstracts #245 (共 3 篇)
|
||||
- `2025AAS...24540303B`
|
||||
- `2025AAS...24540312T`
|
||||
- `2025AAS...24540313K`
|
||||
### American Astronomical Society Meeting Abstracts #237 (共 3 篇)
|
||||
- `2021AAS...23714004P`
|
||||
- `2021AAS...23734904W`
|
||||
- `2021AAS...23755001C`
|
||||
### Journal of Physics Conference Series (共 3 篇)
|
||||
- `2009JPhCS.172a2015H`
|
||||
- `2016JPhCS.728g2023Z`
|
||||
- `2019JPhCS1380a2095S`
|
||||
### The Astrophysical Journal (共 2 篇)
|
||||
- `2011ApJ...737L..27R`
|
||||
- `2026ApJ...997...58W`
|
||||
### Binary Systems, their Evolution and Environments (共 2 篇)
|
||||
- `2014bsee.confE..25H`
|
||||
- `2014bsee.confP..25S`
|
||||
### Publications of the Astronomical Society of the Pacific (共 2 篇)
|
||||
- `1998PASP..110..906H`
|
||||
- `2001PASP..113..490W`
|
||||
### IUE Proposal (共 2 篇)
|
||||
- `1987iue..prop.2806L`
|
||||
- `1993iue..prop.4613J`
|
||||
### Annual Review of Astronomy and Astrophysics (共 1 篇)
|
||||
- `2009ARA&A..47..211H`
|
||||
### Stellar Pulsation: Challenges for Theory and Observation (共 1 篇)
|
||||
- `2009AIPC.1170..585C`
|
||||
### Ph.D. Thesis (共 1 篇)
|
||||
- `2015PhDT.......315A`
|
||||
### Ultraviolet observations of Quasars (共 1 篇)
|
||||
- `1980ESASP.157..323R`
|
||||
### American Astronomical Society Meeting Abstracts #244 (共 1 篇)
|
||||
- `2024AAS...24430302K`
|
||||
### EAS2023, European Astronomical Society Annual Meeting (共 1 篇)
|
||||
- `2023eas..conf..491U`
|
||||
### Future Directions in Ultraviolet Spectroscopy: A Conference Inspired by the Accomplishments of the Far Ultraviolet Spectroscopic Explorer Mission (共 1 篇)
|
||||
- `2009AIPC.1135..148C`
|
||||
### American Astronomical Society Meeting Abstracts #234 (共 1 篇)
|
||||
- `2019AAS...23432204B`
|
||||
### Astronomicheskii Zhurnal (共 1 篇)
|
||||
- `1995AZh....72..879E`
|
||||
### American Astronomical Society Meeting Abstracts #233 (共 1 篇)
|
||||
- `2019AAS...23346403W`
|
||||
### American Astronomical Society Meeting Abstracts #241 (共 1 篇)
|
||||
- `2023AAS...24130225Z`
|
||||
### The Astronomical Journal (共 1 篇)
|
||||
- `2021AJ....161..193L`
|
||||
### American Astronomical Society Meeting Abstracts #227 (共 1 篇)
|
||||
- `2016AAS...22740404B`
|
||||
### Astronomische Nachrichten (共 1 篇)
|
||||
- `2001AN....322..271S`
|
||||
### Thirteenth Marcel Grossmann Meeting: On Recent Developments in Theoretical and Experimental General Relativity, Astrophysics and Relativistic Field Theories (共 1 篇)
|
||||
- `2015mgm..conf.2459M`
|
||||
|
||||
=== 404 OR MISSING PDF MAGIC ===
|
||||
### VizieR Online Data Catalog (共 16 篇)
|
||||
- `1996yCat.3137....0K`
|
||||
- `2016yCat..74573396P`
|
||||
- `2023yCat..74910874N`
|
||||
- `2023yCat..74952844S`
|
||||
- `2024yCat..19280020B`
|
||||
- `2024yCat..19420109L`
|
||||
- `2024yCat..22710021L`
|
||||
- `2024yCat..22710057X`
|
||||
- `2024yCat..36840118U`
|
||||
- `2024yCat..36910223V`
|
||||
- `2024yCat..36930121H`
|
||||
- `2024yCat..36930245W`
|
||||
- `2024yCat..36930268R`
|
||||
- `2025yCat..36900368G`
|
||||
- `2025yCat..36970098B`
|
||||
- `2025yCat..37050248L`
|
||||
### American Astronomical Society Meeting Abstracts (共 12 篇)
|
||||
- `1992AAS...181.5003H`
|
||||
- `1994AAS...185.8005L`
|
||||
- `1995AAS...187.8202M`
|
||||
- `2000AAS...197.8302C`
|
||||
- `2001AAS...199.0615S`
|
||||
- `2004AAS...20517003S`
|
||||
- `2006AAS...20915101W`
|
||||
- `2007AAS...211.0320P`
|
||||
- `2007AAS...211.0333W`
|
||||
- `2007AAS...211.6006C`
|
||||
- `2007AAS...21110422K`
|
||||
- `2026AAS...24730801S`
|
||||
### The Astrophysical Journal (共 9 篇)
|
||||
- `1997ApJ...485..843L`
|
||||
- `1997ApJ...487L..81B`
|
||||
- `1997ApJ...491..172S`
|
||||
- `1998ApJ...493..440G`
|
||||
- `1998ApJ...494L..75B`
|
||||
- `2000ApJ...530..441B`
|
||||
- `2011ApJ...733..100L`
|
||||
- `2011ApJ...734...59G`
|
||||
- `2025ApJ...989..177C`
|
||||
### HST Proposal (共 8 篇)
|
||||
- `1994hst..prop.5305L`
|
||||
- `2012hst..prop12954B`
|
||||
- `2013hst..prop13290G`
|
||||
- `2014hst..prop13800J`
|
||||
- `2017hst..prop15284N`
|
||||
- `2022hst..prop17072D`
|
||||
- `2024hst..prop17697D`
|
||||
- `2024hst..prop17799N`
|
||||
### XMM-Newton Proposal (共 7 篇)
|
||||
- `2009xmm..prop..182M`
|
||||
- `2010xmm..prop...51M`
|
||||
- `2010xmm..prop...57L`
|
||||
- `2011xmm..prop..162L`
|
||||
- `2019xmm..prop...66M`
|
||||
- `2020xmm..prop..117M`
|
||||
- `2021xmm..prop..123M`
|
||||
### IUE Proposal (共 7 篇)
|
||||
- `1980iue..prop..596D`
|
||||
- `1981iue..prop..889W`
|
||||
- `1981iue..prop..907D`
|
||||
- `1986iue..prop.2435D`
|
||||
- `1988iue..prop.3231H`
|
||||
- `1991iue..prop.4189D`
|
||||
- `1994iue..prop.4925T`
|
||||
### Ph.D. Thesis (共 6 篇)
|
||||
- `1991PhDT........10S`
|
||||
- `1991PhDT.......346M`
|
||||
- `1994PhDT.......261M`
|
||||
- `2007PhDT.......230R`
|
||||
- `2013PhDT.......509A`
|
||||
- `2022PhDT........21F`
|
||||
### The Astronomical Journal (共 6 篇)
|
||||
- `2008AJ....136..946M`
|
||||
- `2023AJ....165..142K`
|
||||
- `2023AJ....165..148H`
|
||||
- `2025AJ....170..199O`
|
||||
- `2026AJ....171..165C`
|
||||
- `2026AJ....171..217B`
|
||||
### NOAO Proposal (共 5 篇)
|
||||
- `1999noao.prop...31W`
|
||||
- `2002noao.prop..318S`
|
||||
- `2010noao.prop..372W`
|
||||
- `2011noao.prop..191V`
|
||||
- `2012noao.prop..214B`
|
||||
### White Dwarfs (共 4 篇)
|
||||
- `1995LNP...443..221S`
|
||||
- `1995LNP...443..271T`
|
||||
- `1995LNP...443..272U`
|
||||
- `2003ASIB..105...99G`
|
||||
### American Astronomical Society Meeting Abstracts #233 (共 4 篇)
|
||||
- `2019AAS...23331402W`
|
||||
- `2019AAS...23336016C`
|
||||
- `2019AAS...23342201R`
|
||||
- `2019AAS...23346406D`
|
||||
### IAU General Assembly (共 4 篇)
|
||||
- `2015IAUGA..2224007H`
|
||||
- `2015IAUGA..2233490G`
|
||||
- `2015IAUGA..2235533G`
|
||||
- `2015IAUGA..2254919C`
|
||||
### Research Notes of the American Astronomical Society (共 3 篇)
|
||||
- `2019RNAAS...3...81B`
|
||||
- `2023RNAAS...7..255K`
|
||||
- `2025RNAAS...9..227Z`
|
||||
### EAS2023, European Astronomical Society Annual Meeting (共 3 篇)
|
||||
- `2023eas..conf..202T`
|
||||
- `2023eas..conf..553G`
|
||||
- `2023eas..conf.2257V`
|
||||
### American Astronomical Society Meeting Abstracts #221 (共 3 篇)
|
||||
- `2013AAS...22111605P`
|
||||
- `2013AAS...22114217B`
|
||||
- `2013AAS...22144305B`
|
||||
### American Astronomical Society Meeting Abstracts #227 (共 3 篇)
|
||||
- `2016AAS...22714405V`
|
||||
- `2016AAS...22734412B`
|
||||
- `2016AAS...22734514C`
|
||||
### Odessa Astronomical Publications (共 3 篇)
|
||||
- `2001OAP....14...82P`
|
||||
- `2001OAP....14...87P`
|
||||
- `2005OAP....18..135V`
|
||||
### EAS2024, European Astronomical Society Annual Meeting (共 2 篇)
|
||||
- `2024eas..conf.1492A`
|
||||
- `2024eas..conf.2481P`
|
||||
### Nature (共 2 篇)
|
||||
- `1978Natur.275..385H`
|
||||
- `1979Natur.279..305H`
|
||||
### Publications of the Astronomical Society of the Pacific (共 2 篇)
|
||||
- `1998PASP..110.1315G`
|
||||
- `2001PASP..113..944W`
|
||||
### American Astronomical Society Meeting Abstracts #215 (共 2 篇)
|
||||
- `2010AAS...21541929W`
|
||||
- `2010AAS...21545206C`
|
||||
### New Quests in Stellar Astrophysics. II. Ultraviolet Properties of Evolved Stellar Populations (共 2 篇)
|
||||
- `2009ASSP....7...59H`
|
||||
- `2009ASSP....7..191N`
|
||||
### American Astronomical Society Meeting Abstracts #223 (共 2 篇)
|
||||
- `2014AAS...22315615V`
|
||||
- `2014AAS...22315625R`
|
||||
### Astronomy Reports (共 2 篇)
|
||||
- `1995ARep...39..785E`
|
||||
- `1997ARep...41..802M`
|
||||
### The Atmospheres of Early-Type Stars (共 2 篇)
|
||||
- `1992LNP...401..257D`
|
||||
- `1992LNP...401..264T`
|
||||
### American Astronomical Society Meeting Abstracts #198 (共 2 篇)
|
||||
- `2001AAS...198.4906W`
|
||||
- `2001AAS...198.4907S`
|
||||
### Hot Stars in the Galactic Halo (共 2 篇)
|
||||
- `1994hsgh.conf..182D`
|
||||
- `1994hsgh.conf..341D`
|
||||
### American Astronomical Society Meeting Abstracts #219 (共 2 篇)
|
||||
- `2012AAS...21915325L`
|
||||
- `2012AAS...21940803B`
|
||||
### Magnetic Stars (共 1 篇)
|
||||
- `2011mast.conf..415H`
|
||||
### The First Year of IUE (共 1 篇)
|
||||
- `1979IUE1.symp..363D`
|
||||
### Stellar Atmospheres - Beyond Classical Models (共 1 篇)
|
||||
- `1991ASIC..341..341W`
|
||||
### Fourth European IUE Conference (共 1 篇)
|
||||
- `1984ESASP.218..273H`
|
||||
### Exploring the Universe with the IUE Satellite (共 1 篇)
|
||||
- `1987ASSL..129..355V`
|
||||
### Planetary and Proto-Planetary Nebulae: From IRAS to ISO (共 1 篇)
|
||||
- `1987ASSL..135..137H`
|
||||
### Acta Astronomica Sinica (共 1 篇)
|
||||
- `2020AcASn..61...19M`
|
||||
### American Astronomical Society Meeting Abstracts #231 (共 1 篇)
|
||||
- `2018AAS...23114603H`
|
||||
### Swift and the Surprising Sky: The First Seven Years of Swift. Online at: <A href="http://www.brera.inaf.it/docM/OAB/Research/SWIFT/Swift7/?p=program">http://www.brera.inaf.it/docM/OAB/Research/SWIFT/Swift7/?p=program</A> (共 1 篇)
|
||||
- `2011sssf.confE..42M`
|
||||
### Stellar Magnetic Fields (共 1 篇)
|
||||
- `1997smf..proc..122E`
|
||||
### FUSE Proposal (共 1 篇)
|
||||
- `2003fuse.prop.D165L`
|
||||
### Optical Complex Systems: OCS11 (共 1 篇)
|
||||
- `2011SPIE.8172E..0UV`
|
||||
### American Astronomical Society Meeting Abstracts #224 (共 1 篇)
|
||||
- `2014AAS...22421903B`
|
||||
### The Impact of Asteroseismology across Stellar Astrophysics (共 1 篇)
|
||||
- `2011iasa.confE...2H`
|
||||
### Progress in Astronomy (共 1 篇)
|
||||
- `2008PABei..26..126Y`
|
||||
### American Astronomical Society Meeting Abstracts #218 (共 1 篇)
|
||||
- `2011AAS...21812207C`
|
||||
### NASA Conference Publication (共 1 篇)
|
||||
- `1981NASCP2171..349K`
|
||||
### American Astronomical Society Meeting Abstracts #194 (共 1 篇)
|
||||
- `1999AAS...194.6702H`
|
||||
### Cataclysmic Variables and Low-Mass X-ray Binaries (共 1 篇)
|
||||
- `1985ASSL..113...15B`
|
||||
### Magellanic Clouds and Other Dwarf Galaxies (共 1 篇)
|
||||
- `1998mcdg.proc..229A`
|
||||
### Memoires of the Societe Royale des Sciences de Liege (共 1 篇)
|
||||
- `1975MSRSL...9..247G`
|
||||
### IAU Colloquium 53: White Dwarfs and Variable Degenerate Stars (共 1 篇)
|
||||
- `1979wdvd.coll..107O`
|
||||
### Astrofizika (共 1 篇)
|
||||
- `1990Afz....33..199S`
|
||||
### Structure and Evolution of Active Galactic Nuclei (共 1 篇)
|
||||
- `1986ASSL..121..317K`
|
||||
### Keck Observatory Archive ESI (共 1 篇)
|
||||
- `2013koa..prop...89F`
|
||||
### Astronomy Letters (共 1 篇)
|
||||
- `2020AstL...46..601A`
|
||||
### Astronomische Nachrichten (共 1 篇)
|
||||
- `2007AN....328..708G`
|
||||
### Pisma v Astronomicheskii Zhurnal (共 1 篇)
|
||||
- `1990PAZh...16.1095T`
|
||||
### NASA Special Publication (共 1 篇)
|
||||
- `1982NASSP.456..147L`
|
||||
### Variable Stars, the Galactic halo and Galaxy Formation (共 1 篇)
|
||||
- `2010vsgh.conf..161G`
|
||||
### GALEX Proposal (共 1 篇)
|
||||
- `2004galx.prop...60W`
|
||||
### Visual Double Stars : Formation, Dynamics and Evolutionary Tracks (共 1 篇)
|
||||
- `1997ASSL..223..209U`
|
||||
### Peremennye Zvezdy (共 1 篇)
|
||||
- `2018PZ.....38....2D`
|
||||
@@ -1,67 +0,0 @@
|
||||
import re
|
||||
import sqlite3
|
||||
|
||||
log_path = "/home/fmq/program/AstroResearch/logs/astro_research.log.2026-06-10"
|
||||
db_path = "/home/fmq/program/AstroResearch/library/astro_research.db"
|
||||
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
bibcode_to_pub = {}
|
||||
cursor.execute("SELECT bibcode, pub FROM papers")
|
||||
for row in cursor.fetchall():
|
||||
bibcode_to_pub[row[0]] = row[1]
|
||||
|
||||
bibcode_logs = {}
|
||||
current_bibcode = None
|
||||
|
||||
with open(log_path, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
m = re.search(r"开始处理文献:\s*(\S+)", line)
|
||||
if m:
|
||||
current_bibcode = m.group(1)
|
||||
bibcode_logs.setdefault(current_bibcode, [])
|
||||
bibcode_logs[current_bibcode].append(line)
|
||||
continue
|
||||
m = re.search(r"\[下载\] 开始 (PDF|HTML) 下载:\s*(\S+)", line)
|
||||
if m:
|
||||
current_bibcode = m.group(2)
|
||||
bibcode_logs.setdefault(current_bibcode, [])
|
||||
bibcode_logs[current_bibcode].append(line)
|
||||
continue
|
||||
if current_bibcode:
|
||||
bibcode_logs[current_bibcode].append(line)
|
||||
|
||||
failed_papers = {}
|
||||
for bibcode, logs in bibcode_logs.items():
|
||||
log_text = "".join(logs)
|
||||
if "下载失败(PDF 和 HTML 均下载失败)" in log_text:
|
||||
failed_papers[bibcode] = log_text
|
||||
|
||||
err_403 = {}
|
||||
err_404_magic = {}
|
||||
|
||||
for bibcode, log_text in failed_papers.items():
|
||||
pub = bibcode_to_pub.get(bibcode, "Unknown")
|
||||
has_403 = "403" in log_text or "Forbidden" in log_text or "Cloudflare" in log_text or "验证码" in log_text
|
||||
has_404 = "404" in log_text or "not found" in log_text.lower() or "魔数" in log_text or "不是有效的 PDF" in log_text or "过小" in log_text or "损坏或不完整" in log_text
|
||||
|
||||
if has_403:
|
||||
err_403[bibcode] = pub
|
||||
elif has_404:
|
||||
err_404_magic[bibcode] = pub
|
||||
|
||||
def format_group(err_dict):
|
||||
grouped = {}
|
||||
for b, p in err_dict.items():
|
||||
grouped.setdefault(p, []).append(b)
|
||||
output = []
|
||||
for pub, bibs in sorted(grouped.items(), key=lambda x: len(x[1]), reverse=True):
|
||||
output.append(f"### {pub} (共 {len(bibs)} 篇)")
|
||||
for bib in sorted(bibs):
|
||||
output.append(f"- `{bib}`")
|
||||
return "\n".join(output)
|
||||
|
||||
print("=== 403 FORBIDDEN ===")
|
||||
print(format_group(err_403))
|
||||
print("\n=== 404 OR MISSING PDF MAGIC ===")
|
||||
print(format_group(err_404_magic))
|
||||
@@ -1,15 +0,0 @@
|
||||
import qiniu
|
||||
|
||||
ak = "vf63aPF-QIFbyzULtHaSx9JgiVSS3zRuy0zmBACE"
|
||||
sk = "JlQvHevHSAgilNYaH0UxQoX68rb4m9VflpaXtYL1"
|
||||
|
||||
auth = qiniu.Auth(ak, sk)
|
||||
bucket_manager = qiniu.BucketManager(auth)
|
||||
|
||||
print("Listing buckets...")
|
||||
try:
|
||||
buckets, info = bucket_manager.buckets()
|
||||
print("Buckets:", buckets)
|
||||
print("Info:", info)
|
||||
except Exception as e:
|
||||
print("Error listing buckets:", e)
|
||||
@@ -1,76 +0,0 @@
|
||||
import re
|
||||
import sqlite3
|
||||
|
||||
log_path = "/home/fmq/program/AstroResearch/logs/astro_research.log.2026-06-10"
|
||||
db_path = "/home/fmq/program/AstroResearch/library/astro_research.db"
|
||||
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
bibcode_to_pub = {}
|
||||
cursor.execute("SELECT bibcode, pub FROM papers")
|
||||
for row in cursor.fetchall():
|
||||
bibcode_to_pub[row[0]] = row[1]
|
||||
|
||||
bibcode_logs = {}
|
||||
current_bibcode = None
|
||||
|
||||
with open(log_path, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
m = re.search(r"开始处理文献:\s*(\S+)", line)
|
||||
if m:
|
||||
current_bibcode = m.group(1)
|
||||
bibcode_logs.setdefault(current_bibcode, [])
|
||||
bibcode_logs[current_bibcode].append(line)
|
||||
continue
|
||||
m = re.search(r"\[下载\] 开始 (PDF|HTML) 下载:\s*(\S+)", line)
|
||||
if m:
|
||||
current_bibcode = m.group(2)
|
||||
bibcode_logs.setdefault(current_bibcode, [])
|
||||
bibcode_logs[current_bibcode].append(line)
|
||||
continue
|
||||
if current_bibcode:
|
||||
bibcode_logs[current_bibcode].append(line)
|
||||
|
||||
failed_papers = {}
|
||||
for bibcode, logs in bibcode_logs.items():
|
||||
log_text = "".join(logs)
|
||||
if "下载失败(PDF 和 HTML 均下载失败)" in log_text:
|
||||
failed_papers[bibcode] = log_text
|
||||
|
||||
print("Total failed papers:", len(failed_papers))
|
||||
|
||||
err_403 = {}
|
||||
err_404_magic = {}
|
||||
|
||||
for bibcode, log_text in failed_papers.items():
|
||||
pub = bibcode_to_pub.get(bibcode, "Unknown")
|
||||
|
||||
# We want to identify the primary reason for failure.
|
||||
# If the log text contains "403 Forbidden" or "Cloudflare", then it's a 403 block.
|
||||
# Otherwise, if it has "404 Not Found" or "缺少 %PDF 魔数" or "响应不是有效的 PDF", it's 404/Magic.
|
||||
# Let's check:
|
||||
has_403 = "403" in log_text or "Forbidden" in log_text or "Cloudflare" in log_text or "验证码" in log_text
|
||||
has_404 = "404" in log_text or "not found" in log_text.lower() or "魔数" in log_text or "不是有效的 PDF" in log_text or "过小" in log_text or "损坏或不完整" in log_text
|
||||
|
||||
if has_403:
|
||||
err_403[bibcode] = pub
|
||||
elif has_404:
|
||||
err_404_magic[bibcode] = pub
|
||||
|
||||
print(f"Failed via 403 count: {len(err_403)}")
|
||||
print(f"Failed via 404/Magic count: {len(err_404_magic)}")
|
||||
|
||||
# Print them grouped
|
||||
print("\n--- 403 Grouped ---")
|
||||
grouped_403 = {}
|
||||
for b, p in err_403.items():
|
||||
grouped_403.setdefault(p, []).append(b)
|
||||
for pub, bibs in sorted(grouped_403.items(), key=lambda x: len(x[1]), reverse=True):
|
||||
print(f"出版社/期刊: {pub} (共 {len(bibs)} 篇): {', '.join(bibs)}")
|
||||
|
||||
print("\n--- 404/Magic Grouped ---")
|
||||
grouped_404_magic = {}
|
||||
for b, p in err_404_magic.items():
|
||||
grouped_404_magic.setdefault(p, []).append(b)
|
||||
for pub, bibs in sorted(grouped_404_magic.items(), key=lambda x: len(x[1]), reverse=True):
|
||||
print(f"出版社/期刊: {pub} (共 {len(bibs)} 篇): {', '.join(bibs)}")
|
||||
@@ -1,44 +0,0 @@
|
||||
import base64
|
||||
import hmac
|
||||
import hashlib
|
||||
import json
|
||||
import time
|
||||
import requests
|
||||
|
||||
def urlsafe_base64_encode(data):
|
||||
if isinstance(data, str):
|
||||
data = data.encode('utf-8')
|
||||
ret = base64.urlsafe_b64encode(data)
|
||||
# base64url standard replaces padding '=' with nothing
|
||||
return ret.decode('utf-8').rstrip('=')
|
||||
|
||||
def generate_token(ak, sk, bucket, key, scope_key=True):
|
||||
deadline = int(time.time()) + 3600
|
||||
scope = f"{bucket}:{key}" if scope_key else bucket
|
||||
policy = {
|
||||
"scope": scope,
|
||||
"deadline": deadline
|
||||
}
|
||||
policy_str = json.dumps(policy, separators=(',', ':'))
|
||||
encoded_policy = urlsafe_base64_encode(policy_str)
|
||||
|
||||
# hmac-sha1
|
||||
hashed = hmac.new(sk.encode('utf-8'), encoded_policy.encode('utf-8'), hashlib.sha1)
|
||||
encoded_signature = urlsafe_base64_encode(hashed.digest())
|
||||
|
||||
return f"{ak}:{encoded_signature}:{encoded_policy}"
|
||||
|
||||
ak = "vf63aPF-QIFbyzULtHaSx9JgiVSS3zRuy0zmBACE"
|
||||
sk = "JlQvHevHSAgilNYaH0UxQoX68rb4m9VflpaXtYL1"
|
||||
bucket = "fmqi-img"
|
||||
key = "astroresearch/test_hello.txt"
|
||||
|
||||
token = generate_token(ak, sk, bucket, key, scope_key=True)
|
||||
print(f"Generated python token: {token}")
|
||||
|
||||
# Let's try uploading
|
||||
files = {'file': ('test.txt', b'hello python')}
|
||||
data = {'token': token, 'key': key}
|
||||
res = requests.post("https://up-z1.qiniup.com", data=data, files=files)
|
||||
print(f"Python upload status: {res.status_code}")
|
||||
print(f"Python upload response: {res.text}")
|
||||
@@ -1,68 +0,0 @@
|
||||
use sha1::Sha1;
|
||||
use hmac::{Hmac, Mac};
|
||||
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
|
||||
use reqwest::multipart;
|
||||
|
||||
type HmacSha1 = Hmac<Sha1>;
|
||||
|
||||
fn generate_token(ak: &str, sk: &str, bucket: &str, key: &str, scope_key: bool) -> String {
|
||||
let deadline = chrono::Utc::now().timestamp() + 3600;
|
||||
|
||||
let scope = if scope_key {
|
||||
format!("{}:{}", bucket, key)
|
||||
} else {
|
||||
bucket.to_string()
|
||||
};
|
||||
|
||||
let policy = serde_json::json!({
|
||||
"scope": scope,
|
||||
"deadline": deadline
|
||||
});
|
||||
|
||||
let policy_str = policy.to_string();
|
||||
let encoded_policy = URL_SAFE_NO_PAD.encode(policy_str.as_bytes());
|
||||
|
||||
let mut mac = HmacSha1::new_from_slice(sk.as_bytes()).unwrap();
|
||||
mac.update(encoded_policy.as_bytes());
|
||||
let signature = mac.finalize().into_bytes();
|
||||
let encoded_signature = URL_SAFE_NO_PAD.encode(&signature);
|
||||
|
||||
format!("{}:{}:{}", ak, encoded_signature, encoded_policy)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let ak = "vf63aPF-QIFbyzULtHaSx9JgiVSS3zRuy0zmBACE".to_string();
|
||||
let sk = "JlQvHevHSAgilNYaH0UxQoX68rb4m9VflpaXtYL1".to_string();
|
||||
let bucket = "fmqi-img".to_string();
|
||||
let domain = "http://qnimg.asfmq.cn".to_string();
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let dummy_data = b"hello world qiniu test".to_vec();
|
||||
let filename = "test_hello.txt";
|
||||
let key = "astroresearch/test_hello.txt";
|
||||
|
||||
println!("Testing with scoped key token (bucket:key)...");
|
||||
let token1 = generate_token(&ak, &sk, &bucket, key, true);
|
||||
let form1 = multipart::Form::new()
|
||||
.text("token", token1)
|
||||
.text("key", key)
|
||||
.part("file", multipart::Part::bytes(dummy_data.clone()).file_name(filename));
|
||||
|
||||
let res1 = client.post("https://up-z1.qiniup.com").multipart(form1).send().await?;
|
||||
println!("Status (scoped key): {}", res1.status());
|
||||
println!("Response: {}", res1.text().await?);
|
||||
|
||||
println!("\nTesting with bucket-only scoped token...");
|
||||
let token2 = generate_token(&ak, &sk, &bucket, key, false);
|
||||
let form2 = multipart::Form::new()
|
||||
.text("token", token2)
|
||||
.text("key", key)
|
||||
.part("file", multipart::Part::bytes(dummy_data).file_name(filename));
|
||||
|
||||
let res2 = client.post("https://up-z1.qiniup.com").multipart(form2).send().await?;
|
||||
println!("Status (bucket-only): {}", res2.status());
|
||||
println!("Response: {}", res2.text().await?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import qiniu
|
||||
|
||||
ak = "vf63aPF-QIFbyzULtHaSx9JgiVSS3zRuy0zmBACE"
|
||||
sk = "JlQvHevHSAgilNYaH0UxQoX68rb4m9VflpaXtYL1"
|
||||
bucket = "fmqi-img"
|
||||
key = "astroresearch/test_hello.txt"
|
||||
|
||||
auth = qiniu.Auth(ak, sk)
|
||||
token = auth.upload_token(bucket, key, 3600)
|
||||
print("SDK Generated Token:", token)
|
||||
|
||||
# Upload using Qiniu SDK put_data
|
||||
ret, info = qiniu.put_data(token, key, b"hello SDK")
|
||||
print("Ret:", ret)
|
||||
print("Info:", info)
|
||||
Reference in New Issue
Block a user