API Gateway + AWS Lambda(Python3)에서 RSS 피드(JIMDO)를 검색(스크래핑)하고 로컬 HTML 파일로 표시(크로스 도메인 문제도 대응)

하고 싶은 일



RSS 피드(JIMDO)를 취득해, 외부 사이트에 블로그의 타이틀, 텍스트, 썸네일 화상, 투고일을 표시시키고 싶다.
취득 건수는 최신의 피드 3건으로 한다.

환경



PC: macOS High Sierra 10.13.5
서버 환경: AWS API Gateway, AWS Lambda
언어 1(RSS): Python3.7(AWS Lambda)에서 사용
언어 2(View): HTML, CSS, jQuery(ajax)

JIMDO란?



160만 사용자가 이용하는 최대급의 웹사이트 작성 서비스
htps : // jp. 지 m도. 코m/
JIMDO의 블로그 정보를 외부 사이트에 올리면 RSS가 됩니다. (API는 제공하지 않는다 ※2019/2/22 현재)

보충



・JIMDO의 RSS 정보를 이번 사용하고 있습니다만, 다른 RSS 정보에도 전용할 수 있다고 생각합니다.
・스테이징을 준비할 수 없는 상태로 썼으므로, ​​어디까지나 가치 로컬에서의 실장이 되고 있습니다.
STG환경용은 향후 실리면 올리고 싶습니다.

구성



로컬 환경 (외부 사이트)
↓↓ ↑
AWS API Gateway
↓↓ ↑
AWS Lambda(Python3.7)
↓↓ ↑
RSS 피드(JIMDO)

RSS 피드


※一部割愛したValueがあります
{
  'title': 'タイトル', #取得対象
  'link': 'https://指定したドメイン.jimdofree.com/記事のエイリアス', #取得対象
  'id': 'https://指定したドメイン.jimdofree.com/記事のエイリアス',
  'summary': '
    <?xml version="1.0"?>
    <div id="">
      <div class="" id="">
        <figure class="">
          <a href="" rel="">
            <img alt="" class="" id="" src="挿入画像のURL" /> #取得対象
          </a>
        </figure>
        <div class=""></div>
      </div>
      <div class="" id="">
        <p>1行目</p> #取得対象
        <p>2行目</p> #取得対象
        <p>3行目</p> #取得対象
        <p>4行目</p> #取得対象
        <p>5行目</p> #取得対象
      </div>
    </div>',
  ',
  'published': 'Thu, 14 Feb 2019 15:10:07 +0900', #取得対象
}

코드



AWS Lambda(Python3) 코드



index.py
from bs4 import BeautifulSoup
import datetime
import feedparser
import html5lib
import json
import urllib.request, urllib.error

# ブログURL
RSS_URL = "ブログURL"
# ブログエントリー数のMAX値(3記事)
ENTRY_NUM_MAX = 3
# 本文の取得行数のMAX値(2行)
SENTENCE_NUM_MAX = 2
# 本文の切り取りの閾値
SENTENCE_THRESHOLD = 30

def lambda_handler(event, context):

  try:

    origin = "*" # クロスドメイン対策でワイルドカード

    # 返却用データ
    responseBody = []

    # RSS情報を取得する
    # 最新日付の記事から順にMAX18件取得できます(件数の指定はできない ※2019/2/22現在)
    rss = feedparser.parse(RSS_URL)

    entry_num = 0
    # RSS情報からブログの要素を取得する
    for entry in rss.entries:
      entry_num+=1

      # タイトル
      title = entry.title
      # 記事へのリンク
      link  = entry.link
      # 投稿時間
      date = formatPublishedDate(entry.published)

      # HTML要素をパースする
      summary = entry.summary # 本文、サムネイル画像を含む要素
      soup = BeautifulSoup(summary, "html5lib")

      # サムネイル画像のURL
      img = ""
      if soup.find("img") is not None:
        img = soup.img['src']

      all_sentence = soup.select("p") # 本文(全て)を取得する
      sentence_num = 0
      text = ""
      for sentence in all_sentence:
        # 本文を2行分(改行区切り)取り出し連結する
        sentence_num+=1
        text+=sentence.contents[0].strip()
        if (sentence_num == SENTENCE_NUM_MAX):
          break

      # 本文が指定文字数以上の場合は以降を省略する
      if (len(text) > SENTENCE_THRESHOLD):
        text = text[0:SENTENCE_THRESHOLD] + "..."

      # レスポンス用に整形する
      items = {
        "title" : title,
        "link"  : link,
        "date"  : date,
        "img"   : img,
        "text"  : text,
      }
      responseBody.append(items)

      if (entry_num == ENTRY_NUM_MAX):
        # 3件のブログ記事を取得できたので処理を抜ける
        break

    response = {
      'statusCode': 200,
      'headers': {
        'Access-Control-Allow-Origin': origin
      },
      'body': json.dumps(responseBody)
    }

    return response

  except Exception:

    response = {
      'statusCode': 200,
      'headers': {
        'Access-Control-Allow-Origin' : origin
      },
      'body': []
    }

    return response

def formatPublishedDate(published):
  # 投稿日(Thu, 14 Feb 2019 15:10:07 +0900)をdatetime型で返却する
  word = published.split(" ")
  date = word[3] + " " + word[2] + " " + word[1]
  f_date = datetime.datetime.strptime(date, "%Y %b %d")
  return str(f_date.year) + "-" + str(f_date.month) + "-" + str(f_date.day)


외부 사이트(가치 로컬)의 코드(※크로스 도메인 대책의 코멘트 있음)



jimdo.js
/*
  JIMDOのRSSフィードを受信(直近3件)し、HTMLを動的に生成する
  取得情報:
    title: タイトル
    link : 記事へのリンク
    date : 投稿日
    img  : 記事のサムネイル画像のURL
    text : 記事の本文
*/
$(function(){
  $.ajax({
    url: 'API GatewayのURL',
    type: 'GET',
    dataType: 'json',
    xhrFields: {
      // クロスドメイン対策でローカル確認用にfalseにしている
      // trueの場合、python側で設定している'Access-Control-Allow-Origin'に
      // '*'(ワイルドカード)が使えず、ブラウザでクロスドメインのエラーが発生する
      withCredentials: false
    },
  })
  .done(function(data) {
    // ブログ情報は最新3件取得しているのでループさせる
    $.each(data, function(k, v) {
      // HTMLを動的に生成する(割愛)
      // データアクセス
      //   v.title: タイトル
      //   v.link : 記事へのリンク
      //   v.date : 投稿日
      //   v.img  : 記事のサムネイル画像のURL
      //   v.text : 記事の本文
    });
  });
});

AWS Lambda 문제



일부 라이브러리가 Lambda에 탑재되어 있지 않으므로 로직 파일(index.py)에서 참조하는 라이브러리를 업로드해야 합니다.
따라서 로직 파일 (index.py)과 동일한 디렉토리에 라이브러리를 설치합니다.
(같은 디렉토리가 아니어도 괜찮을지도 모르지만 시도하지 않습니다...)

라이브러리 설치~업로드까지



python3 설치



 ~참고~
 Mac에 Python3을 인스톨 해 환경 구축【결정판】
htps : // m / 7110 / ms / 1 아 5968022373 99 28
→ Python3의 도입, virtualenv에 의한 환경 구축까지 실행해 주세요

라이브러리를 설치합니다 (작업 디렉토리에서)



1. feedparser를 설치한다(RSS 피드를 취득한다)
  (env)[作業ディレクトリ] $ pip install feedparser -t .

2. BeautifulSoup 설치(웹 스크래핑용)
  (env)[作業ディレクトリ] $ pip install beautifulsoup4 -t .

3. html5lib를 설치한다(BeautifulSoup로 지정하는 Parser)
  (env)[作業ディレクトリ] $ pip install html5lib -t .

이런 디렉토리 계층이 되었습니다.



로직 파일 (index.py)과 설치된 라이브러리를 zip에 고정


  (env)[作業ディレクトリ] $ zip -r ファイル名.zip ./*

AWS Lambda에 업로드



1. AWS Lambda 콘솔 화면 열기
 2. 設定 탭 -> 関数コード -> 関数パッケージ -> アップロード3. zip 파일을 선택한다
4. 保存 버튼을 누른다

AWS Lambda 과제



업로드한 파일 크기가 10MB를 초과하면,
  인라인 코드 편집(Lambda 관리 화면에서 코드 편집)을 할 수 없게 됩니다.

응답 결과


// Valueは割愛
[
  {title: "", link: "", date: "", img: "", text: "",}, // 1つめのブログ記事(最新)
  {title: "", link: "", date: "", img: "", text: "",}, // 2つめのブログ記事
  {title: "", link: "", date: "", img: "", text: "",}  // 3つめのブログ記事
]

할 수 없었던 것



BeautifulSoup의 Parser에 'lxml' 사용


libxslt-devellibxml2-devel 설치도 필요합니다.
Homebrew에서 설치를 시도했지만 아래 오류가 발생했습니다.
(env) [作業ディレクトリ] $ brew install libxslt-devel                                                    14:38:21
Error: No available formula with the name "libxslt-devel"
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching for similarly named formulae...
Error: No similarly named formulae found.
==> Searching taps...
==> Searching taps on GitHub...
Error: No formulae found in taps.

----------------------------

(builder) [builder] brew install libxml2-devel                                                    14:39:43
Error: No available formula with the name "libxml2-devel"
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching for similarly named formulae...
Error: No similarly named formulae found.
==> Searching taps...
==> Searching taps on GitHub...
Error: No formulae found in taps.

분명히 yum이라면 패키지가있을 것 같습니다.
해결에 이른 경위의 질문을 이하에 실어 둡니다. (자신의 질문입니다.)

AWS Lambda에서 'lxml'이라는 라이브러리를 사용할 수없는 오류를 해결하고 싶습니다.
htps : // 놀라운 l. 코m/쿠에 s치온 s/173374

라이브러리를 brew install로 설치할 때 No available formula with the name 〜가 나오는 오류를 해결하고 싶습니다.
htps : // 놀라운 l. 코m/쿠에 s치온 s/174026

좋은 웹페이지 즐겨찾기