LINE Messaging APIとGoutteを使用して最新記事を送信してもらう

# はじめに
2020年度XTechグループアドベントカレンダーの13日目を担当します、iXIT株式会社の21卒内定者、小長谷です！
LINE Messaging API と Goutte を使用したボットについて書きます。

# 作成したもの
私が普段閲覧している[Techable](https://techable.jp/)の最新記事を、[Goutte](https://packagist.org/packages/fabpot/goutte)（PHPのライブラリ）を用いてスクレイピングし、LINEで送信してもらうボットを作成しました。

>[Techable（テッカブル） -海外・国内のネットベンチャー系ニュースサイト](https://techable.jp/)  
>
>[fabpot/goutte - Packagist](https://packagist.org/packages/fabpot/goutte)

#### *最新記事* と送信すると、その時の最新記事の一覧を返してくれます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/2dd30337-9314-418b-ad24-e784848d2ff6.png" width=35%>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/a0355f82-871c-68d0-3bbc-038c1e472053.png" width=35%>


#### 記事の詳細を見たい場合、 *サイトへ* をタップすることでサイトへ移動します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/ac5de976-54ae-93fe-589f-fc89505aaa46.png" width=35%>　<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/cf588976-cabb-1359-9ad2-c57ef14f3609.png" width=35%>


#### 実行時のページ画像
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/7cf20933-77dc-e112-aa50-114c671266d2.jpeg" width=45%>


# 環境
macOS BigSur 11.0.1
PHP 7.3.22

# テンプレートメッセージを送信するボットを作成する
LINE Developersのガイドに、サンプルのボットを作成するまでのチュートリアルがあるので、スムーズに始めることができました！
https://developers.line.biz/ja/docs/messaging-api/

### カルーセルテンプレートの作成
送信するメッセージには様々なタイプがあります。私は今回**カルーセルテンプレート**を使用しました。
https://developers.line.biz/ja/docs/messaging-api/message-types/#carousel-template
>##### カルーセルテンプレート
>複数のカラムを表示するテンプレートです。カラムは横にスクロールして順番に表示できます。
><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/90c7a32e-5c4e-2d2e-ebbe-06a56b1cd348.png" width=35%>

私が作成したものは、それぞれのカラムに**画像**、**タイトル**、**テキスト**、**アクション**を配置しました。  

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/883a1682-ece3-0b1b-6223-52ad36782da7.jpeg" width=40%>

１つのカラムだけ配置するコードを以下のように書きました。

```php
<?php
require_once dirname(__FILE__) . '/vendor/autoload.php';

use LINE\LINEBot\Constant\HTTPHeader;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;
use LINE\LINEBot;
use LINE\LINEBot\TemplateActionBuilder\UriTemplateActionBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselColumnTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateBuilder\CarouselTemplateBuilder;
use LINE\LINEBot\MessageBuilder\TemplateMessageBuilder;

$channel_access_token = 'xxxxx';
$channel_secret = 'xxxxx';

$httpClient = new CurlHTTPClient($channel_access_token);
$bot = new LINEBot($httpClient, ['channelSecret' => $channel_secret]);

$events = $bot->parseEventRequest(file_get_contents('php://input'), $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]);
$event = $events[0];

$columns = [];

$action = new UriTemplateActionBuilder("サイトへ", "クリックしたとき、開かれるURI");
$column = new CarouselColumnTemplateBuilder("タイトル（40字以内）", "テキスト（画像、タイトルを指定する場合60字以内）", "画像URL", [$action]);

$columns[] = $column;

$carousel = new CarouselTemplateBuilder($columns);
$templateMessageBuilder = new TemplateMessageBuilder("メッセージのタイトル", $carousel);
$response = $bot->replyMessage($event->getReplyToken(), $templateMessageBuilder);
```



# Goutteで記事をスクレイピングする
次に、カラムに必要な**画像**、**タイトル**、**テキスト**、**アクション**（に使用する、記事へのURL）を、[Goutte](https://packagist.org/packages/fabpot/goutte)を用いて[Techable](https://techable.jp/)からスクレイピングしました。
１つの記事を取得するコードを以下のように書きました。

```php
<?php
require_once dirname(__FILE__) . '/vendor/autoload.php';

$goutteClient = new Goutte\Client();
$crawler = $goutteClient->request("GET", "https://techable.jp/");

$articleUrl = $crawler->filter("#panel-whatsnew")->filter(".te-articles__list__item")->filter("a")->extract(["href"])[0];
echo "記事のURL: " . $articleUrl . PHP_EOL;

$title = $crawler->filter("#panel-whatsnew")->filter(".te-articles__list__item")->filter(".te-articles__list__item__content__title")->text();
echo "記事のタイトル: " . $title . PHP_EOL;

$text = $crawler->filter("#panel-whatsnew")->filter(".te-articles__list__item")->filter(".te-articles__list__item__content__summary")->text();
echo "記事のテキスト: " . $text . PHP_EOL;

$img = $crawler->filter("#panel-whatsnew")->filter(".te-articles__list__item")->filter(".te-articles__list__item__thumb__img")->extract(["style"])[0];
$img = getUrl($img);
echo "画像URL: " . $img. PHP_EOL;

/*
 * CSSプロパティで設定された背景画像のURLを取り出す
 * " background-image: url( https://xxx.png ); "
 *    ↓
 * " https://xxx.png "
 */
function getUrl($img)
{
    preg_match("/(https).*\.(png|jpg|jpeg)/i", $img, $match);
    return $match[0];
}
```

```console
$ php index.php

記事のリンク: https://techable.jp/archives/143963
記事のタイトル: 楽天、UGVによるスーパーからの商品配送サービス実現に向け横須賀市で実証実験
記事のテキスト: 楽天株式会社と神奈川県横須賀市は、2019年に「西友 リヴィンよこすか店」から港湾緑地「うみかぜ公園1年前半には、同市...
画像URL: https://techable.jp/wp-content/uploads/2020/12/32156cdde08f9a24d1d321145576baed.png
```

#### 上記コード実行時のページ画像  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908248/2bed996f-4ad6-299c-0b97-be9d862685b1.png">

以上の処理を取得したい記事に対して行い、カラムを作成しました。


# 最後に
LINE Messaging API と Goutte を使用したボットについて書かせていただきました。
今後は人気記事を送信してくれる機能などを追加して、多機能なボットにしようと思います！

XTechグループのアドベントカレンダーはまだまだ続きます。お楽しみに！

# 以下の情報を参考にしました
[Messaging APIリファレンス](https://developers.line.biz/ja/reference/messaging-api/)
[line-bot-sdk-php](https://github.com/line/line-bot-sdk-php)
[[PHP] Messaging APIを使ったLINEbotで色々試してみる](https://qiita.com/kuzira_vimmer/items/ad485a9365c2c23f0465)
[Packagist](https://packagist.org/packages/fabpot/goutte)