[Python / GAS] Eine Geschichte über das Erstellen einer persönlichen Web-API, mit der Sie alles darüber lesen können, wie man ein Romanautor im vertikalen Schreiben wird und es dann zu einem LINE-Bot macht.

Einführung

Genießt ihr alle euer Selbstbeherrschungsleben? Ich kann nicht aufs College, also verbringe ich meine Zeit damit, zu Hause Programmieren zu studieren, was nichts mit Forschung zu tun hat. ~~ Mehr Spaß als Forschung ... ~~

Außerdem habe ich mehr Zeit zum Lesen. Selbst wenn Sie Lesen sagen, ist der Prozentsatz der Menschen, die "Werden Sie Schriftsteller" lesen, hoch.

Um ein solches Leben in Selbstbeherrschung so angenehm wie möglich zu gestalten

** Sie können mehrere Episoden der Arbeit lesen, ein Romanautor in vertikaler Schrift zu werden **

Ich habe eine solche Web-API erstellt.

Bewegung

Die diesmal erstellte Web-API ist

-------- Naro Novel API --------

** Suche nach Romanen nach angegebenem Wort **   ↓ ** Wähle die Arbeit mit den höchsten Gesamtpunkten aus und erhalte NCODE **   ↓ -------- Naro Novel API --------   ↓ ** Verschrotte die Geschichte im angegebenen Bereich **   ↓ ** Vertikal formatiert in neuartiges HTML **   ↓ ** Unter der Voraussetzung **

Ich verarbeite im Fluss.

Beim Zugriff von einem Smartphone sieht es wie folgt aus. Sie können es lesen, indem Sie horizontal scrollen. (Aus 10 Episoden arbeitsloser Reinkarnation) image.png

Vom PC image.png

Implementierung

Python Zuerst von Python Scraping kann mit nur "Requests" und "Re" überwunden werden, und der Serverteil verwendet "Flask".

# -*- coding: utf-8 -*-
from flask import Flask
from requests import get
import re

app = Flask(__name__)


def narou_html(keyword, num=1, pivot='e'):
    honbun_ = ""
    item = get(
        f"https://api.syosetu.com/novelapi/api/?out=json&of=t-n&lim=1&order=hyoka&word={keyword}"
    ).json()[1]
    #item = max(items[1:], key=lambda x: x["global_point"])  #Überreste einer Ära, in der Sie nicht wussten, dass Sie die API in sortierter Form aufrufen können
    url = "https://ncode.syosetu.com/"
    ncode = item["ncode"]
    headers = {
        'User-Agent':
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.76 Safari/537.36'
    }
    t = get(url + ncode, headers=headers).text
    slist = []
    sl = re.findall('<dl class="novel_sublist2">(.+?)</dl>',
                    t.replace("\n", ""))
    for i in sl[-num:] if pivot == 'e' else sl[:num +
                                               1] if pivot == 's' else sl[
                                                   int(pivot) - 1:int(pivot) +
                                                   num - 1]:
        groups = re.search(
            '<a href="/(.+?)/">(.+?)</a></dd><dt class="long_update">(.+?)[(?:<span)|(?:</dt>)]',
            i)
        slist.append({
            "title": groups.group(2),
            "href": groups.group(1),
            "long_update": groups.group(3)
        })
    for s in range(len(slist)):
        t = get(url + slist[s]["href"], headers=headers).text
        honbun = re.search(
            '<p class="novel_subtitle">(?:.|\s)+?<div id="novel_honbun"(?:.|\s)+?</p>\n</div>',
            t).group(0)
        for j, i in enumerate(honbun.splitlines()):
            if i[:2] == "<p":
                groups = re.search("(<p.*?>)(.+?)(</p>)", i)
                i = re.sub('(\d{1,4})',
                           '<span class="text-combine">\\1</span>',
                           groups.group(2))
                if i[0] in ('(', '「', '(', '『',
                            '【') and honbun_[-9] not in (')', ')', '」', '』',
                                                         '】'):
                    i = '<br><br>' + i
                if i[-1] in (')', ')', '」', '』', '】'):
                    i += '<br><br>'
                if i[0] == '・': i = '<br>' + i + '<br>'
                elif j > 1 and i[0] != '<' and honbun_[-1] != '>':
                    if re.match("\s", i):
                        i = i[1:]
                elif not re.match('\s', i) and i[0] not in ('(', '「', '(', '『',
                                                            '【'):
                    i = " " + i
                if j == 0:
                    i = '<h3>' + i + '</h3>\n<br><br>'
            honbun_ += i
        honbun_ += "<br>" * 25 + "\n"
    honbun_ = '''<html>

<head>
    <meta name="viewport" content="initial-scale=1.3,minimum-scale=1.3">
    <style>
        body {
            margin-top: 3.5%;
            margin-bottom: 3%;
            white-space: break-all;
            -ms-writing-mode: tb-rl;
            writing-mode: vertical-rl;
            text-orientation: upright;
            font-family: "Noto Serif JP", serif;
            font-size: 85%;
        }

        .text-combine {
            -webkit-text-combine: horizontal;
            -ms-text-combine-horizontal: all;
            text-combine-upright: all;
        }
    </style>
    <title>''' + item["title"] + '''</title>
    <link href="https://fonts.googleapis.com/css?family=Noto+Serif+JP&display=swap&subset=japanese" rel="stylesheet">
</head>

<body>
    ''' + honbun_[:-93].replace('→', '↓').replace('-', '|').replace("-", "|") + '''</body>

</html>'''
    return honbun_


@app.route("/")
def hello_world():
    return "Usage: http://ip-address:port/title/pivot/num             pivot - s: from the first. e: from the end. m: pick up one."


@app.route('/<keyword>/<pivot>/<num>')
def html_(keyword, pivot, num):
    html = narou_html(keyword, int(num), pivot)
    return html


if __name__ == "__main__":
    app.run(host="0.0.0.0")

(Wenn Sie viele reguläre Ausdrücke verwenden, wird die Farbcodierung von Qiita aufgrund eines Backslashs zusammenbrechen und es wird traurig sein.) Da die Formgebung es gut aussehen lässt, sind manchmal die Sätze, die gebrochen werden sollten, miteinander verbunden.

Nach der Ausführung "http: // localhost: 5000 / Suchwort / später beschrieben / später beschrieben" (nur vom ausführenden Terminal) oder "http: // lokale IP-Adresse des ausführenden Terminals: 5000 / Suchwort / später beschrieben / später beschrieben" Sie können es unter lesen. Der Teil von "später beschrieben" ist Für die erstere aus der ersten Folge mit "s", aus der letzten Folge mit "e", aus dem durch "number" angegebenen Teil Was steckt dahinter, wie viele Geschichten müssen zurückgegeben werden? Sie können angeben.

GAS(Google Apps Script)

Ich habe versucht, es auf Heroku hochzuladen, um es zu einem LINE-Bot zu machen, aber es schien, als könnte ich nicht davon abkommen, ein Romanautor von Herokus Server zu werden, also habe ich es mit GAS neu geschrieben. Ich tat. Ich schreibe selbst nicht viel Javascript, aber obendrein war der Code, wie die eigenen Funktionen von GAS, kurz, aber es war viel Versuch und Irrtum. Besonders, ich lasse Jupyter normalerweise sofort laufen! Sofortige Antwort! Es war fatal, dass das Protokoll nicht richtig angezeigt werden konnte, weil ich mich daran gewöhnt hatte.

Verwenden von zwei Projekten als LINE-Bot, Eine ist für die LINE-Antwort, Die zweite ist für die Web-API ähnlich dem obigen Python-Code Es wurde gemacht.

Wenn Sie eine Nachricht senden, antwortet das erste Projekt mit einer URL, und wenn Sie auf diese URL zugreifen, erhalten Sie vom zweiten Projekt eine formatierte Seite des Romans. Es ist ein Fluss. GAS ist erstaunlich, dass Sie dies kostenlos tun können. Aber es ist langsam.

Die erste besteht darin, nur die URL zurückzugeben. Ich habe mich daher entschlossen, einen Blick auf die Website zu werfen, auf der erklärt wird, wie ein LINE-Bot mit GAS erstellt wird, und ich werde nur den zweiten Code veröffentlichen. Auch hier wird es von der Python-Version vereinfacht, z. B. nur von der neuesten Story bis zur Rückgabe der angegebenen Anzahl von Storys zu implementieren (vielmehr wurde die Python-Seite nach dem Schreiben verbessert).

function doGet(e) {
  var keyword = e.parameter.keyword; //Suchbegriff
  var num = parseInt(e.parameter.num); //Anzahl der Geschichten
  var getUrl = "https://api.syosetu.com/novelapi/api/?out=json&of=t-n&lim=1&order=hyoka&word="+keyword;
  var response = UrlFetchApp.fetch(getUrl).getContentText('UTF-8');
  var json = JSON.parse(response)[1];
  var title = json["title"]
  var ncode = json["ncode"]
  getUrl = "https://ncode.syosetu.com/"+ncode;
  response = UrlFetchApp.fetch(getUrl).getContentText('UTF-8').replace(/[\r\n]+/g,"");
  var items = response.match(/<dl class="novel_sublist2">(.+?)<\/dl>/gm);
  items = items.slice(items.length-num,items.length);
  var slist = [];
  for (var i = 0;i<num;i++){
    slist.push(items[i].match(/(<a href="\/)(.+?)(\/">)/)[2]); //Sammle hrefs für bestimmte Geschichten
  }
  var honbun = ""
//Unterhalb der Formungszeit
  for (var s = 0;s<num;s++){
    getUrl = "https://ncode.syosetu.com/"+slist[s];
    response = UrlFetchApp.fetch(getUrl).getContentText('UTF-8');
    var honbun_ = response.match(/<p class="novel_subtitle">(?:.|\s)+?<div id="novel_honbun"(?:.|\s)+?<\/p>\n<\/div>/)[0];
    var sphon=honbun_.split(/[\r\n]+/g);
    for (var i = 0, len=sphon.length;i<len;i++){
        if (sphon[i].slice(0,2) == "<p"){
          var groups = sphon[i].match(/(<p.*?>)(.+?)(<\/p>)/);
          var temp = groups[1] + groups[2].replace(/(\d{2,4})/g, '<span class="text-combine">$1<\/span>') + groups[3];
          if(i == 0){
            temp = '<h3>' + temp + '</h3>';
            Logger.log(temp);
          }
          honbun += temp + "\n"
        }
        else{honbun += sphon[i] + "\n";}
     }
    honbun += "</br></br>";
  }
  honbun = '<html>\n<head>\n <title>' + title + '</title>\n</head>\n<font size="5"><style>\n    body {\n        -ms-writing-mode: tb-rl;\n        writing-mode: vertical-rl;\n        text-orientation: upright;\n       font-family: "Yu Mincho", YuMincho, "Hiragino Mincho ProN W3", "Hiragino Mincho ProN W3", "Hiragino Mincho ProN", "HG Mincho E.", "MS P Mincho", "MS morgen früh", serif;\n   }\n\n    .text-combine {\n        -webkit-text-combine: horizontal;\n        -ms-text-combine-horizontal: all;\n        text-combine-upright: all;\n    }\n</style>\n\n<body>\n' + honbun + ' \n</body>\n</font>\n</html>'
  var html = HtmlService.createHtmlOutput(honbun);  //Ich bin mir nicht sicher. Ein vorbereitender Typ, um HTML im Status einer Zeichenkette als HTML anzuzeigen?
  return html;
}

Veröffentlicht → Als Webanwendung eingeführt Und die generierte Adresse + ? Schlüsselwort = Suchwort & Anzahl = Anzahl der Geschichten Beim Zugriff wird die vertikal formatierte Seite angezeigt. (LINE Bot wird diese Adresse im ersten Projekt beantworten.) image.png

Zusammenfassung

Das Lesen schreitet voran ... HTML ist ein Amateur. Wenn es Ihnen nicht gefällt, ändern Sie es ... …… Wenn Sie es verwenden, verwenden Sie es bitte mit Mäßigung, um den Server nicht stark zu belasten und Romanautor zu werden.

Recommended Posts

[Python / GAS] Eine Geschichte über das Erstellen einer persönlichen Web-API, mit der Sie alles darüber lesen können, wie man ein Romanautor im vertikalen Schreiben wird und es dann zu einem LINE-Bot macht.
[Google Photo & Slack Photo Bot] Eine Geschichte über das Erstellen eines Bots, der ein Foto in Google Photo erfasst und an Slack sendet.
Eine Geschichte über alles von der Datenerfassung über die KI-Entwicklung bis hin zur Veröffentlichung von Webanwendungen in Python (3. KI-Entwicklung)
Erstellen Sie ein Plugin, mit dem Sie in Python nach Registerkarten für Sublime Text 3 suchen können
[Python] Eine Geschichte über das Erstellen eines LINE-Bots mit einer praktischen bemannten Funktion ohne Verwendung von Salesforce [Messaging-API]
Python-Skript, das das Azure-Status-RSS crawlt und an Hipchat sendet
[Python] Informationen zum Erstellen eines Tools zum Anzeigen aller Seiten der Website, die in der JSON-Datei registriert sind und auf denen sie abgefangen wurden
Jedi-vim-Verknüpfungsbefehl, mit dem Sie auf die Definitionsquelle und das Definitionsziel in Python verweisen können
Lern-Roadmap, mit der Sie Services mit Python von Grund auf neu entwickeln und veröffentlichen können
Eine Geschichte, die es einfach macht, den Wohnbereich mit Elasticsearch und Python abzuschätzen