Create a linenews-like app with linebot and Rails
When you type in news, a list of news articles will be sent. (A function like delivery at what time in the morning will be implemented next time.)
It's been less than four months since I started working as an engineer intern, but I wanted to be more sensitive to tech news. And I thought that if I could receive it like linenews, I would get into the habit of reading it, so I decided to make it. The image is like a morning newspaper
Rails 6.0.3.1
ruby 2.6.1
Use WSL on surface pro 6 Deploy the app itself to heroku
This time it is not a lecture article on how to make it, so I will omit it. This time, I registered by referring to the following article.
[Rails] Let's easily develop LINE bots in about an hour-Questionnaire total bot basics-[With images]
This time, we will scrape the new news from TechCrunch and display the top 10 news items.
A gem called mechanize is used for scraping. For the basic usage of this gem, I referred to "How to use Rails scraping method Mechanize".
Analyze the tags with Chrome's developer tools to determine which parts to scrape.
As a result, we implemented the method to get the title, image and URL of the news article as follows.
def get_tech_crunch_news
title_ary = []
src_ary = []
href_ary = []
agent = Mechanize.new
page = agent.get("https://jp.techcrunch.com/")
news_contents = page.search('div.block-content')
news_contents.search('h2.post-title').each do |title|
title_ary << title.inner_text
href_ary << title.at('a')['href']
end
news_contents.each do |news_content|
src_ary << news_content.at('img')['data-src']
end
return title_ary, src_ary, href_ary
end
This time, as a countermeasure against LazyLoad of the img tag, get the data-src attribute instead of the src attribute. This completes the scraping part.
This time, we will use something called flexmessage to deliver lineNews-like messages.
↑ It's such a guy
See the official API for details.
This flex message can be easily created using the tools on the WEB provided by line.
You may feel a little stress in the operation, but I think that you can operate it with knowledge that you have some experience with CSS.
When you're done, click the view as json button in the upper right and copy the Json. The JSON this time is as follows.
{
"type": "bubble",
"size": "giga",
"header": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "TechCrunch news",
"size": "xl",
"weight": "bold"
}
]
},
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "box",
"layout": "horizontal",
"margin": "lg",
"spacing": "sm",
"contents": [
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "image",
"url": "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_1_cafe.png ",← Here src
"margin": "none",
"size": "full",
"aspectMode": "cover",
"gravity": "top"
}
],
"position": "relative",
"cornerRadius": "12px"
},
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "WHILL introduces an automatic driving system to the boarding gate using an electric wheelchair at Haneda Airport",← Title here
"size": "md",
"weight": "bold",
"align": "center",
"wrap": true,
"maxLines": 4,
"color": "#ffffff"
}
],
"position": "absolute",
"width": "100%",
"backgroundColor": "#00bfff80",
"offsetBottom": "10px"
}
],
"action": {
"type": "uri",
"label": "action",
"uri": "http://linecorp.com/"← here href
},
"width": "50%",
"position": "relative"
},
~~~~~~~~~~~~~~~~~~~~~~(Abbreviation)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"uri": "http://qiita.com/"
},
"width": "50%",
"position": "relative"
}
]
}
]
}
}
Then, just put the data acquired by scraping this time in the corresponding place and the news distribution function is completed for the time being.
So far, if you type "news" into linebot, you'll be able to pull 10 new articles from TechCrunch from the top. Next time, I would like to be able to deliver new news every morning at 8:00.
Finally, I will put the source of the controller.
linebot_controller.rb
class LinebotController < ApplicationController
require 'line/bot'
protect_from_forgery :except => [:callback]
def client
@client ||= Line::Bot::Client.new { |config|
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
end
def callback
body = request.body.read
signature = request.env['HTTP_X_LINE_SIGNATURE']
unless client.validate_signature(body, signature)
head :bad_request
end
events = client.parse_events_from(body)
events.each { |event|
case event
when Line::Bot::Event::Message
case event.type
when Line::Bot::Event::MessageType::Text
if event.message['text'].eql?('news')
client.reply_message(event['replyToken'], template)
end
end
end
}
head :ok
end
private
def get_tech_crunch_news
title_ary = []
src_ary = []
href_ary = []
agent = Mechanize.new
page = agent.get("https://jp.techcrunch.com/")
news_contents = page.search('div.block-content')
news_contents.search('h2.post-title').each do |title|
title_ary << title.inner_text
href_ary << title.at('a')['href']
end
news_contents.each do |news_content|
src_ary << news_content.at('img')['data-src']
end
return title_ary, src_ary, href_ary
end
def template
title, src, href = get_tech_crunch_news
{
"type": "flex",
"altText": "this is a flex message",
"contents":{
"type": "bubble",
"size": "giga",
"header": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "TechCrunch news",
"size": "xl",
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Abbreviation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
end
The URL that I referred to during this production is attached below.
[Rails] Let's easily develop LINE bots in about an hour-Questionnaire total bot basics-[With images]
How to use Rails scraping method Mechanize
Recommended Posts