[PYTHON] Ich habe versucht, den Pferderennplatz Teil 2 zu kriechen und abzukratzen

Einführung

"Python Crawling & Scraping [Augmented Revised Edition] - Praktisches Entwicklungshandbuch für die Datenerfassung und -analyse -" Erstellen Sie ein Originalprogramm mit den Kenntnissen bis Kapitel 3.

Dieses Mal habe ich ein Programm erstellt, das die URL einer einzelnen Seite aus den Suchergebnissen der Rennpferdesuchfunktion von netkeiba abruft, auf diese URL zugreift, die Informationen jedes Pferdes abruft und in der Datenbank speichert.

Seitenstruktur der Suchergebnisse

Das Suchfenster befindet sich oben in der Basis-Netkeiba und wird daher weggelassen. Mit der erweiterten Suchfunktion können Sie verschiedene Suchbedingungen wie Stammbaum, Haarfarbe, Anzeigereihenfolge usw. festlegen. Dieses Mal bin ich ohne Verwendung des Suchfensters zur Suchergebnisseite in der Spalte Zuchtleistung von Deep Impact Details Page gesprungen (dieser Bereich wird später beschrieben). Bezogen auf JavaScript-Verschränkung) (Klicken Sie auf den rot eingekreisten Link.)

Hier ist zunächst die Suchergebnisseite. Die Suchergebnisse sind standardmäßig nach Preis sortiert. Dieses Mal wird die Seite jedes mit diesem Suchergebnis verknüpften Pferdes abgekratzt.

Auf dieser Suchergebnisseite finden Sie Informationen wie Pferdename, Stall, Stammbaum, Pferdebesitzer usw. Konzentrieren Sie sich jedoch zunächst darauf, die URL der Detailseite jedes Pferdes abzurufen. Jeder Pferdename ist ein Link zur Seite mit den Pferdedetails und die URL endet mit dem Geburtsjahr + 6 Ziffern.

Im URL-Parameter der Suchergebnisseite wird die Nummer "2002100816" am Ende der Detailseite für tiefe Auswirkungen als sire_id angegeben, und die Pferde, die als Vater tiefe Auswirkungen haben, werden eingegrenzt. (Oben befindet sich "Suchergebnis". Wenn Sie jedoch nach dem Pferdenamen suchen, lautet dieser Teil "Suchergebnis von (Pferdename)".)

Dieses Mal möchte ich nicht nur die erste Ergebnisseite erhalten, sondern auch die zweite und die folgenden Seiten, die durch Klicken auf "Weiter" übersprungen werden können, aber der Link dieses Teils ist

<a href="javascript:paging('2')">Nächster</a>

Wenn Sie darauf klicken, wird die nächste Seite angezeigt Die URL lautet https://db.netkeiba.com/, und Sie können sehen, dass der Bildschirmübergang mithilfe von POST durchgeführt wird. (Gleiches gilt für die Suchergebnisseite, wenn das erweiterte Suchformular verwendet wird.) Der Teil der eigentlichen Paging-Funktion ist

function paging(page)
{
document.sort.page.value = page;
document.sort.submit();
}

Sie können sehen, dass es mit Javascript gesendet wird. Wenn Sie das Überprüfungstool des Browsers starten und auf "Weiter" klicken 2019-11-03 19.04.56 db.netkeiba.com 06565a7f139a.png Da der Wert wie dieser POSTed ist, db.netkeiba.com/?pid=horse_list&_sire_id=2002100816&page=(ページ番号) Wenn Sie den Seitenparameter am Ende der URL der Suchergebnisseite angeben, können Sie die zweite und die folgenden Seiten per GET abrufen.

Detail Seitenstruktur

Diesmal der Name des Pferdes, aktiv oder gelöscht, Geschlecht, Haarfarbe oben im Hauptinhalt auf der Detailseite, Analysieren Sie die Tabelle mit Informationen wie dem Geburtsdatum und der Tabelle des Stammbaums darunter und speichern Sie das Ergebnis in der Datenbank.

2019-10-20 23.17.03 db.netkeiba.com f349a0d9a4b6.png 2019-10-20 23.23.46 db.netkeiba.com a15e20bf34a7.png

Die beiden oberen Seiten sind detaillierte Seiten der beiden tiefgreifenden Produktionsstücke, die zum Zeitpunkt des Schreibens den ersten und den zweiten Preis gewonnen haben. Ich stelle jedoch fest, dass die Anzahl der Elemente in der Tabelle, in denen Daten wie das Geburtsdatum angezeigt werden, unterschiedlich ist. In Netkeiba wird der Punkt "Rekrutierungsinformationen" auf der Seite von Pferden hinzugefügt, die sogenannten Bissclubs gehören. Daher unterscheidet sich die Anzahl der Elemente in der Tabelle von denen von Nicht-Clubpferden. Dies muss beim Schaben berücksichtigt werden. ..

Darüber hinaus haben Pferde, die zu lokalen Pferderennen gehören, und ausländische Pferde Symbole wie □ Boden und ○ außerhalb des Pferdenamens, so dass außer dem Pferdenamen nur der Pferdename erfasst wird Machen. Wie Sie auf dem ersten Bild unten sehen können, gibt es auf dem □ Boden (Pferd, das zum örtlichen Pferderennen gehört) keinen Hinweis auf aktiven Dienst oder Löschung. Daher sollte auch hier das Schaben berücksichtigt werden. 2019-10-27 23.08.38 db.netkeiba.com 2cc6e24ab680.png 2019-10-27 23.08.53 db.netkeiba.com 86af2843684b.png

Code abgeschlossen

keiba_scraping.py


import requests
import lxml.html
import time
from pymongo import MongoClient
import re
import sys

def main(sire_id,n):
    client = MongoClient('localhost', 27017) #Stellen Sie auf dem lokalen Host eine Verbindung zu MongoDB her.
    collection = client.scraping.horse_data #Scraping-Datenbank. Erstellen Sie, wenn nicht
    collection.create_index('key', unique=True) #Erstellen Sie im Schlüsselfeld einen eindeutigen Index, in dem der Schlüssel gespeichert ist, der die Daten eindeutig identifiziert.

    session = requests.Session()

    for i in range(n):
        response = session.get("https://db.netkeiba.com/?pid=horse_list&_sire_id=" + sire_id + "&page=" + str(i))
        response.encoding = response.apparent_encoding #Anscheinende Codierung_Ändern Sie das, was durch Codierung erraten wurde
        urls = scrape_list_page(response) #Rufen Sie eine Liste der URLs der Detailseite ab
        for url in urls:
            key = extract_key(url) #Holen Sie sich die Nummer am Ende der URL als Schlüssel
            h = collection.find_one({'key': key}) #Suchen Sie die Daten des entsprechenden Schlüssels
            if not h: #Wenn es in der DB nicht vorhanden ist
                time.sleep(1) #Laufen Sie jede Sekunde(Entlastung des Akquisitionsstandorts)
                response = session.get(url)#Detailseite abrufen
                horse = scrape_horse_page(response)#Scraping Detailseite
                collection.insert_one(horse)#Speichern Sie die Pferdeinformationen in der DB

def scrape_list_page(response):#Generatorfunktion zum Extrahieren der URL der Detailseite
    html = lxml.html.fromstring(response.text)
    html.make_links_absolute(response.url)
    for a in html.cssselect('#contents_liquid > div > form > table > tr > td.xml.txt_l > a'):
        url = a.get("href")
        yield url

def scrape_horse_page(response):#Detailseite analysieren
    response.encoding = response.apparent_encoding #Geben Sie die Codierung an
    html = lxml.html.fromstring(response.text)

    #Name, aktiv oder gelöscht oben auf der Seite,Sex,Holen Sie sich Informationen zur Haarfarbe
    for title in html.cssselect('#db_main_box > div.db_head.fc > div.db_head_name.fc > div.horse_title'):
        name = parse_name(title.cssselect('h1')[0].text.strip()) #Erhielt einen Pferdenamen. Entfernen Sie zusätzliche leere Zeichen mit Streifen und analysieren Sie_Zum Namen weitergeben
        #Da Aktiv oder Gelöscht, Geschlecht und Haarfarbe Zeichenfolgen sind, die durch Leerzeichen getrennt sind, werden sie durch Teilen geteilt und per Karte in Variablen gespeichert.
        data = title.cssselect('p.txt_01')[0].text.split()
        if len(data) > 2:
            status,gender,color = map(str,data)
        else:
            gender,color = map(str,data) #Da gibt es keine Informationen zu aktiven Peripheriegeräten für lokale Pferde
            status = None

    #Informationen zu Vater, Mutter, Mutter und Vater erhalten Sie am Stammbaum
    for bloodline in html.cssselect('#db_main_box > div.db_main_deta > div > div.db_prof_area_02 > div > dl > dd > table'):
        sire = bloodline.cssselect('tr:nth-child(1) > td:nth-child(1) > a')[0].text
        dam = bloodline.cssselect('tr:nth-child(3) > td.b_fml > a')[0].text
        broodmare_sire = bloodline.cssselect('tr:nth-child(3) > td.b_ml > a')[0].text

    club_info = html.cssselect('#owner_info_td > a') #Rekrutierungspreis für Clubpferde anzeigen
    for data in html.cssselect('#db_main_box > div.db_main_deta > div > div.db_prof_area_02 > table'):
        birthday = data.cssselect('tr:nth-child(1) > td')[0].text #Holen Sie sich Geburtstagsinformationen und konvertieren Sie in Datumstyp
        trainer = data.cssselect('tr:nth-child(2) > td > a')[0].text #Informieren Sie sich über Trainer
        owner = data.cssselect('tr:nth-child(3) > td > a')[0].text #Informationen zum Pferdebesitzer erhalten
        #Für Clubpferde unterhalb des Herstellers::nth-Da sich die Anzahl der Kinder nacheinander verschiebt, Verein_Fügen Sie 1 hinzu, wenn ein Informationselement vorhanden ist
        if len(club_info) > 0:
            breeder = data.cssselect('tr:nth-child(5) > td > a')[0].text #Produzent
            prize_money = data.cssselect('tr:nth-child(8) > td')[0].text.strip().replace(' ','') #Der Preisstreifen entfernt Leerzeichen an beiden Enden, die Replase entfernt Leerzeichen im Text
        else:
            breeder = data.cssselect('tr:nth-child(4) > td > a')[0].text
            prize_money = data.cssselect('tr:nth-child(7) > td')[0].text.strip().replace(' ','')


    horse = {
        'url': response.url,
        'key': extract_key(response.url),
        'name':name,
        'status': status,
        'gender':gender,
        'color':color,
        'birthday':birthday,
        'sire':sire,#Vater
        'dam':dam,#Mutter
        'broodmare_sire':broodmare_sire,#Mutter Vater
        'owner':owner,
        'breeder':breeder,
        'trainer':trainer,
        'prize_money' : prize_money
    }

    return horse

def extract_key(url):
    m = re.search(r'\d{10}', url).group() #Letzte/Gehen Sie mit einem regulären Ausdruck vom Ende der Zeichenkette.
    return m

def parse_name(name):
    m = re.search(r'[\u30A1-\u30FF]+', name).group() #○ Boden oder □ Nehmen Sie nur den Pferdenamen vom Pferd auf dem Boden. Wenn Sie den Teil herausnehmen, der dem Muster des regulären Ausdrucks von Katakana entspricht, k
    return m

if __name__ == "__main__":
    main(sys.argv[1],int(sys.argv[2]))#Rufen Sie die Nummer am Ende der URL des Pferdes ab, für das Sie die Suchergebnisliste des Produktionsstücks aus dem Befehlszeilenargument abrufen möchten, und die Anzahl der Seiten, um das Suchseitenergebnis abzurufen und die Hauptfunktion aufzurufen
python keiba_scraping.py 2002100816 4

Führen Sie die Liste der Deep Impact-Produktionsteile unter der Bedingung aus, dass Sie 4 Seiten erwerben. Wenn Sie die gesamte Sammlung von Pferdedaten aus der Mongo-Shell anzeigen ... mongopng.png Kita━━━━━━ (゜ ∀ ゜) ━━━━━━ !!!!! Sie können auch eingrenzen, indem Sie verschiedene Suchbedingungen angeben mongo2.png

Deshalb ist es vorerst abgeschlossen.

abschließend

Obwohl es kein großes Programm ist, hat es aufgrund von Motivations- und Zeitproblemen lange gedauert, einen Artikel zu veröffentlichen. Als eine Funktion, die ich hinzufügen möchte, denke ich, dass es darum geht, eine rekursive Seite wie ein Deep Impact-Produktionsstück zu diesem Produktionsstück zu machen. Ich würde es begrüßen, wenn Sie sich darauf beziehen könnten oder wenn Sie es interessant finden. Wenn Sie Fragen oder Bedenken haben, hinterlassen Sie bitte einen Kommentar.

Recommended Posts

Ich habe versucht, den Pferderennplatz Teil 2 zu kriechen und abzukratzen
Ich habe versucht, mit Pandas eine Pferderenn-Datenbank zu erstellen
Crawlen und Scraping einer Site mit Mitmproxy
Ich habe versucht, PyEZ und JSNAPy zu verwenden. Teil 2: Ich habe versucht, PyEZ zu verwenden
Pferderennseite Web Scraping mit Python
Ich habe versucht zu kratzen
Ich habe das Schaben mit Selen gelernt, um ein Vorhersagemodell für Pferderennen zu erstellen.
Ich habe versucht, Web-Scraping mit Python und Selen
Python-Scraping Extrahieren Sie die Rennumgebung von der Pferderennseite
Ich habe versucht, die Werbung für die Raubkopien-Website zu kratzen
Python: Ich habe es mit Lügner und Ehrlichkeit versucht
Ich habe versucht, mit Python zu kratzen
Ich habe versucht, mit Python Modebilder und Textsätze zu [kratzen].
[Pferderennen] Ich habe versucht, die Stärke des Rennpferdes zu quantifizieren
Crawlen der Website eines Wertpapierunternehmens
Ich habe mit LightGBM einen Code geschrieben, der die Wiederherstellungsrate von 100% bei der Vorhersage von Pferderennen überschreitet (Teil 2).
Datenrabatfluss für Pferderennen
Ich habe eine Klasse in Python erstellt und versucht, Enten zu tippen
Ich habe versucht, mit Python zu kratzen
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ich habe versucht, PyEZ und JSNAPy zu verwenden. Teil 4: Automatisieren Sie die ISP-Einrichtung mit PyEZ und JSNAPy
Holz kratzen und essen - ich möchte ein gutes Restaurant finden! ~ (Arbeit)
Ich habe versucht, Bulls and Cows mit einem Shell-Programm zu erstellen
Ich habe eine C ++ - Lernseite erstellt
Ich habe versucht, WebScraping mit Python.
Scrapping von Pferderenndaten im Colaboratory
Ich habe versucht, Kanas handschriftliche Zeichenerkennung durchzuführen. Teil 2/3 Datenerstellung und Lernen
Starten Sie einen Webserver mit Bottle and Flask (ich habe auch versucht, Apache zu verwenden)
Ich habe ein Beispiel für den Zugriff auf Salesforce mit Python und Bottle erstellt
Einführung in die KI-Erstellung mit Python! Teil 3 Ich habe versucht, Bilder mit einem Convolutional Neural Network (CNN) zu klassifizieren und vorherzusagen.
Ich habe versucht, einen Linebot zu erstellen (Implementierung)
Ich habe versucht, Konversationsdaten von ASKfm zu kratzen
Ich habe versucht, einen Linebot zu erstellen (Vorbereitung)
Ich habe DSX Desktop installiert und ausprobiert
Ich habe versucht, ○ ✕ mit TensorFlow zu spielen
Ich habe eine funktionale Sprache mit Python ausprobiert
Ich habe versucht, DeepPose mit PyTorch PartⅡ zu implementieren
Ich habe eine Web-API erstellt
Ich habe versucht, Yahoo Wetter zu kratzen (Python Edition)
Ich habe versucht, pipenv zu verwenden, machen Sie sich also eine Notiz
Ich habe versucht, das Webanwendungs-Framework zu vergleichen
Ich habe versucht, ein Auto in 3D zu erkennen
Ich habe versucht, Stoff, Küche und Jinja2 zu kombinieren
Ich habe versucht, einen periodischen Prozess mit CentOS7, Selenium, Python und Chrome durchzuführen
[Python] Ich habe versucht, 100 frühere Fragen zu lösen, die Anfänger und Fortgeschrittene lösen sollten [Teil 5/22]
[Python] Ich habe versucht, 100 frühere Fragen zu lösen, die Anfänger und Fortgeschrittene lösen sollten [Teil 7/22]
Python-Programmierung: Ich habe versucht, Nachrichtenartikel mit Selenium und BeautifulSoup4 abzurufen (zu crawlen)
[Python] Ich habe versucht, 100 frühere Fragen zu lösen, die Anfänger und Fortgeschrittene lösen sollten [Teil 4/22]
[Python] Ich habe versucht, 100 frühere Fragen zu lösen, die Anfänger und Fortgeschrittene lösen sollten [Teil 3/22].
Ein Anfänger des maschinellen Lernens versuchte, mit Python ein Vorhersagemodell für Pferderennen zu erstellen
Ich habe versucht, die 100-Yen-Lagerstätte von Rakuten-Pferderennen (Python / Selen) zu automatisieren.
Ich habe SIF Rank auf ein japanisches Dokument angewendet und versucht, Schlüsselphrasen zu extrahieren
Ich habe versucht, Hanana Oba und Emiri Otani durch tiefes Lernen zu klassifizieren (Teil 2)
[Python] Ich habe versucht, 100 frühere Fragen zu lösen, die Anfänger und Fortgeschrittene lösen sollten [Teil 6/22]
Ich habe versucht, eine einfache Bilderkennungs-API mit Fast API und Tensorflow zu erstellen