[PYTHON] Re: Heroku Leben von vorne anfangen mit Flask ~ Selenium & PhantomJS & Beautifulsoup ~

Einführung

Zum ersten Mal habe ich eine API erstellt, die mit json mithilfe von Flask und Heroku of Python Scraped-Informationen zurückgibt. Daher möchte ich die Methode zusammenfassen, die ich damals durchgeführt habe.

Die von Heroku bis Hello World verwendeten und die Umgebungskonstruktion von Python sind der erste Teil. Re: Heroku Leben - Umgebung beginnt mit Flask von Null und der Hallo Welt ~ Beim Dies ist der zweite Teil, bis das zu erstellende Programm auf Heroku bereitgestellt wird. Re: Das Leben in Heroku beginnt von Grund auf mit Flask ~ PhantomJS bis Heroku ~ Da es eingeschrieben ist, siehe bitte auch

Was ist diesmal zu tun?

Wenn Sie studieren, können Sie die Räder neu erfinden

Dieses Mal werde ich schreiben, wie man mit Selenium und PhantomJS mit SlideShare als Thema kratzt.

*** Da es lang wurde, als ich es in einem Artikel zusammenstellte, ist der Ablauf der Bereitstellung für Heroku in den zweiten Teil unterteilt. *** ***

Spezifische Bewegung

[HerokuURL] / api / [Suchwort] / [Anzahl der Seiten] Beispiel: ~ herokuapp.com/api/python/2 Wenn Sie zugreifen

  1. PhantomJS arbeitet mit Heroku und öffnet die Slideshare-Suchseite

  2. Geben Sie das [Suchwort] der URL in das Suchfeld der zu suchenden Suchseite ein.

  3. Ändern Sie die Spracheinstellung der Suchergebnisse in Japanisch

  4. Extrahieren Sie Folieninformationen in Webseiten durch Scraping スクリーンショット 2016-10-17 22.10.28.png

  5. Klicken Sie auf dem Pager unter der Anzahl der Seiten in der URL auf Weiter und wiederholen Sie das Scraping. スクリーンショット 2016-10-17 22.22.28.png

  6. Legen Sie es nach dem Schaben in das JSON-Format und werfen Sie es!

Ich möchte eine API erstellen, die das tut.

Was ich diesmal benutzt habe

Vorbereitung

Umgebungsbau muss vor dieser Zeit durchgeführt werden

Re: Heroku Leben - Umgebung beginnt mit Flask von Null und der Hallo Welt ~ Installiert, wenn Sie Hello World ausführen Bitte geben Sie *** Flask *** und *** Gunicorn *** an Bitte bereiten Sie Ihre Lieblingsumgebung wie pyenv-virtualenv vor.

Erstellen einer zusätzlichen Umgebung für diese Zeit

PhantomJS Setzen Sie PhantomJS lokal ein, um den Vorgang lokal zu überprüfen, bevor Sie es auf Heroku ausführen. Ich denke, es ist in Ordnung zu erkennen, dass der Browser keine GUI hat, die mit Code bedient werden kann. Referenz: Probieren Sie verschiedene Dinge mit PhantomJS aus

$  brew install phantomjs

Selenium Es scheint sich um ein browser- und plattformübergreifendes UI-Testtool zu handeln. Beim normalen Scraping können Sie nur das tun, was unter der angegebenen URL angezeigt wird. Mit Selen können Sie jedoch die Taste drücken, um zur nächsten Seite zu gelangen, oder Zeichen eingeben und die Suchtaste drücken. Beeindruckend

Es ist Ruby, aber es ist ein hilfreicher Artikel: Versuch zur Automatisierung von Web-UI-Tests mit Selenium

$ pip install selenium

beautifulsoup Es wird bei der Verarbeitung der erfassten Webseitendaten verwendet. Referenz: Scraping mit Python und Beautiful Soup

$ pip install beautifulsoup4

lxml Wird in Kombination mit einer schönen Suppe verwendet.

$ pip install lxml

Ein Typ, der domänenübergreifende Einschränkungen mit Cors vermeidet

Selbst wenn Sie eine API erstellen, die normalerweise Json zurückgibt, ist es schwierig, eine API zu verwenden, die aufgrund domänenübergreifender Einschränkungen in Chrome nicht behandelt wurde. Daher werde ich Maßnahmen ergreifen. Ich werde einen Link in die Code-Erklärung einfügen.

$ pip install -U flask-cors

Was wurde gemacht

https://github.com/ymgn/SlideShare-API

api.py


# -*- coding: utf-8 -*-

import json
#Ab hier ist Schaben erforderlich
from bs4 import BeautifulSoup
#Von hier aus müssen Sie den Browser mit Selen bedienen
from selenium import webdriver 
from selenium.webdriver.common.keys import Keys #Wird bei der Eingabe von Zeichen verwendet

#Ab hier die benötigte Kolbenmenge
import os
from flask import Flask

#Von hier aus für domänenübergreifende Einschränkungen bei Verwendung von Cors, die Ajax mit Kolben einstellen
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app)

@app.route('/')
def index():
    return "Wie benutzt man: /api/Wort zu suchen/Anzahl der erfassten Seiten"

@app.route('/api/<string:word>/<int:page>') #Suchbegriff/Erhalten Sie die Anzahl der Seiten vom Pfad zur Variablen
def slide(word,page):
 
    driver = webdriver.PhantomJS() #Verwenden Sie PhantomJS
    driver.set_window_size(1124, 850) #Geben Sie die Größe von PhantomJS an
    driver.implicitly_wait(20) #Wenn kein Element angegeben ist, wartet der Treiber automatisch bis zu 20 Sekunden, bis es herauskommt.

    URL = "http://www.slideshare.net/search/"
    driver.get(URL) #Greifen Sie auf die Slideshare-URL zu
    data_list = [] #Ein Array, das Daten für alle Seiten sammelt

    search = driver.find_element_by_id("nav-search-query") #Suchfeldelement abrufen
    search.send_keys(word) #Geben Sie ein Suchwort ein
    search.submit() #Suche senden

    lang = driver.find_element_by_xpath("//select[@id='slideshows_lang']/option[@value='ja']") #Extrahieren Sie den japanischen Teil der Sprachauswahlliste
    lang.click() #Wählen Sie Japanisch als Sprachauswahl

    for i in range(0,page): 
        print(str(i+1) + u"Seite Seite")
        data = driver.page_source.encode('utf-8') #Verwenden Sie die Informationen auf der Seite-In 8 vorbereiten
        soup = BeautifulSoup(data,"lxml") #Machen Sie es im lxml-Format für eine einfache Verarbeitung
        slide_list = soup.find_all("div",class_="thumbnail-content") #Mit Folie extrahieren
        for slide in slide_list:
            slide_in = {} #Organisieren Sie Folieninformationen im Wörterbuchformat
            
            #Holen Sie sich den Namen des Dia-Posters
            name = slide.find("div",class_="author").text
            slide_in["name"] = name.strip() # strip()Beseitigt Leerzeichen und Zeilenumbrüche an beiden Enden
            
            #Holen Sie sich den Titel der Folie
            title = slide.find("a",class_="title title-link antialiased j-slideshow-title").get("title") #Angegebenes Tag&Geben Sie einen Titel in der Klasse aus
            slide_in["title"] = title

            #Holen Sie sich den Folienlink
            link = slide.find("a",class_="title title-link antialiased j-slideshow-title").get("href") #Angegebenes Tag&Ausgabe href in der Klasse
            slide_in["link"] = "http://www.slideshare.net" + link
            
            #Holen Sie sich den Link zur Miniaturansicht der Folie
            imagetag = slide.find("a",class_="link-bg-img").get("style") #Angegebenes Tag&Setzen Sie den Stil in der Klasse aus
            image = imagetag[imagetag.find("url(")+4:imagetag.find(");")] #Entfernen Sie unnötige Teile
            slide_in["image"] = image
            
            #Erhalten Sie Folien und Likes, dh die Anzahl der Seiten mit Folien
            info = slide.find("div",class_="small-info").string #Holen Sie sich die Zeichenfolgen von Folien und Likes
            slides = info[7:info.find("slides")] #Extrahieren Sie den Folienteil
            slide_in["slides"] = slides.strip() # strip()Beseitigt Leerzeichen und Zeilenumbrüche an beiden Enden
            if "likes" in info:
                likes = info[info.find(", ")+2:info.find("likes")] #Extrahieren Sie den Likes-Teil
            else:
                likes = "0"
            slide_in["likes"] = likes.strip() # strip()Beseitigt Leerzeichen und Zeilenumbrüche an beiden Enden

            data_list.append(slide_in) # data_Fassen Sie den Inhalt einer Seite in der Liste zusammen

        driver.execute_script('window.scrollTo(0, 3000)') #Mit Pager nach unten gehen
        next = driver.find_element_by_xpath("//li[@class='arrow']/a[@rel='next']") #Extrahieren Sie das NEXT-Element des Pagers
        next.click() #Klicken Sie auf die Schaltfläche Weiter

    driver.close() #Browserbetrieb beenden
    jsonstring = json.dumps(data_list,ensure_ascii=False,indent=2) #Geben Sie das erstellte Array im JSON-Format aus
    return jsonstring
 
#Bestimmen Sie, ob Sie mit Bash schlagen oder mit Import einfügen
if __name__ == '__main__':
    app.run()

Codekommentar

Ich habe auch Kommentare in den Code geschrieben, möchte aber die wichtigen Teile von oben erläutern. Der Import ist wie geschrieben, also weggelassen CORS Programme, die APIs verwenden, funktionieren nicht unter Chrome usw.! Ich denke du hast die Erfahrung. Da wir mit viel Aufwand eine API erstellen, sollten wir Maßnahmen ergreifen.

from flask_cors import CORS, cross_origin

app = Flask(__name__)
CORS(app)

Es scheint, dass wenn Sie schreiben, es Maßnahmen ergreifen wird. Benri Referenz: https://flask-cors.readthedocs.io/en/latest/

Nehmen Sie ein Argument aus dem Flaschenpfad

Sie können den Inhalt des Pfads als Argument erhalten, indem Sie <Typname: Variablenname> in die Route von Flask und den Variablennamen in () von def schreiben.

@app.route('/api/<string:word>/<int:page>') #Suchbegriff/Erhalten Sie die Anzahl der Seiten vom Pfad zur Variablen
def slide(word,page):

Referenz: Lassen Sie uns Flask meistern

Bestimmen Sie die Browsergröße von PhantomJS

driver.set_window_size(1124, 850)

Wenn Sie die Browsergröße nicht festlegen, können Sie keine Elemente aufnehmen oder nicht gut scrollen. Der Grund ist unbekannt, da der numerische Wert der Größe so ist, wie er geschrieben wurde, als ich ihn überprüft habe.

Warten auf das Lesen des Elements

driver.implicitly_wait(20)

Wenn Sie auf diese Weise die ID und Klasse von "driver.find ~~" angeben und das Element abrufen und bedienen, warten Sie bis zu 10 Sekunden und führen Sie es sofort aus, wenn das Lesen abgeschlossen ist. Es wird in einem bequemen Zustand zu tun sein. Dies ist sehr praktisch, wenn Sie mit Selen arbeiten, da Sie nicht explizit auf die erwartete Wartezeit warten müssen, z. B. `` time.sleep (3) `. Referenz: Es ist im Abschnitt Implizite Wartezeiten dieser Website geschrieben

Geben Sie den Text in das Formularfeld ein und senden Sie ihn ab

search = driver.find_element_by_id("nav-search-query") #Suchfeldelement abrufen
search.send_keys(word) #Geben Sie ein Suchwort ein
search.submit() #Suche senden

Nachdem Sie das Eingabeelement usw. per ID vom Browser erhalten haben, können Sie den Wert mit `send_keys (" hoge ")` `eingeben. Wenn sich das Element in einem Formular befindet, können Sie es senden, indem Sie .submit () `` hinzufügen.

Wählen Sie Dropdown

lang = driver.find_element_by_xpath("//select[@id='slideshows_lang']/option[@value='ja']") #Extrahieren Sie den japanischen Teil der Sprachauswahlliste
lang.click() #Wählen Sie Japanisch als Sprachauswahl

Dieses Mal wird die Elementspezifikationsmethode von XPATH anstelle von id oder class angegeben. Der Grund dafür ist, dass bei der Auswahl eines untergeordneten Elements mit mehreren IDs oder nur des übergeordneten Elements eine ID in einem anderen Teil als id und class angegeben werden muss.

Übrigens, wenn Sie nicht so auf Japanisch wechseln, auch wenn Sie das Japanisch lokal erhalten, erhält die Heroku-Seite die Folien aller Sprachen.

Wenn es mehrere IDs gibt

lang = driver.find_elements_by_id("slideshows_lang")
lang[1].find_elements_by_tag_name("option")
#Beim Extrahieren mehrerer Elemente erfolgt dies von Element zu Element

Wenn nur der Elternteil eine ID hat

lang = driver.find_element_by_id("slideshows_lang")
lang.find_element_by_tag_name("option")

Informationen zum Schreiben von XPATH und anderen Extraktionsmethoden finden Sie in der Referenz. Referenz: Elemente suchen

Mach dich bereit zum Schaben

data = driver.page_source.encode('utf-8') #Verwenden Sie die Informationen auf der Seite-In 8 vorbereiten
soup = BeautifulSoup(data,"lxml") #Machen Sie es im lxml-Format für eine einfache Verarbeitung

Verwenden Sie nach dem Codieren der Seitendaten der Website, die Webdriver mit utf-8 erhalten hat, lxml, das mit Beautiful Soup kompatibel ist, um das Scrapen zu vereinfachen. Ich habe es eingefügt, weil es jedes Mal geladen werden muss, wenn sich die Seite ändert.

scrollen

driver.execute_script('window.scrollTo(0, 3000)') #Mit Pager nach unten gehen

Jetzt können Sie PhantomJS mit JavaScript um 3000 Pixel nach unten scrollen. Wenn PhantomJS keine grafische Benutzeroberfläche hat, macht das Scrollen keinen Sinn, oder? Sie denken vielleicht, aber wenn Sie nicht scrollen, wird eine Fehlermeldung angezeigt. Ich wollte nach unten gehen, weil ich es auf 3000 gesetzt habe, also habe ich es vorerst auf 3000 gesetzt.

Misst gegen ein Tag, das weder ID noch Klasse unter mehreren Klassennamen hat

next = driver.find_element_by_xpath("//li[@class='arrow']/a[@rel='next']") #Extrahieren Sie das NEXT-Element des Pagers
next.click() #Klicken Sie auf die Schaltfläche Weiter

Als ich versuchte, auf dem Pager-Teil von Slideshare auf Weiter zu klicken, hatten sowohl Zurück als auch Weiter `class =" Pfeil "` und das darin enthaltene a-Tag hatte weder ID noch Klasse. .. Da ich `rel =" next "` in das a-Tag des untergeordneten Elements geschrieben habe, ist dieser Teil auf XPATH gesetzt, das einschließlich des übergeordneten Elements und rel angegeben werden kann.

Konvertieren Sie das erstellte Array in das JSON-Format

jsonstring = json.dumps(data_list,ensure_ascii=False,indent=2) #Geben Sie das erstellte Wörterbuch im JSON-Format aus
return jsonstring
json.dumps(Array,Wörterbuchdaten,Falsch, wenn Japanisch enthalten ist,Nach Einzug organisieren)

Wenn Sie ein Array oder Wörterbuch übergeben, wird es im JSON-Format vorliegen. Einzug kann weggelassen werden, und wenn "Einzug = 2" gesetzt ist, wird er mit zwei Leerzeichen mit halber Breite eingerückt, um die Anzeige zu erleichtern. Referenz: [Python] Handle JSON

Ablauf von der Bestätigung der Bewegung bis zur Bereitstellung in Heroku

Starten Sie Flask lokal und überprüfen Sie

Angenommen, Sie haben alles installiert, was Sie benötigen.

Ordner- und Kolbenvorbereitung

$ mkdir slide
$ cd slide

$ touch api.py Procfile
#Erstellen Sie eine Datei, um die Kolbendatei und die Einstellungen zu schreiben

Dateien erforderlich beim Starten von Flask

Procfile

web: gunicorn hello:app --log-file=-

api.py


Siehe oben

Lassen Sie uns zuerst die Bewegung mit Flask überprüfen

$ python api.py
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

http://127.0.0.1:5000/api/python/2 Greifen Sie über diesen Pfad zu und lassen Sie zwei Seiten von Python auf Slideshare durchsuchen. Ergebnis スクリーンショット 2016-10-16 17.52.34.png In Safari sieht json wie eine Liste aus, aber wenn Sie JSON View usw. in Chrome einfügen, können Sie es wunderschön sehen.

Referenz

Verschiedene Bibliotheken, die zum Crawlen und Scraping in Python verwendet werden können

In Heroku bereitstellen

Der Bereitstellungsfluss für Heroku ist der zweite Teil Re: Das Leben in Heroku beginnt von Grund auf mit Flask ~ PhantomJS bis Heroku ~ Da es geschrieben steht, danke.

Nachwort

Derzeit grundlegende Selenium-Browser-Vorgänge (Zeicheneingabe, Senden, Auswahl der Dropdown-Liste, Elementklick, XPATH-Spezifikation) und Scraping (Text, Bild, URL, Verarbeitung von Zeichenfolgen und Jsonisierung) Ich glaube, ich konnte schreiben, wie es geht, also hoffe ich, dass es jemandem hilft.

Wir würden uns freuen, wenn Sie im Kommentarbereich auf Verbesserungen oder Fehler hinweisen könnten. Twitter:@ymgn_ll

Recommended Posts

Re: Heroku Leben von vorne anfangen mit Flask ~ Selenium & PhantomJS & Beautifulsoup ~
Re: Heroku Leben von Grund auf neu mit Flask ~ PhantomJS bis Heroku ~
Re: Heroku Leben beginnt mit Flask von Null - Umwelt und Hallo Welt -
Geschäftseffizienz von Grund auf mit Python
Selen, Phantomjs & BeautifulSoup4
Micro Service mit GCP auf RoR von Grund auf neu
Maschinelles Lernen von Grund auf neu (maschinelles Lernen mit Kaggle)
[Tweepy] Re: Twitter Bot Entwicklungsleben ab Null # 1 [Python]
Vom Umgebungsaufbau bis zum Einsatz für Kolben + Heroku mit Docker
Betreff: Wettbewerbsfähiges Programmierleben von vorne anfangen Damit Anfänger noch etwas mehr Leistung erzielen ~ ABC154 ~ 156 mit Impressionen ~
Betreff: Wettbewerbsfähiges Programmierleben ab Null Kapitel 1.3 "Beilagentee"
Django von vorne anfangen (Teil: 2)
Django von vorne anfangen (Teil: 1)
Schaben mit Selen in Python
Berühre Flask + laufe mit Heroku
Scraping mit Selen in Python
PySpark Leben beginnt mit Docker
Betreff: Wettbewerbsfähiges Programmierleben ab Null Kapitel 1.2 "Python der Tränen"