Speichern Sie, wie der Titel schon sagt, die gescrapten Informationen in MySQL mithilfe von Anfragen und lxml. Da es nur wenige Websites gab, die im Querschnitt erklärt wurden, sollten Sie dies als Memorandum aufzeichnen. Offensichtlich belastet das Scraping den Server des anderen Teilnehmers, daher müssen Verzögerungen generiert und robot.txt überprüft werden.
--requests 2.13.0 --HTTP Bibliothek --lxml 3.7.3 --XML Bibliothek --PyMySQL 0.7.10 --MySQL-Treiber --fake-useragent 0.1.5 --request_header Erstellungsbibliothek
Andere häufig verwendete Bibliotheken zum Scraping sind urllib, htmllib, BeautifulSoup und Scrapy. Diesmal habe ich mich jedoch für diese Konfiguration entschieden. Da sich der Fake-Useragent nur in pip befand, habe ich diesmal die pip-Umgebung verwendet.
Verschrotten des Artikeltitels des Artikels, der URL des Links zum einzelnen Artikel, des Kategorienamens und des Erstellungsdatums des Artikels aus der IT-Kategorie von Yahoo News (http://news.yahoo.co.jp/list/?c=computer).
In Bezug auf die Seitenstruktur enthält jede Indexseite 20 einzelne Artikel und die Indexseite selbst 714 Seiten. Die URL-Struktur der Indexseite lautet http://news.yahoo.co.jp/list/?c=computer&p=1, wie http://news.yahoo.co.jp/list/?c=computer&p=. Es ist das mit der hinzugefügten Nummer. Jeder einzelne Artikel ist in drei Typen unterteilt: Artikel mit Miniaturansichten, Artikel ohne Miniaturansichten und gelöschte Artikel.
Artikelbeispiel mit Miniaturansicht
Artikelbeispiel ohne Miniaturansicht
Beispiel für einen gelöschten Artikel
lxml verwendet das xPath-Format, um den Speicherort anzugeben, den Sie analysieren möchten. Verwenden Sie die Chrome-Überprüfungsfunktion als Methode, um den xPath der Informationen abzurufen, die Sie erhalten möchten. Gehen Sie zur Indexseite in Chrome und wählen Sie im Kontextmenü die Option Validieren. Öffnen Sie danach die Registerkarte "HTML", während Sie auf die Markierungen auf der Seite verweisen. Wenn Sie endlich die Informationen erreicht haben, die Sie kratzen möchten, können Sie diese Informationen auswählen, das Kontextmenü aufrufen und Kopieren> XPath kopieren auswählen, um den xPath zu erhalten.
Berücksichtigen Sie die xPath-Regelmäßigkeit jeder Information aus einer Stichprobe von xPath, die basierend auf der Aufteilung einzelner Artikel gesammelt wurde.
--Die Position einzelner Artikel wird durch li [num] an der numth Position von oben angegeben. --Span [num] unmittelbar nach / a / ändert sich je nach Vorhandensein oder Fehlen von Miniaturansichten auf 2,3,3,1,2,2.
Usw. wird berücksichtigt. Basierend auf dieser Überlegung werden wir den tatsächlichen xPath generieren und an lxml übergeben.
requests,fake-useragent
import requests #Holen Sie sich HTML per GET-Anfrage zur URL
from fake_useragent import UserAgent #Header generieren
def make_scraping_url(page_num):
scraping_url = "http://news.yahoo.co.jp/list/?c=computer&p=" + str(page_num)
return scraping_url
counter_200 = 0
counter_404 = 0
def make_html_text(scraping_url):
global counter_200
global counter_404
ua = UserAgent() # fakeuser-Agentenobjekt
ran_header = {"User-Agent": ua.random} #Generieren Sie bei jedem Aufruf einen zufälligen Header
html = requests.get(scraping_url, headers=ran_header) #HTML-Objekt durch Anfragen erhalten
html_text = html.text
if html.status_code == 200:
counter_200 += 1
elif html.status_code == 400:
counter_404 += 1
return html_text
Der Header der Anforderungen wird zufällig von fake_useragent generiert. Bereiten Sie "counter_200" als globale Variable als Zähler vor, wenn die Anforderung zum Abrufen von Anforderungen erfolgreich ist, und als Zähler, wenn der Beendigungsprozess und die Anforderung zum Abrufen nicht erfolgreich sind. lxml
import lxml.html #XML-Parser
#Wird durch Konvertieren von Document Object Model und HTML in das XML-Format generiert
def make_dom(html_text):
dom = lxml.html.fromstring(html_text)
return dom
#Empfängt dom und xpath und gibt Text zurück
def make_text_from_xpath(dom, xpath):
text = dom.xpath(xpath)[0].text
return text
#Nimmt dom und xpath und gibt den Link zurück
def make_link_from_xpath(dom, xpath):
link = dom.xpath(xpath)[0].attrib["href"]
return link
#Der Text, den Sie erhalten möchten, ist Text()Wenn es in enthalten ist
def make_text_from_xpath_function(dom, xpath):
text = dom.xpath(xpath)[1]
return text
Sie können ein DOM (Documents Object Model) erstellen, indem Sie HTML im Textformat an lxml übergeben. Sie können Informationen zu jedem Objekt abrufen, indem Sie XPath an dieses Objekt übergeben. Die Methode zur Angabe von XPath hängt von der Art der Informationen ab. Es scheint gut, die XPath-Beschreibungsmethode jedes Mal zu überprüfen. Wenn Sie XPath bestehen, wird es grundsätzlich im Listenformat zurückgegeben. Sie müssen also eine for-Schleife usw. drehen, um zu überprüfen, wo sich die Informationen in der Liste befinden.
def debug_check_where_link_number(page_num, article_num):
scraping_url = make_scraping_url(page_num)
html_text = make_html_text(scraping_url)
dom = make_dom(html_text)
xpath = Xpath(article_num)
thumbnail_link = check_thumbnail_link(dom, article_num)
if thumbnail_link[0] is True and thumbnail_link[1] is True:
xpath.with_thumbnail()
elif thumbnail_link[0] is False:
xpath.no_thumbnail()
elif thumbnail_link[1] is False:
xpath.deleted()
get_link = make_link_from_xpath(dom, xpath.info_list[1])
l_get_link = get_link.split("/")
counter = 0
for item in l_get_link:
print(counter)
counter += 1
print(item)
thumbnail_link
wird etwas weiter unten erklärt.
#Eine Klasse, die die Informationen, die Sie kratzen möchten, und ihre xpaths zusammenfasst, übergibt zuerst die Nummer des einzelnen Artikels von oben
class Xpath:
def __init__(self, article_num):
self.article_num = article_num
self.info_list = []
#Für Artikel mit Miniaturansichten
def with_thumbnail(self):
self.info_list = ["//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[2]", # title
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a", # link
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[3]/span[1]", # category
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[3]/span[2]"] # timestamp
#Für Artikel ohne Thumbnails
def no_thumbnail(self):
self.info_list = ["//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[1]", # title
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a", # link
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[2]/span[1]", # category
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[2]/span[2]"] # timestamp
#Für gelöschte Artikel
def deleted(self):
self.info_list = ["//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/div/span[1]", # title
None, # link
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/div/span[2]/span[1]", # category
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/div/span[2]/span[2]"] # timestamp
Erstellen Sie eine XPath-Klasse basierend auf der zuvor durchgeführten XPath-Diskussion.
#Bestimmen Sie das Vorhandensein oder Fehlen einzelner Artikel-Miniaturansichten und -Links
def check_thumbnail_link(dom, article_num):
#Ein Array, das das Vorhandensein oder Fehlen von Miniaturansichten und Links anzeigt
thumbnail_link = [True, True]
#Werfen Sie den xpath der Artikelkategorie ohne Miniaturansichten und erhalten Sie eine Fehlermeldung, wenn die Miniaturansichten vorhanden sind
try: #Kein Fehler, das heißt, die Miniaturansicht ist nicht vorhanden
make_text_from_xpath(dom, "//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(article_num) + "]/a/span[2]/span[1]")
thumbnail_link[0] = False
except IndexError: #Fehler, d. H. Miniaturansicht vorhanden
pass
#Werfen Sie den x-Pfad des Links des Artikels mit der Miniaturansicht. Wenn der Link nicht vorhanden ist, wird ein Fehler zurückgegeben
try: #Es liegt kein Fehler vor, d. H. Es besteht eine Verbindung
make_link_from_xpath(dom, "//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(article_num) + "]/a")
except IndexError: #Fehler, dh Link existiert nicht
thumbnail_link[1] = False
return thumbnail_link
Versuchen Sie, einen XPath zu werfen, und stellen Sie fest, ob ein Fehler zurückgegeben wird. Es ist eine ziemliche Fähigkeit, also denke ich über einen besseren Weg nach. PyMySQL
$ mysql.server start #Starten Sie den MySQL-Server
$ mysql -u root -p #Starten Sie den MySQL-Cursor
mysql> show databases; #Überprüfen Sie die Datenbank
mysql> create database database_name #Datenbank erstellen
mysql> use database_name; #Wählen Sie die zu verwendende Datenbank aus
mysql> show tables; #Überprüfen der Tabelle in der Datenbank
mysql> show columns from table_name; #Überprüfen Sie die Spalten in der Tabelle
mysql> select * from table_name; #Alle Elemente in der Tabelle anzeigen
mysql> delete from table_name; #Löschen Sie alle Elemente in der Tabelle, verwenden Sie bei falschem Scraping
mysql> create table table_name(column_name_1 column_type_1, column_name_2 column_type_1, ...); #Eine Tabelle erstellen
#Tabelle, die dieses Mal erstellt werden soll
mysql> create table yahoo_news(page_num int not null,
title varchar(255),
link_num varchar(255),
category varchar(255),
article_time varchar(255));
Ich habe eine Datenbank mit dem Namen Scraping und eine Tabelle mit dem Namen yahoo_news erstellt. Der Grund, warum link_num
vom Typ varchar ist, ist, dass wenn link_num
mit 0 beginnt, 0 verschwindet, wenn es in den Typ int gesetzt wird.
import pymysql.cursors #MySQL-Client
#MySQL-Verbindungsinformationen
connection = pymysql.connect(host="localhost",
user="root",
password="hogehoge",
db="scraping",
charset="utf8")
#Ein Cursor zum Auslösen einer Abfrage und jeder Anweisung
cur = connection.cursor()
sql_insert = "INSERT INTO yahoo_news VALUES (%s, %s, %s, %s, %s)" #Passen Sie die Anzahl der Ersetzungszeichenfolgen und die Anzahl der Spalten an
sql_check = "SELECT * FROM yahoo_news WHERE page_num = %s"
# page_Überprüfen Sie num und überspringen Sie, ob es in der Datenbank enthalten ist
cur.execute(sql_check, page_num)
check_num = cur.fetchall() #Holen Sie sich die Informationen, die zurückkamen
if check_num: #Wenn es sich nicht um eine leere Zeichenfolge handelt, dh wenn sie in der Datenbank enthalten ist
continue
#Übergeben Sie Informationen für 20 Elemente an MySQL
cur.executemany(sql_insert, l_all_get_text) #Führen Sie viele aus, wenn Sie eine Liste von Tupeleinschlüssen übergeben. Führen Sie diese aus, wenn Sie nur ein Tupel übergeben
connection.commit() #Wenn Sie kein Commit durchführen, wird das Einfügen nicht durchgeführt
#Cursor- und Datenbankbeendigung
cur.close()
connection.close()
Die Verwendung der Substitutionszeichenfolge $ s
erleichtert das Erstellen von Anweisungen. Es war überraschend gut, "execute" beim Übergeben von int type, str type und tuple type und "executeemany" beim Übergeben von list type zu verwenden.
# coding: utf-8
import requests #Holen Sie sich HTML per GET-Anfrage zur URL
from fake_useragent import UserAgent #Header generieren
import lxml.html #XML-Parser
import pymysql.cursors #MySQL-Client
import time #Zur Verzögerungserzeugung
def make_scraping_url(page_num):
scraping_url = "http://news.yahoo.co.jp/list/?c=computer&p=" + str(page_num)
return scraping_url
counter_200 = 0
counter_404 = 0
def make_html_text(scraping_url):
global counter_200
global counter_404
ua = UserAgent() # fakeuser-Agentenobjekt
ran_header = {"User-Agent": ua.random} #Generieren Sie bei jedem Aufruf einen zufälligen Header
html = requests.get(scraping_url, headers=ran_header) #HTML-Objekt durch Anfragen erhalten
html_text = html.text
if html.status_code == 200:
counter_200 += 1
elif html.status_code == 400:
counter_404 += 1
return html_text
#Wird durch Konvertieren von Document Object Model und HTML in das XML-Format generiert
def make_dom(html_text):
dom = lxml.html.fromstring(html_text)
return dom
#Empfängt dom und xpath und gibt Text zurück
def make_text_from_xpath(dom, xpath):
text = dom.xpath(xpath)[0].text
return text
#Nimmt dom und xpath und gibt den Link zurück
def make_link_from_xpath(dom, xpath):
link = dom.xpath(xpath)[0].attrib["href"]
return link
#Der Text, den Sie erhalten möchten, ist Text()Wenn es in enthalten ist
def make_text_from_xpath_function(dom, xpath):
text = dom.xpath(xpath)[1]
return text
#Eine Klasse, die die Informationen, die Sie kratzen möchten, und ihre xpaths zusammenfasst, übergibt zuerst die Nummer des einzelnen Artikels von oben
class Xpath:
def __init__(self, article_num):
self.article_num = article_num
self.info_list = []
#Für Artikel mit Miniaturansichten
def with_thumbnail(self):
self.info_list = ["//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[2]", # title
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a", # link
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[3]/span[1]", # category
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[3]/span[2]"] # timestamp
#Für Artikel ohne Thumbnails
def no_thumbnail(self):
self.info_list = ["//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[1]", # title
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a", # link
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[2]/span[1]", # category
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/a/span[2]/span[2]"] # timestamp
#Für gelöschte Artikel
def deleted(self):
self.info_list = ["//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/div/span[1]", # title
None, # link
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/div/span[2]/span[1]", # category
"//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(self.article_num) + "]/div/span[2]/span[2]"] # timestamp
#Bestimmen Sie das Vorhandensein oder Fehlen einzelner Artikel-Miniaturansichten und -Links
def check_thumbnail_link(dom, article_num):
#Ein Array, das das Vorhandensein oder Fehlen von Miniaturansichten und Links anzeigt
thumbnail_link = [True, True]
#Werfen Sie den xpath der Artikelkategorie ohne Miniaturansichten und erhalten Sie eine Fehlermeldung, wenn die Miniaturansichten vorhanden sind
try: #Kein Fehler, das heißt, die Miniaturansicht ist nicht vorhanden
make_text_from_xpath(dom, "//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(article_num) + "]/a/span[2]/span[1]")
thumbnail_link[0] = False
except IndexError: #Fehler, d. H. Miniaturansicht vorhanden
pass
#Werfen Sie den x-Pfad des Links des Artikels mit der Miniaturansicht. Wenn der Link nicht vorhanden ist, wird ein Fehler zurückgegeben
try: #Es liegt kein Fehler vor, d. H. Es besteht eine Verbindung
make_link_from_xpath(dom, "//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(article_num) + "]/a")
except IndexError: #Fehler, dh Link existiert nicht
thumbnail_link[1] = False
return thumbnail_link
#Crawling-Vorgang, Dom und Seite_num und Artikel_Erhält num und gibt ein Tupel zurück, das die Scraping-Informationen zusammenfasst
def crawling(dom, page_num, article_num):
list_get_text = [] #Liste zum Sammeln von Informationen für einen Artikel. Der Tupeltyp wird zum Einfügen in MySQL verwendet. Konvertieren Sie ihn daher später
list_get_text.append(page_num)
#Erstellen Sie ein Xpath-Objekt
xpath = Xpath(article_num)
#Suchen Sie nach Miniaturansichten und Links, Informationen_Liste erstellen
thumbnail_link = check_thumbnail_link(dom, article_num)
if thumbnail_link[0] is True and thumbnail_link[1] is True:
xpath.with_thumbnail()
elif thumbnail_link[0] is False:
xpath.no_thumbnail()
elif thumbnail_link[1] is False:
xpath.deleted()
for index, xpath_info in enumerate(xpath.info_list):
if index == 1 and thumbnail_link[1] is True: #Für den Link
get_link = make_link_from_xpath(dom, xpath_info)
l_get_link = get_link.split("/")
list_get_text.append(l_get_link[4]) #Der Index des Links hier ist tatsächlich debug_check_where_link_number()Finden Sie es heraus in
elif index == 1 and thumbnail_link[1] is False:
list_get_text.append(None) #NULL in MySQL wird als None-Typ übergeben
else: #Für Text
get_text = make_text_from_xpath(dom, xpath_info)
list_get_text.append(get_text)
tuple_get_text = tuple(list_get_text)
return tuple_get_text
#MySQL-Verbindungsinformationen
connection = pymysql.connect(host="localhost",
user="root",
password="hogehoge",
db="scraping",
charset="utf8")
#Ein Cursor zum Auslösen einer Abfrage und jeder Anweisung
cur = connection.cursor()
sql_insert = "INSERT INTO yahoo_news VALUES (%s, %s, %s, %s, %s)" #Passen Sie die Anzahl der Ersetzungszeichenfolgen und die Anzahl der Spalten an
sql_check = "SELECT * FROM yahoo_news WHERE page_num = %s"
def main():
global counter_200
start_page = 1
end_page = 5
for page_num in range(start_page, end_page + 1):
# page_Überprüfen Sie num und überspringen Sie, ob es in der Datenbank enthalten ist
cur.execute(sql_check, page_num)
check_num = cur.fetchall() #Holen Sie sich die Informationen, die zurückkamen
if check_num: #Wenn es sich nicht um eine leere Zeichenfolge handelt, dh wenn sie in der Datenbank enthalten ist
continue
#Verarbeitung beenden
if counter_404 == 5:
break
l_all_get_text = [] #Liste zum Sammeln von Informationen für 20 Artikel
#Hier werden auch verschiedene Generierungen und der Zugriff auf URLs durchgeführt
scraping_url = make_scraping_url(page_num)
html_text = make_html_text(scraping_url)
dom = make_dom(html_text)
for article_num in range(1, 21):
tuple_get_text = crawling(dom, page_num, article_num)
l_all_get_text.append(tuple_get_text)
#Übergeben Sie Informationen für 20 Elemente an MySQL
cur.executemany(sql_insert, l_all_get_text) #Führen Sie viele aus, wenn Sie eine Liste von Tupeleinschlüssen übergeben. Führen Sie diese aus, wenn Sie nur ein Tupel übergeben
connection.commit() #Wenn Sie kein Commit durchführen, wird das Einfügen nicht durchgeführt
#Verzögerungsgenerierung für jedes Crawlen
time.sleep(3) #In Sekunden angegeben
#Verzögerungsgenerierung für jedes mehrfache Crawlen
if counter_200 == 10:
counter_200 = 0
time.sleep(60) #In Sekunden angegeben
#Cursor- und Datenbankbeendigung
cur.close()
connection.close()
def debug_check_where_link_number(page_num, article_num):
scraping_url = make_scraping_url(page_num)
html_text = make_html_text(scraping_url)
dom = make_dom(html_text)
xpath = Xpath(article_num)
thumbnail_link = check_thumbnail_link(dom, article_num)
if thumbnail_link[0] is True and thumbnail_link[1] is True:
xpath.with_thumbnail()
elif thumbnail_link[0] is False:
xpath.no_thumbnail()
elif thumbnail_link[1] is False:
xpath.deleted()
get_link = make_link_from_xpath(dom, xpath.info_list[1])
l_get_link = get_link.split("/")
counter = 0
for item in l_get_link:
print(counter)
counter += 1
print(item)
if __name__ == "__main__":
main()
Wenn überhaupt, wurde es zu einer Implementierung, eine Sitemap innerhalb der Site zu erstellen. Es scheint, dass auf jede einzelne Seite mit der von diesem Skript erhaltenen link_num
zugegriffen werden sollte.
Es wäre hilfreich, wenn Sie auf Fehler oder Verbesserungen hinweisen könnten.
Recommended Posts