参考文献格式--book
This commit is contained in:
@@ -24,11 +24,15 @@ class ReferenceDispatchService
|
||||
/** @var BookMetadataService */
|
||||
private $bookMetadata;
|
||||
|
||||
/** @var BookCitationParser */
|
||||
private $bookParser;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->classifier = new ReferenceTypeClassifier(['use_llm' => true]);
|
||||
$this->metadata = new ReferenceMetadataService();
|
||||
$this->bookMetadata = new BookMetadataService();
|
||||
$this->bookParser = new BookCitationParser();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +185,9 @@ class ReferenceDispatchService
|
||||
$summary = is_array($meta) ? $meta['crossref_summary'] : null;
|
||||
$raw = is_array($summary) ? ($summary['raw'] ?? []) : [];
|
||||
$hasMeta = is_array($meta)
|
||||
&& (trim((string)$meta['title']) !== '' || trim((string)$meta['author']) !== '');
|
||||
&& (trim((string)$meta['title']) !== '' || trim((string)$meta['author']) !== '')
|
||||
// 图书著录里挂的 DOI 常常是被错误关联的期刊文章,题名对不上就不能拿来覆盖
|
||||
&& $this->metaMatchesContent($meta, $content);
|
||||
|
||||
if ($hasMeta) {
|
||||
$authorCitation = trim((string)$meta['author']);
|
||||
@@ -217,6 +223,44 @@ class ReferenceDispatchService
|
||||
Db::name('production_article_refer')->where('p_refer_id', $pReferId)->update($update);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOI 抓回来的题名是否确实是这条著录说的那本书
|
||||
*/
|
||||
private function metaMatchesContent($meta, $content)
|
||||
{
|
||||
$title = $this->normalizeForMatch((string)$meta['title']);
|
||||
if ($title === '') {
|
||||
return false;
|
||||
}
|
||||
$blob = $this->normalizeForMatch($content);
|
||||
if ($blob === '' || strpos($blob, $title) !== false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$words = array_filter(explode(' ', $title), function ($w) {
|
||||
return strlen($w) > 3;
|
||||
});
|
||||
if (empty($words)) {
|
||||
return false;
|
||||
}
|
||||
$hit = 0;
|
||||
foreach ($words as $word) {
|
||||
if (strpos($blob, $word) !== false) {
|
||||
$hit++;
|
||||
}
|
||||
}
|
||||
|
||||
return ($hit / count($words)) >= 0.6;
|
||||
}
|
||||
|
||||
private function normalizeForMatch($text)
|
||||
{
|
||||
$text = strtolower(trim((string)$text));
|
||||
$text = preg_replace('/[^a-z0-9\x{4e00}-\x{9fff}\s]+/u', ' ', $text);
|
||||
|
||||
return trim(preg_replace('/\s+/u', ' ', $text));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按书名/作者/年份/版次反查 ISBN,顺带补齐缺失的出版社与出版年
|
||||
*
|
||||
@@ -299,50 +343,22 @@ class ReferenceDispatchService
|
||||
}
|
||||
|
||||
/**
|
||||
* 无 Crossref 时从原文尽量抽取 book 结构化字段
|
||||
* 无可用 DOI 元数据时,从原文著录抽取 book 结构化字段
|
||||
*/
|
||||
private function parseBookFromContent($content)
|
||||
{
|
||||
$content = trim((string)$content);
|
||||
$out = [
|
||||
'author' => '',
|
||||
'title' => '',
|
||||
'joura' => '',
|
||||
'dateno' => '',
|
||||
'isbn' => '',
|
||||
$parsed = $this->bookParser->parse($content);
|
||||
|
||||
$author = trim((string)$parsed['author']);
|
||||
|
||||
return [
|
||||
'author' => $author !== '' ? rtrim($author, '.') . '.' : '',
|
||||
'title' => trim((string)$parsed['title']),
|
||||
'joura' => trim((string)$parsed['publisher']),
|
||||
'dateno' => trim((string)$parsed['year']),
|
||||
'isbn' => trim((string)$parsed['isbn']),
|
||||
'is_ja' => 1,
|
||||
];
|
||||
|
||||
if ($content === '') {
|
||||
return $out;
|
||||
}
|
||||
|
||||
if (preg_match('/\bISBN[:\s]*([\d\-Xx\s]+)/i', $content, $m)) {
|
||||
$out['isbn'] = preg_replace('/\s+/', '-', trim($m[1]));
|
||||
}
|
||||
|
||||
if (preg_match('/\b(19|20)\d{2}\b/', $content, $m)) {
|
||||
$out['dateno'] = $m[0];
|
||||
}
|
||||
|
||||
// Place: Publisher; Year → joura 取 Publisher
|
||||
if (preg_match('/:\s*([^;]+);\s*(19|20)\d{2}/', $content, $m)) {
|
||||
$out['joura'] = trim($m[1]);
|
||||
} elseif (preg_match('/\b([A-Z][A-Za-z .&]+(?:Press|Publishing|Publisher|Books?))\b/i', $content, $m)) {
|
||||
$out['joura'] = trim($m[1]);
|
||||
}
|
||||
|
||||
// 作者. 标题. ... 简单拆分
|
||||
$parts = preg_split('/\.\s+/', $content, 3);
|
||||
if (is_array($parts) && count($parts) >= 2) {
|
||||
$out['author'] = trim($parts[0]);
|
||||
if (substr($out['author'], -1) !== '.') {
|
||||
$out['author'] .= '.';
|
||||
}
|
||||
$out['title'] = trim(rtrim($parts[1], '.'));
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
private function normalizeDoi($doi)
|
||||
|
||||
Reference in New Issue
Block a user