Comme le titre l'indique, enregistrez les informations récupérées dans MySQL à l'aide de requêtes et de lxml. Comme il y avait peu de sites qui expliquaient de manière transversale, enregistrez-le sous forme de mémorandum. De toute évidence, le scraping met un fardeau sur le serveur de l'autre partie, il est donc nécessaire de générer des retards et de vérifier robot.txt.
--requests 2.13.0 - BibliothèqueHTTP --lxml 3.7.3 - Bibliothèque XML --PyMySQL 0.7.10 --Pilote MySQL --fake-useragent 0.1.5 --request_header creation library
D'autres bibliothèques couramment utilisées pour le scraping incluent urllib, htmllib, BeautifulSoup et Scrapy. Cependant, cette fois, je suis allé avec cette configuration. Puisque le faux-useragent n'était que dans pip, j'ai utilisé l'environnement pip cette fois.
Grattage du titre d'article de l'article, de l'url du lien vers l'article individuel, du nom de la catégorie et de la date de création de l'article de la catégorie informatique de Yahoo News (http://news.yahoo.co.jp/list/?c=computer).
Quant à la structure de la page, chaque page d'index comporte 20 articles individuels et la page d'index elle-même compte 714 pages. La structure URL de la page d'index est http://news.yahoo.co.jp/list/?c=computer&p=1, comme http://news.yahoo.co.jp/list/?c=computer&p= C'est celui avec le numéro ajouté. Chaque article individuel est divisé en trois types: les articles avec vignettes, les articles sans vignettes et les articles supprimés.
Exemple d'article avec vignette
Exemple d'article sans vignette
Exemple d'article supprimé
lxml utilise le format xPath pour spécifier l'emplacement que vous souhaitez analyser. Utilisez la fonction de vérification de chrome pour obtenir le xPath des informations que vous souhaitez obtenir. Accédez à la page d'index dans Chrome et sélectionnez Valider dans le menu contextuel. Après cela, ouvrez l'onglet html tout en vous référant aux points forts de la page. Lorsque vous atteignez enfin les informations que vous souhaitez extraire, vous pouvez sélectionner ces informations, afficher le menu contextuel et sélectionner Copier> Copier XPath pour obtenir le xPath.
--Exemple d'article avec vignette (premier à partir du haut) --Titre de l'article: // * [@ id = "main"] / div [1] / div [1] / div [4] / ul / li [1] / a / span [2]
Considérez la régularité xPath de chaque élément d'information à partir d'un échantillon de xPath collecté en fonction de la division des articles individuels.
--La position des articles individuels est spécifiée par li [num] à la position numérique à partir du haut. --Span [num] immédiatement après / a / passe à 2,3,3,1,2,2 selon la présence ou l'absence de vignettes. --Pour les articles supprimés, la partie / a devient / div.
Etc. sera considéré. Sur la base de cette considération, nous allons générer le xPath réel et le transmettre à lxml.
requests,fake-useragent
import requests #Obtenir le code HTML par demande GET à l'URL
from fake_useragent import UserAgent #Générer un en-tête
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-objet agent
ran_header = {"User-Agent": ua.random} #Générer un en-tête aléatoire à chaque fois qu'il est appelé
html = requests.get(scraping_url, headers=ran_header) #objet html obtenu par requêtes
html_text = html.text
if html.status_code == 200:
counter_200 += 1
elif html.status_code == 400:
counter_404 += 1
return html_text
L'en-tête des requêtes est généré aléatoirement par fake_useragent. Préparez counter_200
comme compteur lorsque la demande d'obtention des demandes est réussie et counter_404
comme variable globale comme compteur lorsque le traitement final et la demande d'obtention échouent.
lxml
import lxml.html #analyseur XML
#Généré en convertissant le modèle d'objet de document et le format HTML au format xml
def make_dom(html_text):
dom = lxml.html.fromstring(html_text)
return dom
#Reçoit dom et xpath et renvoie du texte
def make_text_from_xpath(dom, xpath):
text = dom.xpath(xpath)[0].text
return text
#Prend dom et xpath et renvoie le lien
def make_link_from_xpath(dom, xpath):
link = dom.xpath(xpath)[0].attrib["href"]
return link
#Le texte que vous souhaitez obtenir est du texte()S'il est inclus dans
def make_text_from_xpath_function(dom, xpath):
text = dom.xpath(xpath)[1]
return text
Vous pouvez créer un DOM (Document Object Model) en passant html au format texte à lxml. Vous pouvez obtenir des informations sur chacun d'eux en transmettant XPath à cet objet. La méthode de spécification de XPath diffère selon le type d'informations. Il semble bon de vérifier à chaque fois la méthode de description XPath. Si vous passez XPath, il sera essentiellement retourné au format liste, vous devez donc vérifier où se trouvent les informations dans la liste en tournant une boucle for, etc.
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)
miniature_link
sera expliqué un peu plus bas.
#Une classe qui résume les informations que vous souhaitez gratter et leurs xpaths, passez d'abord le numéro de l'article individuel par le haut
class Xpath:
def __init__(self, article_num):
self.article_num = article_num
self.info_list = []
#Pour les articles avec des miniatures
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
#Pour les articles sans vignettes
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
#Pour les articles supprimés
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
Créez une classe XPath basée sur la discussion XPath que nous avons faite précédemment.
#Déterminer s'il existe une miniature / un lien pour un article individuel
def check_thumbnail_link(dom, article_num):
#Un tableau montrant la présence ou l'absence de vignettes et de liens
thumbnail_link = [True, True]
#Lancer le xpath de la catégorie d'article sans vignettes et obtenir une erreur si les vignettes existent
try: #Ce n'est pas une erreur, c'est-à-dire que la vignette n'existe pas
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: #Erreur, c'est-à-dire qu'une vignette existe
pass
#Lancer le xpath du lien de l'article avec la vignette, et si le lien n'existe pas, une erreur sera renvoyée
try: #Aucune erreur, c'est-à-dire que le lien existe
make_link_from_xpath(dom, "//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(article_num) + "]/a")
except IndexError: #Erreur, c'est-à-dire que le lien n'existe pas
thumbnail_link[1] = False
return thumbnail_link
Essayez de lancer un XPath et déterminez s'il renvoie une erreur. C'est tout à fait une compétence, alors je pense à une meilleure façon. PyMySQL
$ mysql.server start #Démarrer le serveur MySQL
$ mysql -u root -p #Lancer le curseur MySQL
mysql> show databases; #Vérifiez la base de données
mysql> create database database_name #Créer une base de données
mysql> use database_name; #Sélectionnez la base de données à utiliser
mysql> show tables; #Vérification de la table dans la base de données
mysql> show columns from table_name; #Vérifiez les colonnes du tableau
mysql> select * from table_name; #Afficher tous les éléments du tableau
mysql> delete from table_name; #Supprimer tous les éléments du tableau, utiliser en cas de mauvais grattage
mysql> create table table_name(column_name_1 column_type_1, column_name_2 column_type_1, ...); #Créer une table
#Table à créer cette fois
mysql> create table yahoo_news(page_num int not null,
title varchar(255),
link_num varchar(255),
category varchar(255),
article_time varchar(255));
J'ai créé une base de données nommée scraping et une table nommée yahoo_news. La raison pour laquelle link_num
est de type varchar est que si link_num
commence par 0, 0 disparaît quand il est mis dans le type int.
import pymysql.cursors #Client MySQL
#Informations de connexion MySQL
connection = pymysql.connect(host="localhost",
user="root",
password="hogehoge",
db="scraping",
charset="utf8")
#Un curseur pour lancer une requête et chaque instruction
cur = connection.cursor()
sql_insert = "INSERT INTO yahoo_news VALUES (%s, %s, %s, %s, %s)" #Faire correspondre le nombre de chaînes de substitution avec le nombre de colonnes
sql_check = "SELECT * FROM yahoo_news WHERE page_num = %s"
# page_Vérifiez num et ignorez s'il est inclus dans la base de données
cur.execute(sql_check, page_num)
check_num = cur.fetchall() #Obtenez les informations qui sont revenues
if check_num: #Lorsqu'il ne s'agit pas d'une chaîne vide, c'est-à-dire lorsqu'il est inclus dans la base de données
continue
#Transmettre des informations pour 20 éléments à MySQL
cur.executemany(sql_insert, l_all_get_text) #exécuter plusieurs lors du passage d'une liste d'inclusions de tuple, exécuter lors du passage d'un simple tuple
connection.commit() #Si vous ne vous engagez pas, l'insertion ne sera pas effectuée
#Arrêt du curseur et de la base de données
cur.close()
connection.close()
L'utilisation de la chaîne de substitution «$ s» facilite la création d'instructions. Il était étonnamment bon d'utiliser ʻexecute lors du passage du type int, du type str et du type tuple, et ʻexecutemany
lors du passage du type liste.
# coding: utf-8
import requests #Obtenir le code HTML par demande GET à l'URL
from fake_useragent import UserAgent #Générer un en-tête
import lxml.html #analyseur XML
import pymysql.cursors #Client MySQL
import time #Pour la génération de retard
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-objet agent
ran_header = {"User-Agent": ua.random} #Générer un en-tête aléatoire à chaque fois qu'il est appelé
html = requests.get(scraping_url, headers=ran_header) #objet html obtenu par requêtes
html_text = html.text
if html.status_code == 200:
counter_200 += 1
elif html.status_code == 400:
counter_404 += 1
return html_text
#Généré en convertissant le modèle d'objet de document et le format HTML au format xml
def make_dom(html_text):
dom = lxml.html.fromstring(html_text)
return dom
#Reçoit dom et xpath et renvoie du texte
def make_text_from_xpath(dom, xpath):
text = dom.xpath(xpath)[0].text
return text
#Prend dom et xpath et renvoie le lien
def make_link_from_xpath(dom, xpath):
link = dom.xpath(xpath)[0].attrib["href"]
return link
#Le texte que vous souhaitez obtenir est du texte()S'il est inclus dans
def make_text_from_xpath_function(dom, xpath):
text = dom.xpath(xpath)[1]
return text
#Une classe qui résume les informations que vous souhaitez gratter et leurs xpaths, passez d'abord le numéro de l'article individuel par le haut
class Xpath:
def __init__(self, article_num):
self.article_num = article_num
self.info_list = []
#Pour les articles avec des miniatures
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
#Pour les articles sans vignettes
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
#Pour les articles supprimés
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
#Déterminer s'il existe une miniature / un lien pour un article individuel
def check_thumbnail_link(dom, article_num):
#Un tableau montrant la présence ou l'absence de vignettes et de liens
thumbnail_link = [True, True]
#Lancer le xpath de la catégorie d'article sans vignettes et obtenir une erreur si les vignettes existent
try: #Ce n'est pas une erreur, c'est-à-dire que la vignette n'existe pas
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: #Erreur, c'est-à-dire qu'une vignette existe
pass
#Lancer le xpath du lien de l'article avec la vignette, et si le lien n'existe pas, une erreur sera renvoyée
try: #Aucune erreur, c'est-à-dire que le lien existe
make_link_from_xpath(dom, "//*[@id=\"main\"]/div[1]/div[1]/div[4]/ul/li[" + str(article_num) + "]/a")
except IndexError: #Erreur, c'est-à-dire que le lien n'existe pas
thumbnail_link[1] = False
return thumbnail_link
#opération d'exploration, dom et page_num et article_Reçoit num et renvoie un tuple résumant les informations de scraping
def crawling(dom, page_num, article_num):
list_get_text = [] #Liste de collecte d'informations pour un article, le type de tuple est utilisé pour l'insertion dans MySQL, donc convertissez-le plus tard
list_get_text.append(page_num)
#Créer un objet Xpath
xpath = Xpath(article_num)
#Vérifiez les vignettes et les liens, les informations_Générer une liste
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: #Pour lien
get_link = make_link_from_xpath(dom, xpath_info)
l_get_link = get_link.split("/")
list_get_text.append(l_get_link[4]) #L'index du lien ici est en fait un débogage_check_where_link_number()Découvrez dans
elif index == 1 and thumbnail_link[1] is False:
list_get_text.append(None) #NULL dans MySQL est passé en tant que type None
else: #Pour le texte
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
#Informations de connexion MySQL
connection = pymysql.connect(host="localhost",
user="root",
password="hogehoge",
db="scraping",
charset="utf8")
#Un curseur pour lancer une requête et chaque instruction
cur = connection.cursor()
sql_insert = "INSERT INTO yahoo_news VALUES (%s, %s, %s, %s, %s)" #Faire correspondre le nombre de chaînes de substitution avec le nombre de colonnes
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_Vérifiez num et ignorez s'il est inclus dans la base de données
cur.execute(sql_check, page_num)
check_num = cur.fetchall() #Obtenez les informations qui sont revenues
if check_num: #Lorsqu'il ne s'agit pas d'une chaîne vide, c'est-à-dire lorsqu'il est inclus dans la base de données
continue
#Terminer le traitement
if counter_404 == 5:
break
l_all_get_text = [] #Liste de collecte d'informations pour 20 articles
#Diverses générations et accès à l'url se font également ici
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)
#Transmettre des informations pour 20 éléments à MySQL
cur.executemany(sql_insert, l_all_get_text) #exécuter plusieurs lors du passage d'une liste d'inclusions de tuple, exécuter lors du passage d'un simple tuple
connection.commit() #Si vous ne vous engagez pas, l'insertion ne sera pas effectuée
#Génération de retard pour chaque exploration
time.sleep(3) #Spécifié en secondes
#Retarder la génération pour chaque exploration plusieurs fois
if counter_200 == 10:
counter_200 = 0
time.sleep(60) #Spécifié en secondes
#Arrêt du curseur et de la base de données
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()
Si quoi que ce soit, il est devenu une mise en œuvre pour créer un plan de site dans le site. Il semble que chaque page individuelle devrait être accédée en utilisant le link_num
obtenu par ce script.
Il serait utile que vous signaliez des erreurs ou des améliorations.
Recommended Posts