// 注意事項:無料版の投稿上限は1500回/月まで
// API V2 対応 動画、画像、テキスト、ツリー投稿(アフィリエイトリンク付き)
// 定数
// google spread sheetのurl - 別noteにてgoogle spread sheetへのFANZAスクレイピング記事があります。
const GoogleSpreadSheet_URL = "";
// 例:1000行分取得する、5だと5行取得になります
const GoogleSPreadSheetNumRows = 1000;
try {
const ss = SpreadsheetApp.openByUrl(GoogleSpreadSheet_URL);
} catch (e) {
Logger.log("エラー発生: " + e.message);
Logger.log("指定したURLが間違っています。もう一度GoogleSpreadSheet_URLを指定しなおしてください。")
}
const sheet1 = ss.getSheets()[0];
const sheet2 = ss.getSheets()[1];
const sheet3 = ss.getSheets()[2];
if (!sheet1) throw new Error("シート1が見つかりません。");
if (!sheet2) throw new Error("シート2が見つかりません。シートを追加してください。");
if (!sheet3) throw new Error("シート3が見つかりません。シートをもう1つ追加してください。");
// シート2からURLを取得。同じ記事があれば、スキップさせます。
const fanza_url_values = get_posted_url(sheet2);
const fanza_url_duplicates_values = get_posted_url(sheet3);
// FANZA
const APIID = ""; // FANZA の API ID
const affiliateID = ""; // FANZA の アフィリエイト ID
// falseにすれば、出力を他のnote販売しているWordPress記事用出力にも変更可能
// const FANZA_TO_TWITTER_FLAG = false;
const FANZA_TO_TWITTER_FLAG = true;
/// 一度の取得件数 - 例 〇件Spread sheetに記載されます。- 100が最大です。35件で一度にGASを動かせる時間を超えてしまうので、それ以下に抑えてください。
const get_hits = "30";
const sort_rank = "date";
// 初期値:rank
// 人気:rank
// 価格が高い順:price
// 価格が安い順:-price
// 新着:date
// 評価:review
// マッチング順:match
// sort_rank = date, get_hits = 100 にすれば、毎日新着のFANZA動画を100件分(あれば)取得します
// 接続しているSheetのC列(mp4)が重複している場合、1000行目までチェックして削除する。
// 1000の部分を100にすれば、100行目まで確認、CをBにすれば、B列で確認から削除を行う。
const delete_DUPLICATE_FANZA_RANGE = "C1:C100";
// 2:10秒のサンプル動画のファイルサイズ。これ以上のサイズのファイルはツイートをしない。
// const MP4_MAX_FILE_SIZE = 49236568;
const MP4_MAX_FILE_SIZE = 30000000;
// ------------------------------------------------
// Twitter(X)のAPI
// ------------------------------------------------
// V2用のAPI(テキストのみを投稿する場合はv2のみでも可)
const CLIENT_ID = ''
const CLIENT_SECRET = ''
// V1用のAPI(動画、画像を投稿する場合はこちらも取得する必要あり)
const API_KEY = '';
const API_KEY_SECRET = '';
const ACCESS_TOKEN = '';
const ACCESS_TOKEN_SECRET = '';
const BearerTOKEN = '';
// ------------------------------------------------
// Google Sheetの設定
// ------------------------------------------------
function google_sheet_get_one_range(gssurl, column, numRows){
// row Integer 範囲の開始行インデックス。行のインデックスは 1 から始まります。
// column Integer 範囲の列インデックス。列のインデックスは 1 から始まります。
// numRows Integer 返される行数です。
var range = sheet1.getRange(row=1, column=column, numRows=numRows);
// 列の配列
var values = range.getValues();
// 取得した情報の出力
console.log(values);
return values;
}
// ------------------------------------------------
// Twitter(X)の認証
// ------------------------------------------------
function getService() {
pkceChallengeVerifier();
const userProps = PropertiesService.getUserProperties();
const scriptProps = PropertiesService.getScriptProperties();
return OAuth2.createService('twitter')
.setAuthorizationBaseUrl('https://twitter.com/i/oauth2/authorize')
.setTokenUrl('https://api.twitter.com/2/oauth2/token?code_verifier=' + userProps.getProperty("code_verifier"))
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('authCallback')
.setPropertyStore(userProps)
.setScope('users.read tweet.read tweet.write offline.access')
.setParam('response_type', 'code')
.setParam('code_challenge_method', 'S256')
.setParam('code_challenge', userProps.getProperty("code_challenge"))
.setTokenHeaders({
'Authorization': 'Basic ' + Utilities.base64Encode(CLIENT_ID + ':' + CLIENT_SECRET),
'Content-Type': 'application/x-www-form-urlencoded'
})
}
function getService1(){
return OAuth1.createService( "Twitter" )
.setAccessTokenUrl( "https://api.twitter.com/oauth/access_token" )
.setRequestTokenUrl( "https://api.twitter.com/oauth/request_token" )
.setAuthorizationUrl( "https://api.twitter.com/oauth/authorize" )
.setConsumerKey( API_KEY )
.setConsumerSecret( API_KEY_SECRET )
.setAccessToken( ACCESS_TOKEN, ACCESS_TOKEN_SECRET )
.setCallbackFunction('authCallback'); // コールバック関数名
}
function authCallback(request) {
const service = getService();
const authorized = service.handleCallback(request);
if (authorized) {
return HtmlService.createHtmlOutput('Success!');
} else {
return HtmlService.createHtmlOutput('Denied.');
}
}
function pkceChallengeVerifier() {
var userProps = PropertiesService.getUserProperties();
if (!userProps.getProperty("code_verifier")) {
var verifier = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
for (var i = 0; i < 128; i++) {
verifier += possible.charAt(Math.floor(Math.random() * possible.length));
}
var sha256Hash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, verifier)
var challenge = Utilities.base64Encode(sha256Hash)
.replace(/+/g, '-')
.replace(///g, '_')
.replace(/=+$/, '')
userProps.setProperty("code_verifier", verifier)
userProps.setProperty("code_challenge", challenge)
}
}
function logRedirectUri() {
var service = getService();
Logger.log(service.getRedirectUri());
}
function main() {
const service = getService();
if (service.hasAccess()) {
Logger.log("Already authorized");
} else {
const authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
}
}
// ------------------------------------------------
// ###################### ツイート関数 ######################
// テキストのみ送信する関数
function send_text_Tweet(content) {
// 引数-ツイート内容
var payload = {
text: content
}
var service = getService();
var url = `https://api.twitter.com/2/tweets`;
var response = UrlFetchApp.fetch(url, {
method: 'POST',
'contentType': 'application/json',
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
},
muteHttpExceptions: true,
payload: JSON.stringify(payload)
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
return result.data["id"]
}
// 画像送信する関数
function send_image_Tweet(image_url, content) {
// 引数 - 画像URL, ツイート内容
// 画像のBlobデータを取得
let imageBlob = UrlFetchApp.fetch(image_url).getBlob();
// OAuth1.0 Service
let oauth1Service = getService1();
// 画像アップロードのURL
let uploadUrl = 'https://upload.twitter.com/1.1/media/upload.json';
// 画像アップロードのPayload
let payload = {
media_data: Utilities.base64Encode(imageBlob.getBytes())
};
// 画像アップロードのオプション
let options = {
method: 'POST',
payload: payload,
muteHttpExceptions: true
};
// 画像アップロードリクエスト
let response = oauth1Service.fetch(uploadUrl, options);
let mediaId = JSON.parse(response.getContentText()).media_id_string;
console.log('mediaId', mediaId)
// OAuth2.0認証情報 - getService() = v2
let oauth2Service = getService();
// 投稿のURL
let endpoint2 = 'https://api.twitter.com/2/tweets';
// 投稿のPayload
if (oauth2Service.hasAccess()){
let tweetPayload = JSON.stringify({
'text': content,
'media': {
'media_ids': [mediaId]
}
});
// 投稿のオプション
let tweetOptions = {
method: 'POST',
headers: {
Authorization: 'Bearer ' + oauth2Service.getAccessToken(),
'Content-Type': 'application/json'
},
payload: tweetPayload,
muteHttpExceptions: true
};
// 投稿投稿リクエスト
let tweetResponse = UrlFetchApp.fetch(endpoint2, tweetOptions);
// レスポンスをログに出力
console.log(JSON.parse(tweetResponse.getContentText()).data.id);
return JSON.parse(tweetResponse.getContentText()).data.id
}else{
return null
}
}
// 動画送信をする関数
function send_video_Tweet(video_url, content){
// 再生時間は0.5秒~140秒の間としてください - 2分を超えるとエラーになる可能性があります。
// フレームレートは60FPS以下としてください
// サイズは32x32~1280x1024の間としてください
// 動画のURL
let twitterService = getService1();
// 例 https://cc3001.dmm.co.jp/litevideo/freepv/4/422/422base00035/422base00035_sm_s.mp4
let sample_movie_url = video_url;
if (twitterService.hasAccess()) {
try{
// v2とv1のエンドポイント
const endpoint_media = 'https://upload.twitter.com/1.1/media/upload.json';
const endpoint2 = 'https://api.twitter.com/2/tweets';
// OAuth2.0認証情報 - getService() = v2
const oauth2Service = getService();
//動画の取得
const movie_blob = UrlFetchApp.fetch(sample_movie_url).getBlob();
const movie_file_size = movie_blob.getBytes().length;
console.log(movie_file_size);
const movie_64 = Utilities.base64Encode(movie_blob.getBytes());
const movie_64_file_size = movie_64.length;
console.log(movie_64_file_size);
// 動画投稿処理
//INIT
const movie_init_option = {
'method' : "POST",
'payload': {
'command':'INIT',
'media_type':'video/mp4',
'media_category':"tweet_video", //30秒超え対策
'total_bytes':movie_file_size
}
};
const movie_init = JSON.parse(twitterService.fetch(endpoint_media, movie_init_option));
console.log(movie_init);
//APPEND
const segment_index = 0;
const bytes_sent = 0;
const chunk_size = 1000000;
const chunk_num = Math.ceil(movie_64_file_size / chunk_size);
for (let index = 0; index < chunk_num; index++) {
const chunk = movie_64.slice(chunk_size * index, chunk_size * (index + 1));
console.log(chunk.length);
const movie_append_option = {
'method' : "POST",
"muteHttpExceptions" : true,
'payload': {
'command':'APPEND',
'media_data':chunk,
'media_id':movie_init['media_id_string'],
'segment_index':index
}
};
twitterService.fetch(endpoint_media, movie_append_option);
}
//FINALIZE
const movie_finalize_option = {
'method' : "POST",
"muteHttpExceptions" : true,
'payload': {
'command':'FINALIZE',
'media_id':movie_init['media_id_string']
}
};
const movie_finalize = JSON.parse(twitterService.fetch(endpoint_media, movie_finalize_option));
console.log(movie_finalize);
// STATUS
while (true) {
var movie_status_option = { 'method':"GET" };
var movie_status = JSON.parse(twitterService.fetch(endpoint_media+"?command=STATUS&media_id="+movie_init['media_id_string'], movie_status_option));
console.log(movie_status);
if (movie_status["processing_info"]["state"] == "succeeded") {
break;
} else if (movie_status["processing_info"]["state"] == "failed") {
sheet1.getRange(i, 14).setValue(movie_status["processing_info"]["error"]["message"]);
throw new Error(movie_status["processing_info"]["error"]["message"]);
} else {
Utilities.sleep(movie_status["processing_info"]["check_after_secs"] + 1);
}
};
// 動画投稿用パラメーター設定
var payload = {
'text': content,
'media': {
'media_ids': [movie_init['media_id_string']]
}
};
var response = UrlFetchApp.fetch(endpoint2, {
method: 'POST',
'contentType': 'application/json',
headers: {
Authorization: 'Bearer ' + getService().getAccessToken()
},
muteHttpExceptions: true,
payload: JSON.stringify(payload)
});
// 動画投稿結果の出力
console.log(JSON.parse(response.getContentText()).data.id);
return JSON.parse(response.getContentText()).data.id
} catch (e){
console.log(e);
}
} else {
return null;
}
}
// ツリー投稿する関数
function tree_send_text_Tweet(tw_id, content) {
// 引数-ツイートID(ツリー元)、ツイート内容(アフィリエイトリンクなど)
var payload = {
text: content,
reply: {
"in_reply_to_tweet_id": tw_id}
}
var service = getService();
if (service.hasAccess()) {
var url = `https://api.twitter.com/2/tweets`;
var response = UrlFetchApp.fetch(url, {
method: 'POST',
'contentType': 'application/json',
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
},
muteHttpExceptions: true,
payload: JSON.stringify(payload)
});
var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));
} else {
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s',authorizationUrl);
}
return result.tw_id
}
// ##################### ツイート投稿用関数 ########################
function normal_post_tweet_main(){
// テキストのみ送信する際に使用してください
let content = "いまからテスト投稿開始。同じだとNG";
return send_text_Tweet(content);
}
function image_post_tweet_main(){
// 画像とテキストのみ送信する際に使用してください
let content = "テスト画像投稿";
let image_url = "https://pics.dmm.co.jp/digital/video/1nhdtb00868/1nhdtb00868jp-2.jpg";
let tw_id = send_image_Tweet(image_url, content);
console.log(tw_id);
return tw_id;
}
function video_post_tweet_main(){
// 動画とテキストのみ送信する際に使用してください
// DVDのサンプル動画はエラーになる可能性があります。有料動画のサンプルmp4を入れてみてください。
let content = "テスト動画です。1";
let video_url = "https://s3t3d2y8.afcdn.net/library/657631/6d142a53ffbd7afe4a5dce58b4be4fad4eca283d.mp4";
return send_video_Tweet(video_url, content);
}
function tree_text_tweet_main(){
// アフィリエイトリンクなどのツリー用リンク及びテキスト
let content = "ツリー投稿テスト。";
// テキスト投稿ツリー
tw_id = normal_post_tweet_main();
tree_send_text_Tweet(tw_id, content);
}
function tree_image_tweet_main(){
// アフィリエイトリンクなどのツリー用リンク及びテキスト
let content = "https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=h_1711dcxd00004/?dmmref=videoa_top_pickup_pc&i3_ref=recommend&i3_ord=2";
// 画像投稿ツリー
tw_id = image_post_tweet_main();
tree_send_text_Tweet(tw_id, content);
}
function tree_video_tweet_main(){
// アフィリエイトリンクなどのツリー用リンク及びテキスト
let content = "動画ツリーの投稿テスト。";
// 動画投稿ツリー
tw_id = video_post_tweet_main();
if(tw_id != null){
tree_send_text_Tweet(tw_id, content);
}
}
function google_sheet_texts_tweet(spreadsheeturl){
// 重複行はあらかじめ削除
// delete_fanza_duplicates();
// A列投稿タイトル、B列投稿画像、C列投稿動画、D列ツリー用ツイート
contents = google_sheet_get_one_range(spreadsheeturl, column=1,
numRows=GoogleSPreadSheetNumRows);
replies = google_sheet_get_one_range(spreadsheeturl, column=4,
numRows=GoogleSPreadSheetNumRows);
tweet:for (var row in contents) {
for (var col in contents[row]) {
Logger.log(contents[row][col]);
try{
tw_id = send_text_Tweet(contents[row][col]);
if (tw_id != null){
send_text_Tweet(tw_id,replies[row][col]);
for (let i = 0; i < Number(row) + 1; i++){
sheet1.deleteRows(Number(row) + 1);
}
break tweet;
}
} catch (e) {
if (e instanceof TypeError) {
console.log("ツイート内容が空欄。もしくは、同様のためツイートをスキップします。")
}
}
}
}
}
function google_sheet_images_tweet(spreadsheeturl){
// 重複行はあらかじめ削除
// delete_fanza_duplicates();
// A列投稿タイトル、B列投稿画像、C列投稿動画、D列ツリー用ツイート
contents = google_sheet_get_one_range(spreadsheeturl, column=1, numRows=GoogleSPreadSheetNumRows);
images = google_sheet_get_one_range(spreadsheeturl, column=2,
numRows=GoogleSPreadSheetNumRows);
replies = google_sheet_get_one_range(spreadsheeturl, column=4, numRows=GoogleSPreadSheetNumRows);
tweet:for (var row in contents) {
for (var col in contents[row]) {
Logger.log(contents[row][col]);
try{
tw_id = send_image_Tweet(images[row][col], contents[row][col]);
if (tw_id != null){
tree_send_text_Tweet(tw_id,replies[row][col]);
if (!fanza_url_duplicates_values.includes(images[row][col])){
tree_send_text_Tweet(tw_id,replies[row][col]);
sheet2.appendRow([images[row][col]]);
for (let i = 0; i < Number(row) + 1; i++){
sheet1.deleteRows(Number(row) + 1);
}
}
break tweet;
}
} catch (e) {
if (e instanceof TypeError) {
console.log("ツイート内容が空欄。もしくは、同様のためツイートをスキップします。")
}
}
}
}
}
function google_sheet_videos_tweet(spreadsheeturl){
// 重複行はあらかじめ削除
// delete_fanza_duplicates();
// A列投稿タイトル、B列投稿画像、C列投稿動画、D列ツリー用ツイート
contents = google_sheet_get_one_range(spreadsheeturl, column=1, numRows=GoogleSPreadSheetNumRows);
videos = google_sheet_get_one_range(spreadsheeturl, column=3,
numRows=GoogleSPreadSheetNumRows);
replies = google_sheet_get_one_range(spreadsheeturl, column=4, numRows=GoogleSPreadSheetNumRows);
tweet:for (var row in contents) {
for (var col in contents[row]) {
Logger.log(contents[row][col]);
try{
if (Number(get_fanza_mp4_length(videos[row][col])< MP4_MAX_FILE_SIZE)){
tw_id = send_video_Tweet(videos[row][col], contents[row][col]);
if (tw_id != null){
if (!fanza_url_duplicates_values.includes(videos[row][col])){
tree_send_text_Tweet(tw_id,replies[row][col]);
sheet2.appendRow([videos[row][col]]);
// 投稿した行は削除
for (let i = 0; i < Number(row) + 1; i++){
sheet1.deleteRows(Number(row) + 1);
}
}
break tweet;
}
}
} catch (e) {
if (e instanceof TypeError) {
console.log("ツイート内容が空欄。もしくは、同様のためツイートをスキップします。")
}
}
}
}
}
function tree_of_tree_tweet_main(){
// ツリー回数によってカスタム
// tree_of_tree_content - ツリー投稿に対してさらにツリツリー投稿する
// アフィリエイトリンクなどのツリー用リンク及びテキスト
let content = "";
let tree_of_tree_content = "";
// 動画投稿ツリー
tw_id = video_post_tweet_main();
if(tw_id != null){
tw_tree_id = tree_send_text_Tweet(tw_id, content);
tw_tree_id = tree_send_text_Tweet(tw_tree_id, tree_of_tree_content);
}
}
// ------------------------------------------------
// FANZAの関数
// ------------------------------------------------
function fanza_api(keyword) {
var keyword = keyword; // 女優名 ー 上原亜衣 など 特定の女優に絞る場合は女優名を入力
var response = UrlFetchApp.fetch('https://api.dmm.com/affiliate/v3/ItemList?api_id='+ APIID
+ '&affiliate_id='+ affiliateID + '&site=FANZA&service=digital&floor=videoa' + '&hits=' + get_hits +
'&sort=' + sort_rank + '&keyword=' + keyword + '&output=json')
var jsonObject = JSON.parse(response); // JSON 形式のAPIレスポンス
var jsonItemsFANZAresponse = jsonObject['result']['items']; // 参照:https://affiliate.dmm.com/api/v3/itemlist.html
for( key in jsonItemsFANZAresponse ) {
// 配列 ー 画像収納用
let image_Lsizes = [];
// 配列 ー カテゴリー、監督、ジャンル、女優
let genres = [];
let genres_id = [];
let categories = [];
let categories_id = [];
let makers = [];
let makers_id = [];
let directors = [];
let directors_id = [];
let labels = [];
let labels_id = [];
let actresses = [];
let actresses_id = [];
let content_id = jsonItemsFANZAresponse[key]['content_id'];
let product_id = jsonItemsFANZAresponse[key]['product_id'];
let title = jsonItemsFANZAresponse[key]['title']; // タイトル
let url = jsonItemsFANZAresponse[key]['URL']; // URL
let affiliateURL = jsonItemsFANZAresponse[key]['affiliateURL']; // アフィリエイト用のURL
// FANZAから説明文を抽出
var description = get_fanza_description(url);
// FANZAから動画を抽出
var fanza_sample_mp4 = get_fanza_sample_video_mp4(content_id);
try{
var review_num = jsonItemsFANZAresponse[key]['review']['count']; // レビュー数
} catch(e){
Logger.log('レビュー数がありません');
var review_num = ""; // レビュー数
}
try{
var review_avarage = jsonItemsFANZAresponse[key]['review']['average'] // レビュー平均点
} catch(e){
Logger.log('レビュー平均点がありません');
var review_avarage = ""; // レビュー平均点
}
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['sampleImageURL']['sample_l']['image']); // サンプル画像の大サイズ
var sample_image_L = jsonItemsFANZAresponse[key]['sampleImageURL']['sample_l']['image']; // サンプル画像の大サイズ
console.log(sample_image_L);
var sample_image_LLength = sample_image_L.length;
for (let i = 0; i < sample_image_LLength; i++){
Logger.log( key + ': ' + sample_image_L[i]); // 画像URL
image_Lsizes.push(sample_image_L[i]);
}
}
catch(e){
Logger.log('サンプル画像がありません');
var sample_image_L = "";
}
var wp_sample_images = image_Lsizes.join(","); // WordPrses用に , で区切る
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['sampleMovieURL']['size_476_306']); // サンプル動画 size_476_306 サイズ
var sampleMovieURL_476_306 = jsonItemsFANZAresponse[key]['sampleMovieURL']['size_476_306']; // サンプル動画 size_476_306 サイズ
}
catch(e){
Logger.log('サンプル動画 size_476_306 サイズがありません');
var sampleMovieURL_476_306 = "";
}
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['sampleMovieURL']['size_560_360']); // サンプル動画 size_560_360 サイズ
var sampleMovieURL_560_360 = jsonItemsFANZAresponse[key]['sampleMovieURL']['size_560_360']; // サンプル動画 size_560_360 サイズ
}
catch(e){
Logger.log('サンプル動画 size_560_360 サイズがありません');
var sampleMovieURL_560_360 = "";
}
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['sampleMovieURL']['size_644_414']); // サンプル動画 size_644_414 サイズ
var sampleMovieURL_644_414 = jsonItemsFANZAresponse[key]['sampleMovieURL']['size_644_414']; // サンプル動画 size_644_414 サイズ
}
catch(e){
Logger.log('サンプル動画 size_644_414 サイズがありません');
var sampleMovieURL_644_414 = "";
}
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['sampleMovieURL']['size_720_480']); // サンプル動画 size_720_480 サイズ
var sampleMovieURL_720_480 = jsonItemsFANZAresponse[key]['sampleMovieURL']['size_720_480']; // サンプル動画 size_720_480 サイズ
}
catch(e){
Logger.log('サンプル動画 size_720_480 サイズがありません');
var sampleMovieURL_720_480 = "";
}
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['prices']['price']); // 価格
var prices = jsonItemsFANZAresponse[key]['prices']['price']; // 価格
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['genre']['name']); // ジャンル名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['genre']['id']); // ジャンル id
// ジャンル数を取得
var genreLength = jsonItemsFANZAresponse[key]['iteminfo']['genre'].length;
for (let i = 0; i < genreLength; i++){
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['genre'][i]['name']); // ジャンル名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['genre'][i]['id']); // ジャンル id
genres.push(jsonItemsFANZAresponse[key]['iteminfo']['genre'][i]['name']);
genres_id.push(jsonItemsFANZAresponse[key]['iteminfo']['genre'][i]['id']);
}
}
catch(e){
Logger.log('特定のジャンルがありません');
}
var wp_genres = genres.join(","); // WordPrses用に , で区切る
var wp_genres_id = genres_id.join(","); // WordPrses用に , で区切る
// 続ぎ...
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['series']['name']); // シリーズ名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['series']['id']); // シリーズ id
var series_name = jsonItemsFANZAresponse[key]['iteminfo']['series']['name']; // シリーズ名
var series_id = jsonItemsFANZAresponse[key]['iteminfo']['series']['id']; // シリーズ id
// シリーズ数を取得
var seriesLength = jsonItemsFANZAresponse[key]['iteminfo']['series'].length;
for (let i = 0; i < seriesLength; i++){
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['series'][i]['name']); // シリーズ名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['series'][i]['id']); // シリーズ id
categories.push(jsonItemsFANZAresponse[key]['iteminfo']['series'][i]['name']);
categories_id.push(jsonItemsFANZAresponse[key]['iteminfo']['series'][i]['id']);
}
}
catch(e){
Logger.log('特定のシリーズがありません');
}
var wp_categories = categories.join(","); // WordPrses用に , で区切る
var wp_categories_id = categories_id.join(","); // WordPrses用に , で区切る
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['maker']['name']); // メーカー名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['maker']['id']); // メーカーid
var maker_name = jsonItemsFANZAresponse[key]['iteminfo']['maker']['name']; // メーカー名
var maker_id = jsonItemsFANZAresponse[key]['iteminfo']['maker']['id']; // メーカーid
// メーカー 数を取得
var makerLength = jsonItemsFANZAresponse[key]['iteminfo']['maker'].length;
for (let i = 0; i < makerLength; i++){
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['maker'][i]['name']); // メーカー名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['maker'][i]['id']); // メーカー id
makers.push(jsonItemsFANZAresponse[key]['iteminfo']['maker'][i]['name']);
makers_id.push(jsonItemsFANZAresponse[key]['iteminfo']['maker'][i]['id']);
}
}
catch(e){
Logger.log('特定のメーカーがありません');
}
var wp_maker = makers.join(","); // WordPrses用に , で区切る
var wp_maker_id = makers_id.join(","); // WordPrses用に , で区切る
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['actress']['name']); // 女優名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['actress']['id']); //女優id
var actress_name = jsonItemsFANZAresponse[key]['iteminfo']['actress']['name']; // 女優名
var actress_id = jsonItemsFANZAresponse[key]['iteminfo']['actress']['id']; //女優id
// 女優 数を取得
var actressLength = jsonItemsFANZAresponse[key]['iteminfo']['actress'].length;
for (let i = 0; i < actressLength; i++){
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['actress'][i]['name']); // 女優名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['actress'][i]['id']); // 女優 id
actresses.push(jsonItemsFANZAresponse[key]['iteminfo']['actress'][i]['name']);
actresses_id.push(jsonItemsFANZAresponse[key]['iteminfo']['actress'][i]['id']);
}
}
catch(e){
Logger.log('特定の女優がありません');
}
var wp_actresses = actresses.join(","); // WordPrses用に , で区切る
var wp_actresses_id = actresses_id.join(","); // WordPrses用に , で区切る
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['label']['name']); // ラベル名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['label']['id']); // ラベルid
var label_name = jsonItemsFANZAresponse[key]['iteminfo']['label']['name']; // ラベル名
var label_id = jsonItemsFANZAresponse[key]['iteminfo']['label']['id']; // ラベルid
// 女優 数を取得
var labelLength = jsonItemsFANZAresponse[key]['iteminfo']['label'].length;
for (let i = 0; i < labelLength; i++){
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['label'][i]['name']); // ラベル名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['label'][i]['id']); // ラベル id
labels.push(jsonItemsFANZAresponse[key]['iteminfo']['label'][i]['name']);
labels_id.push(jsonItemsFANZAresponse[key]['iteminfo']['label'][i]['id']);
}
}
catch(e){
Logger.log('特定のラベルがありません');
}
var wp_labels = labels.join(","); // WordPrses用に , で区切る
var wp_labels_id = labels_id.join(","); // WordPrses用に , で区切る
try{
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['director']['name']); //監督名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['director']['id']); // 監督 id
var director_name = jsonItemsFANZAresponse[key]['iteminfo']['director']['name']; //監督名
var director_id = jsonItemsFANZAresponse[key]['iteminfo']['director']['id']; // 監督 id
// 女優 数を取得
var directorLength = jsonItemsFANZAresponse[key]['iteminfo']['director'].length;
for (let i = 0; i < directorLength; i++){
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['director'][i]['name']); // 監督名
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['iteminfo']['director'][i]['id']); // 監督 id
directors.push(jsonItemsFANZAresponse[key]['iteminfo']['director'][i]['name']);
directors_id.push(jsonItemsFANZAresponse[key]['iteminfo']['director'][i]['id']);
}
}
catch(e){
Logger.log('特定の監督がありません');
}
var wp_directors = directors.join(","); // WordPrses用に , で区切る
var wp_directors_id = directors_id.join(","); // WordPrses用に , で区切る
Logger.log( key + ': ' + jsonItemsFANZAresponse[key]['maker_product']); // メーカー品番
var maker_product = jsonItemsFANZAresponse[key]['maker_product']; // メーカー品番
putGoogleSpreadSheetData(content_id, product_id, title, url, affiliateURL,
wp_sample_images, sample_image_L,review_num, review_avarage,sampleMovieURL_476_306,
sampleMovieURL_560_360, sampleMovieURL_644_414, sampleMovieURL_720_480,
prices, wp_genres, wp_genres_id, wp_categories, wp_categories_id, wp_maker,
wp_maker_id, wp_actresses, wp_actresses_id,wp_labels, wp_labels_id, wp_directors, wp_directors_id, maker_product, description,fanza_sample_mp4)
}
}
function get_fanza_description(url){
// 説明文を返す。なければ、空欄を返します。
var regexp_description = new RegExp("<meta name="description" content="(.*?)" />", "s");
//年齢認証ページをスキップするためのcookieを設定
var headers = { // リクエストヘッダー
'cookie': 'age_check_done=1;'
}
var options = {
'method': 'get', // POSTメソッド
'headers': headers
}
//dmmの商品ページをスクレイピングして動画説明文章を取得
var fanza_res = UrlFetchApp.fetch(url, options).getContentText();
//動画説明文の加工
if(fanza_res.match(regexp_description) !== undefined){
//動画説明格納
description = fanza_res.match(regexp_description)[1];
//htmlエンティティのデコード
description = XmlService.parse('<d>' + description + '</d>').getRootElement().getText();
//【FANZA(ファンザ)】文字除外
description = description.replace("【FANZA(ファンザ)】", "");
//htmlタグ除外
description = description.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'');
console.log(description);
return description;
}else{
return "";
}
}
function get_fanza_mp4_length(url){
if (url == undefined || url == ""){
return 9999999999;
}
const movie_blob = UrlFetchApp.fetch(url).getBlob();
const movie_file_size = movie_blob.getBytes().length;
return movie_file_size;
}
function get_fanza_sample_video_mp4(content_id){
//サンプル動画urlの取得
const sample_movie_url_mhb_w = 'https://cc3001.dmm.co.jp/litevideo/freepv/'+content_id.slice(0,1)+'/'+content_id.slice(0,3)+'/'+content_id+'/'+content_id+'_mhb_w.mp4';
const sample_movie_url_mhb_s = 'https://cc3001.dmm.co.jp/litevideo/freepv/'+content_id.slice(0,1)+'/'+content_id.slice(0,3)+'/'+content_id+'/'+content_id+'_mhb_s.mp4';
const sample_movie_url_dmb_w = 'https://cc3001.dmm.co.jp/litevideo/freepv/'+content_id.slice(0,1)+'/'+content_id.slice(0,3)+'/'+content_id+'/'+content_id+'_dmb_w.mp4';
const sample_movie_url_dmb_s = 'https://cc3001.dmm.co.jp/litevideo/freepv/'+content_id.slice(0,1)+'/'+content_id.slice(0,3)+'/'+content_id+'/'+content_id+'_dmb_s.mp4';
const sample_movie_url_sm_w = 'https://cc3001.dmm.co.jp/litevideo/freepv/'+content_id.slice(0,1)+'/'+content_id.slice(0,3)+'/'+content_id+'/'+content_id+'_sm_w.mp4';
const sample_movie_url_sm_s = 'https://cc3001.dmm.co.jp/litevideo/freepv/'+content_id.slice(0,1)+'/'+content_id.slice(0,3)+'/'+content_id+'/'+content_id+'_sm_s.mp4';
const sample_movie_url_vrlite = 'https://cc3001.dmm.co.jp/vrsample/'+content_id.slice(0,1)+'/'+content_id.slice(0,3)+'/'+content_id+'/'+content_id+'vrlite.mp4';
const sample_movie_urls = [sample_movie_url_mhb_w, sample_movie_url_mhb_s, sample_movie_url_dmb_w, sample_movie_url_dmb_s, sample_movie_url_sm_w, sample_movie_url_sm_s, sample_movie_url_vrlite];
for(const index in sample_movie_urls){
try{
const response_code = UrlFetchApp.fetch(sample_movie_urls[index], { muteHttpExceptions:true }).getResponseCode();
if(response_code == 200){
sample_movie_url = sample_movie_urls[index];
console.log(sample_movie_url);
return sample_movie_url
}else{
sample_movie_url = 0;
}
} catch (e) {
console.log(e);
return "";
}
}
return "";
}
function putGoogleSpreadSheetData(content_id, product_id, title, url, affiliateURL,
wp_sample_images, sample_image_L, review_num, review_avarage, sampleMovieURL_476_306,
sampleMovieURL_560_360, sampleMovieURL_644_414, sampleMovieURL_720_480,
prices, wp_genres, wp_genres_id, wp_categories, wp_categories_id, wp_maker,
wp_maker_id, wp_actresses, wp_actresses_id,wp_labels, wp_labels_id, wp_directors, wp_directors_id, maker_product, description,fanza_sample_mp4){
// 動画の長さを取得
let video_length = get_fanza_mp4_length(fanza_sample_mp4);
let video_upload_mark;
// 動画の長さでサンプル動画を投稿できるか判定
if (Number(video_length) > 49236568){
video_upload_mark = "動画投稿できません";
} else {
video_upload_mark = "動画投稿できます";
}
let content;
// シート2にURLがなければ、シート1とシート2に取得したFANZAデータを記入。
if (!fanza_url_values.includes(url)){
if (FANZA_TO_TWITTER_FLAG){
content = [title, sample_image_L[0], fanza_sample_mp4, affiliateURL, description, video_upload_mark]
} else{
content = [content_id, product_id, title, url, affiliateURL, wp_sample_images,
review_num, review_avarage, sampleMovieURL_476_306,
sampleMovieURL_560_360, sampleMovieURL_644_414,
sampleMovieURL_720_480, fanza_sample_mp4, prices, wp_genres, wp_genres_id,
wp_categories, wp_categories_id, wp_maker,
wp_maker_id, wp_actresses, wp_actresses_id,wp_labels, wp_labels_id,
wp_directors, wp_directors_id, maker_product, description];
}
Logger.log(content);
//最終行に1件ずつデータを追加
sheet1.appendRow(content);
// URLをシート2に挿入。同じURLは取得しない
sheet2.appendRow([url]);
}
}
function clear_sheet(){
sheet1.clear();
}
function delete_fanza_duplicates(){
let range = sheet1.getRange(delete_DUPLICATE_FANZA_RANGE);
range.removeDuplicates();
}
function get_posted_url(sheet){
//シート最終行の値を取得する
const lastRow = sheet.getLastRow() || 1;
//指定したセル範囲を取得する
const range = sheet.getRange(1, 1, lastRow);
//セル範囲の値を取得する - 2次元配列
const values = range.getValues();
// 1次元配列にする
const values_1 = values.flat();
return values_1;
}
function insert_post_url(url){
sheet2.appendRow(url);
}
function _testFANZA(){
// まずは、FANZAからの記事を自動取得しています。
// 条件を絞り込みたい場合、特定のキーワードを入力 例 上原あい など
var keyword = "伊藤舞雪";
fanza_api(keyword);
}
function _test_get_description_FANZA(){
var url = "https://www.dmm.co.jp/digital/videoa/-/detail/=/cid=kwbd00367/?utm_medium=dmm_affiliate&utm_source=zoqzoqqqq-990&utm_campaign=affiliate_api"
get_fanza_description(url);
}
function _test_video_get(){
var url = "https://cc3001.dmm.co.jp/litevideo/freepv/k/kwb/kwbd00367/kwbd00367_mhb_w.mp4";
get_fanza_mp4_length(url)
}
// 本番
function automate_get_fanzadata(){
// この関数をトリガーで実行しつづければ完全に自動化できます。
// 指定キーワード - 女優名、他 美少女、プレイ名などでも検索名はOKですが、同人などもまぎれるためFANZAのAPIを参考に
let keyword = "素人";
fanza_api(keyword);
}
function automate_tweet_fanza(){
// シートにあるデータをツイート
google_sheet_videos_tweet(GoogleSpreadSheet_URL);
}
function automate_get_dugadata(){
let keyword = "美少女";
_get_duga(keyword);
}
function automate_tweet_duga(){
google_sheet_videos_tweet(DUGA_SHEET_URL);
}
コメント