Merge pull request #280 from eai04191/feature/remove-status-200
不要な成否判定の削除
This commit is contained in:
commit
92847fefe0
@ -25,19 +25,15 @@ class CienResolver extends MetadataResolver
|
|||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
// 画像URLから有効期限の起点を拾う
|
// 画像URLから有効期限の起点を拾う
|
||||||
parse_str(parse_url($metadata->image, PHP_URL_QUERY), $params);
|
parse_str(parse_url($metadata->image, PHP_URL_QUERY), $params);
|
||||||
if (empty($params['px-time'])) {
|
if (empty($params['px-time'])) {
|
||||||
throw new \RuntimeException('Parameter "px-time" not found. Image=' . $metadata->image . ' Source=' . $url);
|
throw new \RuntimeException('Parameter "px-time" not found. Image=' . $metadata->image . ' Source=' . $url);
|
||||||
}
|
|
||||||
$metadata->expires_at = Carbon::createFromTimestamp($params['px-time'])->addHour(1);
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
$metadata->expires_at = Carbon::createFromTimestamp($params['px-time'])->addHour(1);
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,59 +73,55 @@ class DLsiteResolver implements Resolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
|
|
||||||
// OGPタイトルから[]に囲まれているmakerを取得する
|
// OGPタイトルから[]に囲まれているmakerを取得する
|
||||||
// 複数の作者がいる場合スペース区切りになるためexplodeしている
|
// 複数の作者がいる場合スペース区切りになるためexplodeしている
|
||||||
// スペースを含むmakerの場合名前の一部しか取れないが動作には問題ない
|
// スペースを含むmakerの場合名前の一部しか取れないが動作には問題ない
|
||||||
preg_match('~ \[([^\[\]]*)\] (予告作品 )?\| DLsite(がるまに)?$~', $metadata->title, $match);
|
preg_match('~ \[([^\[\]]*)\] (予告作品 )?\| DLsite(がるまに)?$~', $metadata->title, $match);
|
||||||
$makers = explode(' ', $match[1]);
|
$makers = explode(' ', $match[1]);
|
||||||
|
|
||||||
//フォローボタン(.btn_follow)はテキストを含んでしまうことがあるので要素を削除しておく
|
//フォローボタン(.btn_follow)はテキストを含んでしまうことがあるので要素を削除しておく
|
||||||
$followButtonNode = $xpath->query('//*[@class="btn_follow"]')->item(0);
|
$followButtonNode = $xpath->query('//*[@class="btn_follow"]')->item(0);
|
||||||
$followButtonNode->parentNode->removeChild($followButtonNode);
|
$followButtonNode->parentNode->removeChild($followButtonNode);
|
||||||
|
|
||||||
// maker, makerHeadを探す
|
// maker, makerHeadを探す
|
||||||
|
|
||||||
// makers
|
// makers
|
||||||
// #work_makerから「makerを含むテキスト」を持つ要素を持つtdを探す
|
// #work_makerから「makerを含むテキスト」を持つ要素を持つtdを探す
|
||||||
// 作者名単体の場合もあるし、"作者A / 作者B"のようになることもある
|
// 作者名単体の場合もあるし、"作者A / 作者B"のようになることもある
|
||||||
$makersNode = $xpath->query('//*[@id="work_maker"]//*[contains(text(), "' . $makers[0] . '")]/ancestor::td')->item(0);
|
$makersNode = $xpath->query('//*[@id="work_maker"]//*[contains(text(), "' . $makers[0] . '")]/ancestor::td')->item(0);
|
||||||
// nbspをspaceに置換
|
// nbspをspaceに置換
|
||||||
$makers = trim(str_replace("\xc2\xa0", ' ', $makersNode->textContent));
|
$makers = trim(str_replace("\xc2\xa0", ' ', $makersNode->textContent));
|
||||||
|
|
||||||
// makersHaed
|
// makersHaed
|
||||||
// $makerNode(td)に対するthを探す
|
// $makerNode(td)に対するthを探す
|
||||||
// "著者", "サークル名", "ブランド名"など
|
// "著者", "サークル名", "ブランド名"など
|
||||||
$makersHeadNode = $xpath->query('preceding-sibling::th', $makersNode)->item(0);
|
$makersHeadNode = $xpath->query('preceding-sibling::th', $makersNode)->item(0);
|
||||||
$makersHead = trim($makersHeadNode->textContent);
|
$makersHead = trim($makersHeadNode->textContent);
|
||||||
|
|
||||||
// 余分な文を消す
|
// 余分な文を消す
|
||||||
|
|
||||||
// OGPタイトルから作者名とサイト名を消す
|
// OGPタイトルから作者名とサイト名を消す
|
||||||
$metadata->title = trim(preg_replace('~ \[[^\[\]]*\] (予告作品 )?\| DLsite(がるまに)?$~', '', $metadata->title));
|
$metadata->title = trim(preg_replace('~ \[[^\[\]]*\] (予告作品 )?\| DLsite(がるまに)?$~', '', $metadata->title));
|
||||||
|
|
||||||
// OGP説明文から定型文を消す
|
// OGP説明文から定型文を消す
|
||||||
if (strpos($url, 'dlsite.com/eng/') || strpos($url, 'dlsite.com/ecchi-eng/')) {
|
if (strpos($url, 'dlsite.com/eng/') || strpos($url, 'dlsite.com/ecchi-eng/')) {
|
||||||
$metadata->description = preg_replace('~DLsite.+ is a download shop for .+With a huge selection of products, we\'re sure you\'ll find whatever tickles your fancy\. DLsite is one of the greatest indie contents download shops in Japan\.$~', '', $metadata->description);
|
$metadata->description = preg_replace('~DLsite.+ is a download shop for .+With a huge selection of products, we\'re sure you\'ll find whatever tickles your fancy\. DLsite is one of the greatest indie contents download shops in Japan\.$~', '', $metadata->description);
|
||||||
} else {
|
|
||||||
$metadata->description = preg_replace('~「DLsite.+」は.+のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる!毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」!$~', '', $metadata->description);
|
|
||||||
}
|
|
||||||
$metadata->description = trim(strip_tags($metadata->description));
|
|
||||||
|
|
||||||
// 整形
|
|
||||||
$metadata->description = $makersHead . ': ' . $makers . PHP_EOL . $metadata->description;
|
|
||||||
$metadata->image = str_replace('img_sam.jpg', 'img_main.jpg', $metadata->image);
|
|
||||||
$metadata->tags = $this->extractTags($res->getBody());
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
} else {
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
$metadata->description = preg_replace('~「DLsite.+」は.+のダウンロードショップ。お気に入りの作品をすぐダウンロードできてすぐ楽しめる!毎日更新しているのであなたが探している作品にきっと出会えます。国内最大級の二次元総合ダウンロードショップ「DLsite」!$~', '', $metadata->description);
|
||||||
}
|
}
|
||||||
|
$metadata->description = trim(strip_tags($metadata->description));
|
||||||
|
|
||||||
|
// 整形
|
||||||
|
$metadata->description = $makersHead . ': ' . $makers . PHP_EOL . $metadata->description;
|
||||||
|
$metadata->image = str_replace('img_sam.jpg', 'img_main.jpg', $metadata->image);
|
||||||
|
$metadata->tags = $this->extractTags($res->getBody());
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,21 +24,17 @@ class FC2ContentsResolver implements Resolver
|
|||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
|
|
||||||
$thumbnailNode = $xpath->query('//*[@class="main_thum_img"]/a')->item(0);
|
$thumbnailNode = $xpath->query('//*[@class="main_thum_img"]/a')->item(0);
|
||||||
if ($thumbnailNode) {
|
if ($thumbnailNode) {
|
||||||
$metadata->image = preg_replace('~^http:~', 'https:', $thumbnailNode->getAttribute('href'));
|
$metadata->image = preg_replace('~^http:~', 'https:', $thumbnailNode->getAttribute('href'));
|
||||||
}
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,29 +28,25 @@ class FantiaResolver implements Resolver
|
|||||||
$postId = $match[0];
|
$postId = $match[0];
|
||||||
|
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
|
|
||||||
$node = $xpath->query("//meta[@property='twitter:image']")->item(0);
|
$node = $xpath->query("//meta[@property='twitter:image']")->item(0);
|
||||||
$ogpUrl = $node->getAttribute('content');
|
$ogpUrl = $node->getAttribute('content');
|
||||||
|
|
||||||
// 投稿に画像がない場合(ogp.jpgでない場合)のみ大きい画像に変換する
|
// 投稿に画像がない場合(ogp.jpgでない場合)のみ大きい画像に変換する
|
||||||
if ($ogpUrl != 'http://fantia.jp/images/ogp.jpg') {
|
if ($ogpUrl != 'http://fantia.jp/images/ogp.jpg') {
|
||||||
preg_match("~https://fantia\.s3\.amazonaws\.com/uploads/post/file/{$postId}/ogp_(.*?)\.(jpg|png)~", $ogpUrl, $match);
|
preg_match("~https://fantia\.s3\.amazonaws\.com/uploads/post/file/{$postId}/ogp_(.*?)\.(jpg|png)~", $ogpUrl, $match);
|
||||||
$uuid = $match[1];
|
$uuid = $match[1];
|
||||||
$extension = $match[2];
|
$extension = $match[2];
|
||||||
|
|
||||||
// 大きい画像に変換
|
// 大きい画像に変換
|
||||||
$metadata->image = "https://c.fantia.jp/uploads/post/file/{$postId}/main_{$uuid}.{$extension}";
|
$metadata->image = "https://c.fantia.jp/uploads/post/file/{$postId}/main_{$uuid}.{$extension}";
|
||||||
}
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,10 @@ class FanzaResolver implements Resolver
|
|||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
$metadata->image = preg_replace("~(pr|ps)\.jpg$~", 'pl.jpg', $metadata->image);
|
||||||
$metadata->image = preg_replace("~(pr|ps)\.jpg$~", 'pl.jpg', $metadata->image);
|
$metadata->description = str_replace('<>', '', $metadata->description);
|
||||||
$metadata->description = str_replace('<>', '', $metadata->description);
|
|
||||||
|
|
||||||
return $metadata;
|
return $metadata;
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,45 +20,41 @@ class IwaraResolver implements Resolver
|
|||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = new Metadata();
|
||||||
$metadata = new Metadata();
|
$html = (string) $res->getBody();
|
||||||
$html = (string) $res->getBody();
|
$crawler = new Crawler($html);
|
||||||
$crawler = new Crawler($html);
|
|
||||||
|
|
||||||
$infoElements = $crawler->filter('#video-player + div, .field-name-field-video-url + div, .field-name-field-images + div');
|
$infoElements = $crawler->filter('#video-player + div, .field-name-field-video-url + div, .field-name-field-images + div');
|
||||||
$title = $infoElements->filter('h1.title')->text();
|
$title = $infoElements->filter('h1.title')->text();
|
||||||
$author = $infoElements->filter('.username')->text();
|
$author = $infoElements->filter('.username')->text();
|
||||||
$description = $infoElements->filter('.field-type-text-with-summary')->text('');
|
$description = $infoElements->filter('.field-type-text-with-summary')->text('');
|
||||||
$tags = $infoElements->filter('a[href^="/videos"], a[href^="/images"]')->extract('_text');
|
$tags = $infoElements->filter('a[href^="/videos"], a[href^="/images"]')->extract('_text');
|
||||||
// 役に立たないタグを削除する
|
// 役に立たないタグを削除する
|
||||||
$tags = array_values(array_diff($tags, ['Uncategorized', 'Other']));
|
$tags = array_values(array_diff($tags, ['Uncategorized', 'Other']));
|
||||||
array_push($tags, $author);
|
array_push($tags, $author);
|
||||||
|
|
||||||
$metadata->title = $title;
|
$metadata->title = $title;
|
||||||
$metadata->description = '投稿者: ' . $author . PHP_EOL . $description;
|
$metadata->description = '投稿者: ' . $author . PHP_EOL . $description;
|
||||||
$metadata->tags = $tags;
|
$metadata->tags = $tags;
|
||||||
|
|
||||||
// iwara video
|
// iwara video
|
||||||
if ($crawler->filter('#video-player')->count()) {
|
if ($crawler->filter('#video-player')->count()) {
|
||||||
$metadata->image = 'https:' . $crawler->filter('#video-player')->attr('poster');
|
$metadata->image = 'https:' . $crawler->filter('#video-player')->attr('poster');
|
||||||
}
|
|
||||||
|
|
||||||
// youtube
|
|
||||||
if ($crawler->filter('iframe[src^="//www.youtube.com"]')->count()) {
|
|
||||||
if (preg_match('~youtube\.com/embed/(\S+)\?~', $crawler->filter('iframe[src^="//www.youtube.com"]')->attr('src'), $matches) === 1) {
|
|
||||||
$youtubeId = $matches[1];
|
|
||||||
$metadata->image = 'https://img.youtube.com/vi/' . $youtubeId . '/maxresdefault.jpg';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// images
|
|
||||||
if ($crawler->filter('.field-name-field-images')->count()) {
|
|
||||||
$metadata->image = 'https:' . $crawler->filter('.field-name-field-images a')->first()->attr('href');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// youtube
|
||||||
|
if ($crawler->filter('iframe[src^="//www.youtube.com"]')->count()) {
|
||||||
|
if (preg_match('~youtube\.com/embed/(\S+)\?~', $crawler->filter('iframe[src^="//www.youtube.com"]')->attr('src'), $matches) === 1) {
|
||||||
|
$youtubeId = $matches[1];
|
||||||
|
$metadata->image = 'https://img.youtube.com/vi/' . $youtubeId . '/maxresdefault.jpg';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// images
|
||||||
|
if ($crawler->filter('.field-name-field-images')->count()) {
|
||||||
|
$metadata->image = 'https:' . $crawler->filter('.field-name-field-images a')->first()->attr('href');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,33 +24,28 @@ class KomifloResolver implements Resolver
|
|||||||
$id = $matches[1];
|
$id = $matches[1];
|
||||||
|
|
||||||
$res = $this->client->get('https://api.komiflo.com/content/id/' . $id);
|
$res = $this->client->get('https://api.komiflo.com/content/id/' . $id);
|
||||||
if ($res->getStatusCode() === 200) {
|
$json = json_decode($res->getBody()->getContents(), true);
|
||||||
$json = json_decode($res->getBody()->getContents(), true);
|
$metadata = new Metadata();
|
||||||
$metadata = new Metadata();
|
|
||||||
|
|
||||||
$metadata->title = $json['content']['data']['title'] ?? '';
|
$metadata->title = $json['content']['data']['title'] ?? '';
|
||||||
$metadata->description = ($json['content']['attributes']['artists']['children'][0]['data']['name'] ?? '?') .
|
$metadata->description = ($json['content']['attributes']['artists']['children'][0]['data']['name'] ?? '?') .
|
||||||
' - ' .
|
' - ' . ($json['content']['parents'][0]['data']['title'] ?? '?');
|
||||||
($json['content']['parents'][0]['data']['title'] ?? '?');
|
$metadata->image = 'https://t.komiflo.com/564_mobile_large_3x/' . $json['content']['named_imgs']['cover']['filename'];
|
||||||
$metadata->image = 'https://t.komiflo.com/564_mobile_large_3x/' . $json['content']['named_imgs']['cover']['filename'];
|
|
||||||
|
|
||||||
// 作者情報
|
// 作者情報
|
||||||
if (!empty($json['content']['attributes']['artists']['children'])) {
|
if (!empty($json['content']['attributes']['artists']['children'])) {
|
||||||
foreach ($json['content']['attributes']['artists']['children'] as $artist) {
|
foreach ($json['content']['attributes']['artists']['children'] as $artist) {
|
||||||
$metadata->tags[] = preg_replace('/\s/', '_', $artist['data']['name']);
|
$metadata->tags[] = preg_replace('/\s/', '_', $artist['data']['name']);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// タグ
|
|
||||||
if (!empty($json['content']['attributes']['tags']['children'])) {
|
|
||||||
foreach ($json['content']['attributes']['tags']['children'] as $tag) {
|
|
||||||
$metadata->tags[] = preg_replace('/\s/', '_', $tag['data']['name']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// タグ
|
||||||
|
if (!empty($json['content']['attributes']['tags']['children'])) {
|
||||||
|
foreach ($json['content']['attributes']['tags']['children'] as $tag) {
|
||||||
|
$metadata->tags[] = preg_replace('/\s/', '_', $tag['data']['name']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,46 +27,42 @@ class MelonbooksResolver implements Resolver
|
|||||||
$cookieJar = CookieJar::fromArray(['AUTH_ADULT' => '1'], 'www.melonbooks.co.jp');
|
$cookieJar = CookieJar::fromArray(['AUTH_ADULT' => '1'], 'www.melonbooks.co.jp');
|
||||||
|
|
||||||
$res = $this->client->get($url, ['cookies' => $cookieJar]);
|
$res = $this->client->get($url, ['cookies' => $cookieJar]);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
$descriptionNodelist = $xpath->query('//div[@id="description"]//p');
|
$descriptionNodelist = $xpath->query('//div[@id="description"]//p');
|
||||||
$specialDescriptionNodelist = $xpath->query('//div[@id="special_description"]//p');
|
$specialDescriptionNodelist = $xpath->query('//div[@id="special_description"]//p');
|
||||||
|
|
||||||
// censoredフラグの除去
|
// censoredフラグの除去
|
||||||
if (mb_strpos($metadata->image, '&c=1') !== false) {
|
if (mb_strpos($metadata->image, '&c=1') !== false) {
|
||||||
$metadata->image = preg_replace('/&c=1/u', '', $metadata->image);
|
$metadata->image = preg_replace('/&c=1/u', '', $metadata->image);
|
||||||
}
|
|
||||||
|
|
||||||
// 抽出
|
|
||||||
preg_match('~^(.+)((.+))の通販・購入はメロンブックス$~', $metadata->title, $match);
|
|
||||||
$title = $match[1];
|
|
||||||
$maker = $match[2];
|
|
||||||
|
|
||||||
// 整形
|
|
||||||
$description = 'サークル: ' . $maker . "\n";
|
|
||||||
|
|
||||||
if ($specialDescriptionNodelist->length !== 0) {
|
|
||||||
$description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(0)->nodeValue)) . "\n";
|
|
||||||
if ($specialDescriptionNodelist->length === 2) {
|
|
||||||
$description .= "\n";
|
|
||||||
$description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(1)->nodeValue)) . "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($descriptionNodelist->length !== 0) {
|
|
||||||
$description .= trim(str_replace('<br>', "\n", $descriptionNodelist->item(0)->nodeValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
$metadata->title = $title;
|
|
||||||
$metadata->description = trim($description);
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 抽出
|
||||||
|
preg_match('~^(.+)((.+))の通販・購入はメロンブックス$~', $metadata->title, $match);
|
||||||
|
$title = $match[1];
|
||||||
|
$maker = $match[2];
|
||||||
|
|
||||||
|
// 整形
|
||||||
|
$description = 'サークル: ' . $maker . "\n";
|
||||||
|
|
||||||
|
if ($specialDescriptionNodelist->length !== 0) {
|
||||||
|
$description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(0)->nodeValue)) . "\n";
|
||||||
|
if ($specialDescriptionNodelist->length === 2) {
|
||||||
|
$description .= "\n";
|
||||||
|
$description .= trim(str_replace('<br>', "\n", $specialDescriptionNodelist->item(1)->nodeValue)) . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($descriptionNodelist->length !== 0) {
|
||||||
|
$description .= trim(str_replace('<br>', "\n", $descriptionNodelist->item(0)->nodeValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
$metadata->title = $title;
|
||||||
|
$metadata->description = trim($description);
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,34 +27,30 @@ class NarouResolver implements Resolver
|
|||||||
$cookieJar = CookieJar::fromArray(['over18' => 'yes'], '.syosetu.com');
|
$cookieJar = CookieJar::fromArray(['over18' => 'yes'], '.syosetu.com');
|
||||||
|
|
||||||
$res = $this->client->get($url, ['cookies' => $cookieJar]);
|
$res = $this->client->get($url, ['cookies' => $cookieJar]);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
$metadata->description = '';
|
||||||
$metadata->description = '';
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win'));
|
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'ASCII,JIS,UTF-8,eucJP-win,SJIS-win'));
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
|
|
||||||
$description = [];
|
$description = [];
|
||||||
|
|
||||||
// 作者名
|
// 作者名
|
||||||
$writerNodes = $xpath->query('//*[contains(@class, "novel_writername")]');
|
$writerNodes = $xpath->query('//*[contains(@class, "novel_writername")]');
|
||||||
if ($writerNodes->length !== 0 && !empty($writerNodes->item(0)->textContent)) {
|
if ($writerNodes->length !== 0 && !empty($writerNodes->item(0)->textContent)) {
|
||||||
$description[] = trim($writerNodes->item(0)->textContent);
|
$description[] = trim($writerNodes->item(0)->textContent);
|
||||||
}
|
|
||||||
|
|
||||||
// あらすじ
|
|
||||||
$exNodes = $xpath->query('//*[@id="novel_ex"]');
|
|
||||||
if ($exNodes->length !== 0 && !empty($exNodes->item(0)->textContent)) {
|
|
||||||
$summary = trim($exNodes->item(0)->textContent);
|
|
||||||
$description[] = mb_strimwidth($summary, 0, 101, '…'); // 100 + '…'(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
$metadata->description = implode(' / ', $description);
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// あらすじ
|
||||||
|
$exNodes = $xpath->query('//*[@id="novel_ex"]');
|
||||||
|
if ($exNodes->length !== 0 && !empty($exNodes->item(0)->textContent)) {
|
||||||
|
$summary = trim($exNodes->item(0)->textContent);
|
||||||
|
$description[] = mb_strimwidth($summary, 0, 101, '…'); // 100 + '…'(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
$metadata->description = implode(' / ', $description);
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,32 +32,28 @@ class NijieResolver implements Resolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$html = (string) $res->getBody();
|
||||||
$html = (string) $res->getBody();
|
$metadata = $this->ogpResolver->parse($html);
|
||||||
$metadata = $this->ogpResolver->parse($html);
|
$crawler = new Crawler($html);
|
||||||
$crawler = new Crawler($html);
|
|
||||||
|
|
||||||
// DomCrawler内でjson内の日本語がHTMLエンティティに変換されるのでhtml_entity_decode
|
// DomCrawler内でjson内の日本語がHTMLエンティティに変換されるのでhtml_entity_decode
|
||||||
$json = html_entity_decode($crawler->filter('script[type="application/ld+json"]')->first()->text());
|
$json = html_entity_decode($crawler->filter('script[type="application/ld+json"]')->first()->text());
|
||||||
|
|
||||||
// 改行がそのまま入っていることがあるのでデコード前にエスケープが必要
|
// 改行がそのまま入っていることがあるのでデコード前にエスケープが必要
|
||||||
$data = json_decode(preg_replace('/\r?\n/', '\n', $json), true);
|
$data = json_decode(preg_replace('/\r?\n/', '\n', $json), true);
|
||||||
|
|
||||||
$metadata->title = $data['name'];
|
$metadata->title = $data['name'];
|
||||||
$metadata->description = '投稿者: ' . $data['author']['name'] . PHP_EOL . $data['description'];
|
$metadata->description = '投稿者: ' . $data['author']['name'] . PHP_EOL . $data['description'];
|
||||||
if (
|
if (
|
||||||
isset($data['thumbnailUrl']) &&
|
isset($data['thumbnailUrl']) &&
|
||||||
!ends_with($data['thumbnailUrl'], '.gif') &&
|
!ends_with($data['thumbnailUrl'], '.gif') &&
|
||||||
!ends_with($data['thumbnailUrl'], '.mp4')
|
!ends_with($data['thumbnailUrl'], '.mp4')
|
||||||
) {
|
) {
|
||||||
// サムネイルからメイン画像に
|
// サムネイルからメイン画像に
|
||||||
$metadata->image = str_replace('__rs_l160x160/', '', $data['thumbnailUrl']);
|
$metadata->image = str_replace('__rs_l160x160/', '', $data['thumbnailUrl']);
|
||||||
}
|
|
||||||
$metadata->tags = $crawler->filter('#view-tag span.tag_name')->extract('_text');
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
$metadata->tags = $crawler->filter('#view-tag span.tag_name')->extract('_text');
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,7 @@ class OGPResolver implements Resolver, Parser
|
|||||||
|
|
||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
return $this->parse($this->client->get($url)->getBody());
|
||||||
if ($res->getStatusCode() === 200) {
|
|
||||||
return $this->parse($res->getBody());
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function parse(string $html): Metadata
|
public function parse(string $html): Metadata
|
||||||
|
@ -25,18 +25,14 @@ class PatreonResolver implements Resolver
|
|||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
parse_str(parse_url($metadata->image, PHP_URL_QUERY), $query);
|
parse_str(parse_url($metadata->image, PHP_URL_QUERY), $query);
|
||||||
if (isset($query['token-time'])) {
|
if (isset($query['token-time'])) {
|
||||||
$expires_at_unixtime = $query['token-time'];
|
$expires_at_unixtime = $query['token-time'];
|
||||||
$metadata->expires_at = Carbon::createFromTimestamp($expires_at_unixtime);
|
$metadata->expires_at = Carbon::createFromTimestamp($expires_at_unixtime);
|
||||||
}
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,14 +38,10 @@ class PixivResolver implements Resolver
|
|||||||
{
|
{
|
||||||
if (preg_match('~www\.pixiv\.net/user/\d+/series/\d+~', $url, $matches)) {
|
if (preg_match('~www\.pixiv\.net/user/\d+/series/\d+~', $url, $matches)) {
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
$metadata->image = $this->proxize($metadata->image);
|
||||||
$metadata->image = $this->proxize($metadata->image);
|
|
||||||
|
|
||||||
return $metadata;
|
return $metadata;
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_str(parse_url($url, PHP_URL_QUERY), $params);
|
parse_str(parse_url($url, PHP_URL_QUERY), $params);
|
||||||
@ -58,32 +54,28 @@ class PixivResolver implements Resolver
|
|||||||
}
|
}
|
||||||
|
|
||||||
$res = $this->client->get('https://www.pixiv.net/ajax/illust/' . $illustId);
|
$res = $this->client->get('https://www.pixiv.net/ajax/illust/' . $illustId);
|
||||||
if ($res->getStatusCode() === 200) {
|
$json = json_decode($res->getBody()->getContents(), true);
|
||||||
$json = json_decode($res->getBody()->getContents(), true);
|
$metadata = new Metadata();
|
||||||
$metadata = new Metadata();
|
|
||||||
|
|
||||||
$metadata->title = $json['body']['illustTitle'] ?? '';
|
$metadata->title = $json['body']['illustTitle'] ?? '';
|
||||||
$metadata->description = '投稿者: ' . $json['body']['userName'] . PHP_EOL . strip_tags(str_replace('<br />', PHP_EOL, $json['body']['illustComment'] ?? ''));
|
$metadata->description = '投稿者: ' . $json['body']['userName'] . PHP_EOL . strip_tags(str_replace('<br />', PHP_EOL, $json['body']['illustComment'] ?? ''));
|
||||||
$metadata->image = $this->proxize($json['body']['urls']['regular'] ?? '');
|
$metadata->image = $this->proxize($json['body']['urls']['regular'] ?? '');
|
||||||
|
|
||||||
// ページ数の指定がある場合は画像URLをそのページにする
|
// ページ数の指定がある場合は画像URLをそのページにする
|
||||||
if ($page != 0) {
|
if ($page != 0) {
|
||||||
$metadata->image = str_replace('_p0', '_p'.$page, $metadata->image);
|
$metadata->image = str_replace('_p0', '_p' . $page, $metadata->image);
|
||||||
}
|
}
|
||||||
|
|
||||||
// タグ
|
// タグ
|
||||||
if (!empty($json['body']['tags']['tags'])) {
|
if (!empty($json['body']['tags']['tags'])) {
|
||||||
foreach ($json['body']['tags']['tags'] as $tag) {
|
foreach ($json['body']['tags']['tags'] as $tag) {
|
||||||
// 一部の固定キーワードは無視
|
// 一部の固定キーワードは無視
|
||||||
if (array_search($tag['tag'], ['R-18', 'イラスト', 'pixiv', 'ピクシブ'], true) === false) {
|
if (array_search($tag['tag'], ['R-18', 'イラスト', 'pixiv', 'ピクシブ'], true) === false) {
|
||||||
$metadata->tags[] = preg_replace('/\s/', '_', $tag['tag']);
|
$metadata->tags[] = preg_replace('/\s/', '_', $tag['tag']);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,21 +24,17 @@ class PlurkResolver implements Resolver
|
|||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
$imageNode = $xpath->query('//div[@class="text_holder"]/a[1]')->item(0);
|
$imageNode = $xpath->query('//div[@class="text_holder"]/a[1]')->item(0);
|
||||||
|
|
||||||
if ($imageNode) {
|
if ($imageNode) {
|
||||||
$metadata->image = $imageNode->getAttribute('href');
|
$metadata->image = $imageNode->getAttribute('href');
|
||||||
}
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,21 +24,17 @@ class SteamResolver implements Resolver
|
|||||||
$appid = $matches[1];
|
$appid = $matches[1];
|
||||||
|
|
||||||
$res = $this->client->get('https://store.steampowered.com/api/appdetails/?l=japanese&appids=' . $appid);
|
$res = $this->client->get('https://store.steampowered.com/api/appdetails/?l=japanese&appids=' . $appid);
|
||||||
if ($res->getStatusCode() === 200) {
|
$json = json_decode($res->getBody()->getContents(), true);
|
||||||
$json = json_decode($res->getBody()->getContents(), true);
|
if ($json[$appid]['success'] === false) {
|
||||||
if ($json[$appid]['success'] === false) {
|
throw new \RuntimeException("API response [$appid][success] is false: $url");
|
||||||
throw new \RuntimeException("API response [$appid][success] is false: $url");
|
|
||||||
}
|
|
||||||
$data = $json[$appid]['data'];
|
|
||||||
$metadata = new Metadata();
|
|
||||||
|
|
||||||
$metadata->title = $data['name'] ?? '';
|
|
||||||
$metadata->description = strip_tags(str_replace('<br />', PHP_EOL, html_entity_decode($data['short_description'] ?? '')));
|
|
||||||
$metadata->image = $data['header_image'] ?? '';
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
$data = $json[$appid]['data'];
|
||||||
|
$metadata = new Metadata();
|
||||||
|
|
||||||
|
$metadata->title = $data['name'] ?? '';
|
||||||
|
$metadata->description = strip_tags(str_replace('<br />', PHP_EOL, html_entity_decode($data['short_description'] ?? '')));
|
||||||
|
$metadata->image = $data['header_image'] ?? '';
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,20 +25,16 @@ class ToranoanaResolver implements Resolver
|
|||||||
public function resolve(string $url): Metadata
|
public function resolve(string $url): Metadata
|
||||||
{
|
{
|
||||||
$res = $this->client->get($url);
|
$res = $this->client->get($url);
|
||||||
if ($res->getStatusCode() === 200) {
|
$metadata = $this->ogpResolver->parse($res->getBody());
|
||||||
$metadata = $this->ogpResolver->parse($res->getBody());
|
|
||||||
|
|
||||||
$dom = new \DOMDocument();
|
$dom = new \DOMDocument();
|
||||||
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
@$dom->loadHTML(mb_convert_encoding($res->getBody(), 'HTML-ENTITIES', 'UTF-8'));
|
||||||
$xpath = new \DOMXPath($dom);
|
$xpath = new \DOMXPath($dom);
|
||||||
$imgNode = $xpath->query('//*[@id="preview"]//img')->item(0);
|
$imgNode = $xpath->query('//*[@id="preview"]//img')->item(0);
|
||||||
if ($imgNode !== null) {
|
if ($imgNode !== null) {
|
||||||
$metadata->image = $imgNode->getAttribute('src');
|
$metadata->image = $imgNode->getAttribute('src');
|
||||||
}
|
|
||||||
|
|
||||||
return $metadata;
|
|
||||||
} else {
|
|
||||||
throw new \RuntimeException("{$res->getStatusCode()}: $url");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $metadata;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ namespace Tests\Unit\MetadataResolver;
|
|||||||
use App\MetadataResolver\Resolver;
|
use App\MetadataResolver\Resolver;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Handler\MockHandler;
|
use GuzzleHttp\Handler\MockHandler;
|
||||||
|
use GuzzleHttp\HandlerStack;
|
||||||
use GuzzleHttp\Psr7\Response;
|
use GuzzleHttp\Psr7\Response;
|
||||||
use Monolog\Handler\AbstractHandler;
|
use Monolog\Handler\AbstractHandler;
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ trait CreateMockedResolver
|
|||||||
|
|
||||||
$mockResponse = new Response($status, $headers, $responseText);
|
$mockResponse = new Response($status, $headers, $responseText);
|
||||||
$this->handler = new MockHandler([$mockResponse]);
|
$this->handler = new MockHandler([$mockResponse]);
|
||||||
$client = new Client(['handler' => $this->handler]);
|
$client = new Client(['handler' => HandlerStack::create($this->handler)]);
|
||||||
$this->resolver = app()->make($resolverClass, ['client' => $client]);
|
$this->resolver = app()->make($resolverClass, ['client' => $client]);
|
||||||
|
|
||||||
return $this->resolver;
|
return $this->resolver;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace Tests\Unit\MetadataResolver;
|
namespace Tests\Unit\MetadataResolver;
|
||||||
|
|
||||||
use App\MetadataResolver\OGPResolver;
|
use App\MetadataResolver\OGPResolver;
|
||||||
use GuzzleHttp\Exception\ClientException;
|
use GuzzleHttp\Exception\BadResponseException;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class OGPResolverTest extends TestCase
|
class OGPResolverTest extends TestCase
|
||||||
@ -14,7 +14,7 @@ class OGPResolverTest extends TestCase
|
|||||||
{
|
{
|
||||||
$this->createResolver(OGPResolver::class, '', [], 404);
|
$this->createResolver(OGPResolver::class, '', [], 404);
|
||||||
|
|
||||||
$this->expectException(\RuntimeException::class);
|
$this->expectException(BadResponseException::class);
|
||||||
$this->resolver->resolve('http://example.com/404');
|
$this->resolver->resolve('http://example.com/404');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user