class InstagramData

Constants

TAG_URL_PREFIX

Attributes

csv_filename[R]
get_number[R]
instagram_data[R]
tag_name[R]

Public Class Methods

new(tag_name: '岸和田', get_number: 10) click to toggle source
# File lib/instagram-tag-search.rb, line 15
def initialize(tag_name: '岸和田', get_number: 10)
    @tag_name = tag_name
    @get_number = get_number
    @got_number = 0
end

Public Instance Methods

convertCSVtoSJIS() click to toggle source

sjisへの変換

# File lib/instagram-tag-search.rb, line 163
def convertCSVtoSJIS
    csv_data = File.read(@csv_filename).encode(Encoding::Windows_31J, undef: :replace)
    sjis_csv_filename = @csv_filename.gsub(/\.csv$/, "_sjis.csv")
    File.open(sjis_csv_filename, "w:UTF-8:SJIS") do |file|
        file.write(csv_data)
    end
end
csvDataWrite(dataArray) click to toggle source

CSVファイルへの書き込み

# File lib/instagram-tag-search.rb, line 143
def csvDataWrite(dataArray)
    dataArray.each do |n|
        CSV.open(@csv_filename, "ab+") do |csv|
            # データはハッシュなので配列にし、キーを除き、値を代入する
            writeData = n.to_a.map{|e| e[1]}
            csv << writeData
        end
    end
end
csvHeaderWrite() click to toggle source

CSVファイルのヘッダを記入

# File lib/instagram-tag-search.rb, line 127
def csvHeaderWrite
    CSV.open(@csv_filename, "ab+") do |csv|
        writeData = Array.new
        writeData.push("ユーザID")
        writeData.push("投稿日時(日本時間)")
        writeData.push("ページURL")
        writeData.push("いいねの数")
        writeData.push("コメント数")
        writeData.push("投稿者コメント")
        writeData.push("ハッシュタグ")
    
        csv << writeData
    end
end
getInstagramData() click to toggle source
# File lib/instagram-tag-search.rb, line 66
def getInstagramData
    tag_search_url = TAG_URL_PREFIX + URI.encode_www_form_component(@tag_name)
    @instagram_data = []

    # 文字コード
    charset = nil

    puts "#{@tag_name} のデータを #{@get_number} 件分取得します"

    # タグ検索ページへアクセス
    # 文字コードを取得しながら、アクセス
    html = open(tag_search_url) do |f|
        charset = f.charset
        f.read
    end

    # 以下、Nokogiriによるアクセスに必要な情報の取得処理
    # 全部のHTMLを取得
    allDoc = Nokogiri::HTML.parse(html, nil, charset)
    # メタ情報だけ取得
    metaInfo = allDoc.css('body script').first.text
    # 前後に不要な情報があるのでカット
    metaInfo.slice!(0, 21)
    metaInfo = metaInfo.chop

    # 解析用JSONの保存
    response_json = JSON.parse(metaInfo)

    # データの中身を取得
    dataArray = response_json['entry_data']['TagPage'][0]['graphql']['hashtag']['edge_hashtag_to_media']['edges'];

    # 初期ページの分を取得
    parseInstagramData(dataArray)

    # 取得した件数を記録
    puts "#{@got_number} 件取得しました"

    # 取得枚数に足りていない場合
    while @got_number < @get_number do
        # 次のページの取得に必要な情報を取得
        # csrfトークンの取得
        csrfToken = response_json['config']['csrf_token']
        # rhx_gisの取得
        rhx_gis = response_json['rhx_gis']
        # 次のページ取得用のカーソル
        @endCursor = response_json['entry_data']['TagPage'][0]['graphql']['hashtag']['edge_hashtag_to_media']['page_info']['end_cursor']

        puts "5秒待ってから再開します"
        sleep 5

        dataArray, @endCursor = getNextPageData(@endCursor, csrfToken, rhx_gis, @got_number)

        parseInstagramData(dataArray)

        # 取得した件数を記録
        puts "#{@got_number} 件取得しました"
    end

end
getNextPageData(endCursor, csrfToken, rhx_gis, gotNumber) click to toggle source
# File lib/instagram-tag-search.rb, line 21
def getNextPageData(endCursor, csrfToken, rhx_gis, gotNumber)
    uri = URI.parse(TAG_URL_PREFIX + URI.encode_www_form_component(@tag_name) + "/?__a=1&max_id=" + endCursor)
    http = Net::HTTP.new(uri.host, uri.port)
    
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  
    req = Net::HTTP::Get.new(uri.request_uri)
  
    res = http.request(req)
    endCursor = JSON.parse(res.body)['graphql']['hashtag']['edge_hashtag_to_media']['page_info']['end_cursor']
    dataArray =  JSON.parse(res.body)['graphql']['hashtag']['edge_hashtag_to_media']['edges']
    
    return dataArray, endCursor
end
parseInstagramData(dataArray) click to toggle source
# File lib/instagram-tag-search.rb, line 37
def parseInstagramData(dataArray)
    dataArray.length.times do |i|
        insta_data = {userId: '', timestamp: '', pageUrl: '', likeCount: '', commentCount: '', caption: ''}
        # ユーザIDの取得
        insta_data[:userId] = dataArray[i]['node']['owner']['id']
        # UNIXタイムからの変換
        insta_data[:timestamp] = Time.at(dataArray[i]['node']['taken_at_timestamp'])
        # 画像URLの取得
        # writeData.push(dataArray[i]["thumbnail"])
        # ページURLの取得
        insta_data[:pageUrl] = "https://www.instagram.com/p/" + dataArray[i]['node']['shortcode'] + "/"
        # いいねの数とコメントの数
        insta_data[:likeCount] = dataArray[i]['node']['edge_liked_by']['count']
        insta_data[:commentCount] = dataArray[i]['node']['edge_media_to_comment']['count']
        
        # 投稿者コメントの取得
        insta_data[:caption] = (dataArray[i]['node']['edge_media_to_caption']['edges'][0]['node']['text'])

        # 投稿者コメントからタグのみ抽出
        tags = (dataArray[i]['node']['edge_media_to_caption']['edges'][0]['node']['text'] + " ").scan(/[#][A-Za-zA-Za-z一-鿆0-90-9ぁ-ヶヲ-゚ー○]+/).join(" ")
        insta_data[:tags] = tags
        
        @instagram_data.push(insta_data)
        @got_number += 1
        # 予定取得枚数に到達したら終了
        break if @got_number >= @get_number
    end
end
writeToCSV(dataArray, csvfilename: "getInstagramData_ click to toggle source

CSVファイルへの書き込み

# File lib/instagram-tag-search.rb, line 154
def writeToCSV(dataArray, csvfilename: "getInstagramData_#{Time.now.strftime("%Y%m%d%H%M%S")}.csv")
    @csv_filename = csvfilename
    # csvファイルにヘッダを記入
    csvHeaderWrite
    # csvファイルに保存
    csvDataWrite(dataArray)
end