2022-09-25 23:22:49 +03:00
|
|
|
<?php
|
|
|
|
|
|
|
|
class GoogleScholarBridge extends BridgeAbstract
|
|
|
|
{
|
2023-06-10 19:35:04 +03:00
|
|
|
const NAME = 'Google Scholar v2';
|
2022-09-25 23:22:49 +03:00
|
|
|
const URI = 'https://scholar.google.com/';
|
2023-06-10 19:35:04 +03:00
|
|
|
const DESCRIPTION = 'Search for publications or follow authors on Google Scholar.';
|
|
|
|
const MAINTAINER = 'nicholasmccarthy';
|
2022-09-25 23:22:49 +03:00
|
|
|
const CACHE_TIMEOUT = 86400; // 24h
|
|
|
|
|
2023-06-10 19:35:04 +03:00
|
|
|
const PARAMETERS = [
|
|
|
|
'user' => [
|
|
|
|
'userId' => [
|
|
|
|
'name' => 'User ID',
|
|
|
|
'exampleValue' => 'qc6CJjYAAAAJ',
|
|
|
|
'required' => true
|
|
|
|
]
|
|
|
|
],
|
|
|
|
'query' => [
|
|
|
|
'q' => [
|
|
|
|
'name' => 'Search Query',
|
|
|
|
'title' => 'Search Query',
|
|
|
|
'required' => true,
|
|
|
|
'exampleValue' => 'machine learning'
|
|
|
|
],
|
|
|
|
'cites' => [
|
|
|
|
'name' => 'Cites',
|
|
|
|
'required' => false,
|
|
|
|
'default' => '',
|
|
|
|
'exampleValue' => '1275980731835430123',
|
|
|
|
'title' => 'Parameter defines unique ID for an article to trigger Cited By searches. Usage of cites
|
|
|
|
will bring up a list of citing documents in Google Scholar. Example value: cites=1275980731835430123.
|
|
|
|
Usage of cites and q parameters triggers search within citing articles.'
|
|
|
|
],
|
|
|
|
'language' => [
|
|
|
|
'name' => 'Language',
|
|
|
|
'required' => false,
|
|
|
|
'default' => '',
|
|
|
|
'exampleValue' => 'en',
|
|
|
|
'title' => 'Parameter defines the language to use for the Google Scholar search. '
|
|
|
|
],
|
|
|
|
'minCitations' => [
|
|
|
|
'name' => 'Minimum Citations',
|
|
|
|
'required' => false,
|
|
|
|
'type' => 'number',
|
|
|
|
'default' => '0',
|
|
|
|
'title' => 'Parameter defines the minimum number of citations in order for the results to be included.'
|
|
|
|
],
|
|
|
|
'sinceYear' => [
|
|
|
|
'name' => 'Since Year',
|
|
|
|
'required' => false,
|
|
|
|
'type' => 'number',
|
|
|
|
'default' => '0',
|
|
|
|
'title' => 'Parameter defines the year from which you want the results to be included.'
|
|
|
|
],
|
|
|
|
'untilYear' => [
|
|
|
|
'name' => 'Until Year',
|
|
|
|
'required' => false,
|
|
|
|
'type' => 'number',
|
|
|
|
'default' => '0',
|
|
|
|
'title' => 'Parameter defines the year until which you want the results to be included.'
|
|
|
|
],
|
|
|
|
'sortBy' => [
|
|
|
|
'name' => 'Sort By Date',
|
|
|
|
'type' => 'checkbox',
|
|
|
|
'default' => false,
|
|
|
|
'title' => 'Parameter defines articles added in the last year, sorted by date. Alternatively sorts
|
|
|
|
by relevance. This overrides Since-Until Year values.',
|
|
|
|
],
|
|
|
|
'includePatents' => [
|
|
|
|
'name' => 'Include Patents',
|
|
|
|
'type' => 'checkbox',
|
|
|
|
'default' => false,
|
|
|
|
'title' => 'Include Patents',
|
|
|
|
],
|
|
|
|
'includeCitations' => [
|
|
|
|
'name' => 'Include Citations',
|
|
|
|
'type' => 'checkbox',
|
|
|
|
'default' => true,
|
|
|
|
'title' => 'Parameter defines whether you would like to include citations or not.',
|
|
|
|
],
|
|
|
|
'reviewArticles' => [
|
|
|
|
'name' => 'Only Review Articles',
|
|
|
|
'type' => 'checkbox',
|
|
|
|
'default' => false,
|
|
|
|
'title' => 'Parameter defines whether you would like to show only review articles or not (these
|
|
|
|
articles consist of topic reviews, or discuss the works or authors you have searched for).',
|
|
|
|
],
|
|
|
|
'numResults' => [
|
|
|
|
'name' => 'Number of Results (max 20)',
|
|
|
|
'required' => false,
|
|
|
|
'type' => 'number',
|
|
|
|
'default' => 10,
|
|
|
|
'exampleValue' => 10,
|
|
|
|
'title' => 'Number of results to return'
|
|
|
|
]
|
|
|
|
],
|
|
|
|
];
|
|
|
|
|
2022-09-25 23:22:49 +03:00
|
|
|
|
|
|
|
public function getIcon()
|
|
|
|
{
|
|
|
|
return 'https://scholar.google.com/favicon.ico';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function collectData()
|
|
|
|
{
|
2023-06-10 19:35:04 +03:00
|
|
|
switch ($this->queriedContext) {
|
|
|
|
case 'user':
|
|
|
|
$userId = $this->getInput('userId');
|
|
|
|
$uri = self::URI . '/citations?hl=en&view_op=list_works&sortby=pubdate&user=' . $userId;
|
|
|
|
$html = getSimpleHTMLDOM($uri) or returnServerError('Could not fetch Google Scholar data.');
|
|
|
|
|
|
|
|
$publications = $html->find('tr[class="gsc_a_tr"]');
|
|
|
|
|
|
|
|
foreach ($publications as $publication) {
|
|
|
|
$articleUrl = self::URI . htmlspecialchars_decode($publication->find('a[class="gsc_a_at"]', 0)->href);
|
|
|
|
$articleTitle = $publication->find('a[class="gsc_a_at"]', 0)->plaintext;
|
|
|
|
|
|
|
|
# fetch the article itself to extract rest of content
|
|
|
|
$contentArticle = getSimpleHTMLDOMCached($articleUrl);
|
|
|
|
$articleEntries = $contentArticle->find('div[class="gs_scl"]');
|
|
|
|
|
|
|
|
$articleDate = '';
|
|
|
|
$articleAbstract = '';
|
|
|
|
$articleAuthor = '';
|
|
|
|
$content = '';
|
|
|
|
|
|
|
|
foreach ($articleEntries as $entry) {
|
|
|
|
$field = $entry->find('div[class="gsc_oci_field"]', 0)->plaintext;
|
|
|
|
$value = $entry->find('div[class="gsc_oci_value"]', 0)->plaintext;
|
|
|
|
|
|
|
|
if ($field == 'Publication date') {
|
|
|
|
$articleDate = $value;
|
|
|
|
} elseif ($field == 'Description') {
|
|
|
|
$articleAbstract = $value;
|
|
|
|
} elseif ($field == 'Authors') {
|
|
|
|
$articleAuthor = $value;
|
|
|
|
} elseif ($field == 'Scholar articles' || $field == 'Total citations') {
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
$content = $content . $field . ': ' . $value . '<br><br>';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$content = $content . $articleAbstract;
|
|
|
|
|
|
|
|
$item = [];
|
|
|
|
|
|
|
|
$item['title'] = $articleTitle;
|
|
|
|
$item['uri'] = $articleUrl;
|
|
|
|
$item['timestamp'] = strtotime($articleDate);
|
|
|
|
$item['author'] = $articleAuthor;
|
|
|
|
$item['content'] = $content;
|
|
|
|
|
|
|
|
$this->items[] = $item;
|
|
|
|
|
|
|
|
if (count($this->items) >= 10) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'query':
|
|
|
|
$query = urlencode($this->getInput('q'));
|
|
|
|
$cites = $this->getInput('cites');
|
|
|
|
$language = $this->getInput('language');
|
|
|
|
$sinceYear = $this->getInput('sinceYear');
|
|
|
|
$untilYear = $this->getInput('untilYear');
|
|
|
|
$minCitations = (int)$this->getInput('minCitations');
|
|
|
|
$includeCitations = $this->getInput('includeCitations');
|
|
|
|
$includePatents = $this->getInput('includePatents');
|
|
|
|
$reviewArticles = $this->getInput('reviewArticles');
|
|
|
|
$sortBy = $this->getInput('sortBy');
|
|
|
|
$numResults = $this->getInput('numResults');
|
|
|
|
|
|
|
|
# Build URI
|
|
|
|
$uri = self::URI . 'scholar?q=' . $query;
|
|
|
|
$uri .= $sinceYear != 0 ? '&as_ylo=' . $sinceYear : '';
|
|
|
|
$uri .= $untilYear != 0 ? '&as_yhi=' . $untilYear : '';
|
|
|
|
$uri .= $language != '' ? '&hl=' . $language : '';
|
|
|
|
$uri .= $includePatents ? '&as_vis=7' : '&as_vis=0';
|
|
|
|
$uri .= $includeCitations ? '&as_vis=0' : ($includePatents ? '&as_vis=1' : '');
|
|
|
|
$uri .= $reviewArticles ? '&as_rr=1' : '';
|
|
|
|
$uri .= $sortBy ? '&scisbd=1' : '';
|
|
|
|
$uri .= $numResults ? '&num=' . $numResults : '';
|
|
|
|
|
|
|
|
$html = getSimpleHTMLDOM($uri) or returnServerError('Could not fetch Google Scholar data.');
|
|
|
|
|
|
|
|
$publications = $html->find('div[class="gs_r gs_or gs_scl"]');
|
|
|
|
|
|
|
|
foreach ($publications as $publication) {
|
|
|
|
$articleTitleElement = $publication->find('h3[class="gs_rt"]', 0);
|
|
|
|
$articleUrl = $articleTitleElement->find('a', 0)->href;
|
|
|
|
$articleTitle = $articleTitleElement->plaintext;
|
|
|
|
|
|
|
|
$articleDateElement = $publication->find('div[class="gs_a"]', 0);
|
|
|
|
$articleDate = $articleDateElement ? $articleDateElement->plaintext : '';
|
|
|
|
|
|
|
|
$articleAbstractElement = $publication->find('div[class="gs_rs"]', 0);
|
|
|
|
$articleAbstract = $articleAbstractElement ? $articleAbstractElement->plaintext : '';
|
|
|
|
|
|
|
|
$articleAuthorElement = $publication->find('div[class="gs_a"]', 0);
|
|
|
|
$articleAuthor = $articleAuthorElement ? $articleAuthorElement->plaintext : '';
|
|
|
|
|
|
|
|
$bottomRowElement = $publication->find('div[class="gs_fl"]', 0);
|
|
|
|
|
|
|
|
$item = [
|
|
|
|
'title' => $articleTitle,
|
|
|
|
'uri' => $articleUrl,
|
|
|
|
'timestamp' => strtotime($articleDate),
|
|
|
|
'author' => $articleAuthor,
|
|
|
|
'content' => $articleAbstract
|
|
|
|
];
|
|
|
|
|
|
|
|
switch ($this->queriedContext) {
|
|
|
|
case 'user':
|
|
|
|
$this->items[] = $item;
|
|
|
|
break;
|
|
|
|
case 'query':
|
|
|
|
$citedBy = 0;
|
|
|
|
if ($bottomRowElement) {
|
|
|
|
$anchorTags = $bottomRowElement->find('a');
|
|
|
|
foreach ($anchorTags as $anchorTag) {
|
|
|
|
if (strpos($anchorTag->plaintext, 'Cited') !== false) {
|
|
|
|
$parts = explode('Cited by ', $anchorTag->plaintext);
|
|
|
|
if (isset($parts[1])) {
|
|
|
|
$citedBy = (int)$parts[1];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($citedBy >= $minCitations) {
|
|
|
|
$this->items[] = $item;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-09-25 23:22:49 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|