Je suis allé à PyCon 2016 le 20/09 et le 21.
J'écoutais la conférence en cherchant le sujet de l'étude de Python 3 pour diverses raisons, mais Introduction à Web Crawler Made with Python Le "** Scrapy **" introduit dans était apparemment intéressant, et il était juste compatible avec Python3, j'ai donc décidé de créer un robot d'exploration avec Python3.
Cliquez ici pour la vidéo de la conférence
«J'aime la manière de toucher et de comprendre plutôt que la théorie, donc c'est beaucoup de choses diverses. «Parce qu'il est analphabète, je pense que ce sera difficile à comprendre. ――Pour cette raison, je pense qu'il y a beaucoup de choses qui vous donnent envie de le lire, mais comprenez s'il vous plaît!
Cette fois, j'ai récupéré le nom du magasin de ramen près de l'entreprise **, le score ** et les ** coordonnées ** du ** journal des repas ** avec Scrapy, et ce n'est pas amusant de simplement les récupérer, alors J'ai essayé de tracer sur une carte en une seule fois en utilisant l'API Javascript. (Il a été confirmé que l'exploration n'est pas interdite dans ** robots.txt ** du journal de consommation au cas où)
La configuration est simple.
Le flux est comme ça ① Utilisez Scrapy pour récupérer ** nom du magasin **, ** score **, ** latitude / longitude ** à partir du ** journal alimentaire **. ② Enregistrez les informations du magasin dans un fichier. ③ Accédez au serveur depuis le navigateur. ④ django (+ djang-gmapi) lit les informations du magasin, les intègre dans le modèle Jinja afin qu'il appelle l'API Javascirpt et la renvoie. ⑤ Affichez Google Map avec Javascript.
Il s'est avéré être quelque chose comme ça! (Le nombre de cas a été réduit à 1/5 pour faciliter la visualisation.) Les marqueurs sont rouges lorsque le score est de 3,5 ou plus, blancs lorsque le score est de 3,0 ou moins et jaunes entre les deux.
Comme prévu, il y a de nombreux magasins de ramen avec des scores élevés devant la gare d'Ogikubo / Koenji ...! Un magasin se trouve à quelques pas de la gare de Nakano.
Je rampe et rampe comme ça.
Vous pouvez obtenir le "nom du magasin" et les "points" dans la liste affichée par 20 éléments, mais uniquement la "latitude et longitude" Je ne peux l'obtenir qu'à partir des informations détaillées de chaque boutique, je vais donc l'obtenir à partir de là. Après avoir terminé à partir de 20 cas, j'irai chercher les 20 prochains cas.
L'intervalle de collecte est à peu près le même que manuel (10 secondes). ** Exploration gentleman **. La structure de l'URL du journal alimentaire est simple, donc si vous modifiez l'URL de base (start_urls), Il semble que l'exploration et la cartographie peuvent être effectuées avec des listes autres que des ramen, des lieux autres que Tokyo et divers modèles.
・ Ubuntu 16.04.1 ・ Python 3.5.2 ・ Scrapy 1.2.0 * Installer avec pip ・ Django 1.8 ・ Django-gmapi https://bitbucket.org/dbinit/django-gmapi/
Selon la présentatrice de la conférence, Mme Makahi, il semblait préférable d'installer Ubuntu avec apt-get. Python 3 Scrapy peut-il encore être abandonné par apt? Il semblait que, alors j'ai installé Scrapy avec pip. Pour l'instant, je peux le déplacer sans aucun problème.
Ceci est un extrait de la partie Spider qui est au cœur de l'exploration. J'ai utilisé Beutiful Soup pour l'analyse.
tabelogcrawl/spiders/tlspider.py
# -*- coding: utf-8 -*-
from urllib.parse import urlparse, parse_qs
from datetime import datetime
import pytz
import scrapy
from scrapy.contrib.spiders import CrawlSpider
from bs4 import BeautifulSoup
from tabelogcrawl.items import TabelogcrawlItem
#Combien d'articles à obtenir par page(Réglé sur 1 lors de la vérification du fonctionnement)
LIMIT_GET_PER_PAGE = 20
class TLSpider(CrawlSpider):
name = "tlspider"
allowed_domains = ["tabelog.com"]
start_urls = (
'https://tabelog.com/tokyo/A1319/rstLst/ramen/1/?Srt=D&SrtT=rt&sort_mode=1',
)
def parse(self, response):
#Extraire les informations du magasin et stocker les scores de la liste.
soup = BeautifulSoup(response.body, "html.parser")
summary_list = soup.find_all("a", class_="cpy-rst-name")
score_list = soup.find_all(
"span", class_="list-rst__rating-val", limit=LIMIT_GET_PER_PAGE)
for summary, score in zip(summary_list, score_list):
#Stockez les informations nécessaires pour chaque magasin dans TabelogcrawlItem.
jstnow = pytz.timezone(
'Asia/Tokyo').localize(datetime.now()).strftime('%Y/%m/%d')
item = TabelogcrawlItem()
item['date'] = jstnow
item['name'] = summary.string
item['score'] = score.string
href = summary["href"]
item['link'] = href
#Pour obtenir la latitude et la longitude du magasin
#La page de détails est également explorée et stockée dans TabelogcrawlItem.
request = scrapy.Request(
href, callback=self.parse_child)
request.meta["item"] = item
yield request
#page suivante.
soup = BeautifulSoup(response.body, "html.parser")
next_page = soup.find(
'a', class_="page-move__target--next")
if next_page:
href = next_page.get('href')
yield scrapy.Request(href, callback=self.parse)
def parse_child(self, response):
#Extrayez la latitude et la longitude du magasin.
soup = BeautifulSoup(response.body, "html.parser")
g = soup.find("img", class_="js-map-lazyload")
longitude, latitude = parse_qs(
urlparse(g["data-original"]).query)["center"][0].split(",")
item = response.meta["item"]
item['longitude'] = longitude
item['latitude'] = latitude
return item
Pour Django, la partie vue est extraite. La partie où la couleur est décidée en fonction du score est appropriée, je voudrais donc la colorer un peu mieux par normalisation, etc.
tabelogmap/gmapi/views.py
# -*- coding: utf-8 -*-
import codecs
import ast
from django import forms
from django.shortcuts import render_to_response
from gmapi import maps
from gmapi.forms.widgets import GoogleMap
SAVE_FILE = "../tabelog_data.txt"
class MapForm(forms.Form):
map = forms.Field(
widget=GoogleMap(
attrs={'width': 1850, 'height': 900}))
def index(request):
json_path = SAVE_FILE
raw_list = codecs.open(json_path, "r", encoding="utf-8").read().split("\n")
gmap = maps.Map(opts={
'center': maps.LatLng(35.70361991852944, 139.64842779766255),
'mapTypeId': maps.MapTypeId.ROADMAP,
'zoom': 15,
'mapTypeControlOptions': {
'style': maps.MapTypeControlStyle.DROPDOWN_MENU
},
})
info = maps.InfoWindow({
'content': 'Délinquance à Ramen',
'disableAutoPan': True
})
for raw_data in raw_list:
try:
json_data = ast.literal_eval(raw_data)
except:
continue
if float(json_data["score"]) > 3.5:
color = "FF776B"
elif float(json_data["score"]) > 3.0:
color = "FFBB00"
else:
color = "FFFFFF"
marker_info = {
'map': gmap,
'position': maps.LatLng(
float(json_data["longitude"]),
float(json_data["latitude"])),
"label": "%s(%s)" % (
json_data["name"],
json_data["score"]),
"color": color
}
marker = maps.Marker(opts=marker_info)
maps.event.addListener(marker, 'mouseover', 'myobj.markerOver')
maps.event.addListener(marker, 'mouseout', 'myobj.markerOut')
info.open(gmap, marker)
context = {'form': MapForm(initial={'map': gmap})}
return render_to_response('index.html', context)
Scrapy est facile à utiliser. On a l'impression qu'il cache le traitement de la couche basse d'une bonne manière. Ce sera amusant si vous pouvez utiliser la fonction de planification, etc. d'une bonne manière. C'était si facile que je ne pouvais pas étudier Python3, mais lol
Au contraire, django-gmapi ne supportait pas Python3, donc Je l'ai déplacé en le convertissant avec 2to3, mais cela a pris un peu plus de temps ... Je sais que Python3 n'est pas trop effrayant, mais j'ai encore besoin d'étudier un peu.
Recommended Posts