参考文献作者堆叠

参考文献相关性检测
作者ai写作辅助检测工作
This commit is contained in:
wyn
2026-07-15 10:49:05 +08:00
parent da71dfc04e
commit 8785610e6d
27 changed files with 10008 additions and 204 deletions

View File

@@ -0,0 +1,120 @@
<?php
namespace app\common;
/**
* Europe PMC REST API
* @see https://europepmc.org/RestfulWebService
*/
class EuropePmcService
{
private $base = 'https://www.ebi.ac.uk/europepmc/webservices/rest';
private $timeout = 25;
public function searchByDoi($doi)
{
$doi = trim((string)$doi);
if ($doi === '') {
return null;
}
$query = 'DOI:"' . str_replace('"', '', $doi) . '"';
return $this->searchFirst($query);
}
public function searchByBibliographic($title, $author, $year = '')
{
$title = trim((string)$title);
if ($title === '') {
return null;
}
$parts = ['TITLE:"' . str_replace('"', '', $title) . '"'];
$author = trim((string)$author);
if ($author !== '') {
$firstAuthor = preg_split('/[,;]/', $author);
$firstAuthor = trim((string)($firstAuthor[0] ?? ''));
if ($firstAuthor !== '') {
$parts[] = 'AUTH:"' . str_replace('"', '', $firstAuthor) . '"';
}
}
$year = trim((string)$year);
if ($year !== '' && preg_match('/^(19|20)\d{2}$/', $year)) {
$parts[] = 'PUB_YEAR:' . $year;
}
return $this->searchFirst(implode(' AND ', $parts));
}
public function fetchFullTextByPmcid($pmcid)
{
$pmcid = strtoupper(trim((string)$pmcid));
if ($pmcid === '') {
return '';
}
if (strpos($pmcid, 'PMC') !== 0) {
$pmcid = 'PMC' . preg_replace('/\D/', '', $pmcid);
}
$url = $this->base . '/' . rawurlencode($pmcid) . '/fullTextXML';
$xml = $this->httpGet($url);
if ($xml === '') {
return '';
}
return $this->xmlToPlainText($xml);
}
private function searchFirst($query)
{
$url = $this->base . '/search?' . http_build_query([
'query' => $query,
'format' => 'json',
'pageSize' => 1,
]);
$raw = $this->httpGet($url);
if ($raw === '') {
return null;
}
$json = json_decode($raw, true);
$list = $json['resultList']['result'] ?? [];
if (empty($list[0]) || !is_array($list[0])) {
return null;
}
$row = $list[0];
return [
'title' => trim((string)($row['title'] ?? '')),
'abstract' => trim((string)($row['abstractText'] ?? '')),
'doi' => trim((string)($row['doi'] ?? '')),
'pmid' => trim((string)($row['pmid'] ?? '')),
'pmcid' => trim((string)($row['pmcid'] ?? '')),
'journal' => trim((string)($row['journalTitle'] ?? '')),
'year' => trim((string)($row['pubYear'] ?? '')),
'source' => 'europe_pmc',
];
}
private function xmlToPlainText($xml)
{
$xml = trim((string)$xml);
if ($xml === '') {
return '';
}
libxml_use_internal_errors(true);
$doc = new \DOMDocument();
if (!$doc->loadXML($xml)) {
return trim(strip_tags($xml));
}
return trim(preg_replace('/\s+/u', ' ', $doc->textContent));
}
private function httpGet($url)
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_HTTPHEADER => ['User-Agent: TMRjournals-EuropePMC/1.0'],
]);
$res = curl_exec($ch);
curl_close($ch);
return is_string($res) ? $res : '';
}
}