参考文献作者堆叠
参考文献相关性检测 作者ai写作辅助检测工作
This commit is contained in:
120
application/common/EuropePmcService.php
Normal file
120
application/common/EuropePmcService.php
Normal 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 : '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user