J'ai créé un environnement avec Docker pour enregistrer les informations de tendance Qiita. Fondamentalement, si vous démarrez le conteneur, le processus de scraping s'exécutera de votre propre chef tous les jours et les informations de tendance converties en JSON seront enregistrées. Cet article est recommandé aux personnes suivantes.
――Je veux analyser la tendance de Qiita ――Je veux étudier un peu Python --Docker, je veux le toucher un instant
--author (liste des auteurs tendance) --list (liste des articles de tendance --tag (liste des balises attachées aux articles de tendance
Le contenu du JSON réellement enregistré est le suivant.
Liste des noms d'utilisateur des auteurs.
[
"uhyo",
"suin",
"Yz_4230",
"atskimura",
"pineappledreams",
"Amanokawa",
"k_shibusawa",
"minakawa-daiki",
"morry_48",
"c60evaporator",
"takuya_tsurumi",
"TomoEndo",
"yhatt",
"CEML",
"moritalous",
"svfreerider",
"daisukeoda",
"karaage0703",
"tommy19970714",
"tyru",
"galileo15640215",
"keitah",
"mocapapa",
"akeome",
"ssssssssok1",
"yuno_miyako",
"katzueno",
"cometscome_phys",
"mpyw",
"akane_kato"
]
list
: Obtenez une liste d'articles qui ont évolué vers QiitaLes informations suivantes sont produites.
--UUID de l'article (ID de l'article) --Le titre de l'article
[
{
"article_id":"e66cbca2f582e81d5b16",
"article_title":"Let'Serveur proxy qui bloque les pages Web à l'aide de s Encrypt",
"article_url":"https://qiita.com/uhyo/items/e66cbca2f582e81d5b16",
"author_name":"uhyo",
"likes":66,
"tag_list":[
{
"tag_link":"/tags/javascript",
"tag_name":"JavaScript"
},
{
"tag_link":"/tags/node.js",
"tag_name":"Node.js"
},
{
"tag_link":"/tags/proxy",
"tag_name":"proxy"
},
{
"tag_link":"/tags/https",
"tag_name":"HTTPS"
},
{
"tag_link":"/tags/letsencrypt",
"tag_name":"letsencrypt"
}
]
},
{
"article_id":"83ebaf96caa2c13c8b2f",
"article_title":"Créer un économiseur d'écran macOS avec HTML / CSS / JS(Aucune compétence Swift requise)",
"article_url":"https://qiita.com/suin/items/83ebaf96caa2c13c8b2f",
"author_name":"suin",
"likes":60,
"tag_list":[
{
"tag_link":"/tags/html",
"tag_name":"HTML"
},
{
"tag_link":"/tags/css",
"tag_name":"CSS"
},
{
"tag_link":"/tags/javascript",
"tag_name":"JavaScript"
},
{
"tag_link":"/tags/macos",
"tag_name":"macos"
}
]
}
]
La tendance de Qiita est mise à jour deux fois par jour à 17 h 17 tous les jours, mais comme les articles ne changent pas tellement, je ne l'exécuterai qu'une fois par jour.
tag
: récupère les balises attachées aux articles qui ont évolué vers Qiita[
{
"tag_link":"/tags/python",
"tag_name":"Python"
},
{
"tag_link":"/tags/r",
"tag_name":"R"
},
{
"tag_link":"/tags/%e6%a9%9f%e6%a2%b0%e5%ad%a6%e7%bf%92",
"tag_name":"Apprentissage automatique"
}
]
Les balises sont également acquises dans la liste d'articles ci-dessus, mais comme ce sont des balises liées à un article, elles seront dupliquées si la même balise est attachée à différents articles. Par conséquent, nous avons décidé d'omettre les balises en double et d'enregistrer uniquement les balises avec des tendances dans une liste.
Nous allons créer un environnement Docker simple. La structure du répertoire ressemble à ce qui suit.
├── batch
│ └── py
│ └── article.py
├── docker
│ └── python
│ ├── Dockerfile
│ ├── etc
│ │ └── cron.d
│ │ └── qiita
│ └── requirements.txt
├── docker-compose.yml
└── mnt
└── json
├── author
├── list
└── tag
batch
directory
J'ai un fichier python.
Ce fichier est le fichier réel à extraire.
docker
directory
Vous pouvez trouver ce dont vous avez besoin dans le conteneur ou les paramètres cron réels ici
mnt
directory
J'ai un répertoire monté sur l'hôte et un fichier JSON est généré ici à la suite du scraping
répertoire de lots
)Le contenu du vrai fichier ʻarticle.py` dans le répertoire batch. J'ai écrit un tel article dans le passé, je vais donc vous expliquer la méthode détaillée ici. >> Obtenez les tendances Qiita (classement) et envoyez-les à Slack Dans cet article, je n'utiliserai que le programme.
Il existe deux différences par rapport au programme de l'article ci-dessus. Je veux juste une liste d'articles! Je pense que l'article ci-dessus est suffisant pour les gens.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
import json
import datetime
import os
def get_article_tags(detail_url):
tag_list = []
res = requests.get(detail_url, headers=headers)
#Manipulez le HTML avec une belle soupe
soup = BeautifulSoup(res.text, "html.parser")
tags = soup.find_all(class_="it-Tags_item")
for tag in tags:
tag_name = tag.get_text()
tag_link = tag.get('href')
tag_list.append({
'tag_name' : tag_name,
'tag_link': tag_link
})
return tag_list
def write_json(json_list, path):
with open(path, 'w') as f:
f.write(json.dumps(json_list, ensure_ascii=False, indent=4, sort_keys=True, separators=(',', ':')))
def mkdir(path):
os.makedirs(path, exist_ok=True)
def get_unique_list(seq):
seen = []
return [x for x in seq if x not in seen and not seen.append(x)]
def get_unique_tag(tag_lists):
tags = []
for v in tag_lists:
for i in v:
tags.append(i)
return tags
try:
# Root URL
url = "https://qiita.com/"
headers = {
"User-Agent" : "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"
}
today_date = datetime.datetime.now().date()
items = []
item_json = []
result = []
res = requests.get(url, headers=headers)
#Manipulez le HTML avec une belle soupe
soup = BeautifulSoup(res.text, "html.parser")
try:
main_items = soup.find(class_="p-home_main")
for main_items in soup.find_all():
if "data-hyperapp-props" in main_items.attrs:
item_json.append(main_items["data-hyperapp-props"])
items = json.loads(item_json[1])
except:
raise Exception("Not Found Json Dom Info")
if 'edges' not in items['trend']:
raise Exception("The expected list does not exist")
try:
item_detail_list = []
tags_list = []
author_list = []
for edges in items['trend']['edges']:
uuid = edges['node']['uuid']
title = edges['node']['title']
likes = edges['node']['likesCount']
article_url = url + edges['node']['author']['urlName'] + '/items/' + uuid
author_name = edges['node']['author']['urlName']
create_at = datetime.datetime.now().date()
tag_list = get_article_tags(article_url)
item = {
'article_title' : title,
'article_url' : article_url,
'article_id' : edges['node']['uuid'],
'likes' : likes,
'uuid' : uuid,
'author_name' : author_name,
'tag_list' : tag_list,
}
item_detail_list.append(item)
tags_list.append(tag_list)
author_list.append(author_name)
mkdir('/mnt/json/list/')
mkdir('/mnt/json/tag/')
mkdir('/mnt/json/author/')
#Rendre les balises uniques
tags_list = get_unique_tag(tags_list)
#Exporter le fichier json
write_json(item_detail_list, f"/mnt/json/list/{today_date}.json")
write_json(tags_list, f"/mnt/json/tag/{today_date}.json")
write_json(author_list, f"/mnt/json/author/{today_date}.json")
except:
raise Exception("Can't Create Json")
except Exception as e:
#échec de création de fichier json
mkdir('/mnt/log/')
with open(f'/mnt/log/{today_date}', 'w') as f:
f.write(e)
Ensuite, créez un environnement pour exécuter les fichiers ci-dessus.
répertoire docker
)Ce n'est pas un gros problème ici. Répertoires et monte sur votre PC avec des volumes.
version: "3"
qiita_batch:
container_name: "qiita_batch"
build:
context: ./docker/python
tty: true
volumes:
- ./batch:/usr/src/app
- ./mnt:/mnt
Dockerfile Pardonnez-moi d'être sale ... juste une brève explication ↓
Si vous souhaitez exécuter cron à l'heure japonaise spécifiée, il est essentiel de définir le fuseau horaire. J'ai foiré quelque chose et je suis finalement passé à l'heure japonaise, mais il doit y avoir un meilleur moyen ...
Les paramètres cron sont rassemblés dans etc / cron.d / qiita et écrits dans crontab ultérieurement. Je me demande si c'est mieux car ce sera plus facile à gérer. Si vous faites une erreur, n'appelez pas la commande crontab -r
...! !!
FROM python:3
ARG project_dir=/usr/src/app
WORKDIR $project_dir
ADD requirements.txt $project_dir/py/
ADD /etc/cron.d/qiita /etc/cron.d/
ENV TZ=Asia/Tokyo
RUN apt-get update && \
apt-get install -y cron less vim tzdata && \
rm -rf /var/lib/apt/lists/* && \
echo "${TZ}" > /etc/timezone && \
rm /etc/localtime && \
ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
dpkg-reconfigure -f noninteractive tzdata && \
chmod 0744 /etc/cron.d/* && \
touch /var/log/cron.log && \
crontab /etc/cron.d/qiita && \
pip install --upgrade pip && \
pip install -r $project_dir/py/requirements.txt
CMD ["cron", "-f"]
Étant donné que require.txt n'est que la sortie de ce que j'utilisais sur mon Macbook Pro, il contient pas mal de choses. Veuillez gratter ce dont vous n'avez pas besoin. Tout ce dont vous avez besoin est «beautiful soup4», «requests» et «json». Je n'en ai pas assez! Les gens bougent et pas assez de pip installent! !!
appdirs==1.4.3
beautifulsoup4==4.8.1
bs4==0.0.1
certifi==2019.9.11
chardet==3.0.4
Click==7.0
filelock==3.0.12
get==2019.4.13
gunicorn==20.0.4
idna==2.8
importlib-metadata==1.5.0
importlib-resources==1.0.2
itsdangerous==1.1.0
Jinja2==2.11.1
MarkupSafe==1.1.1
post==2019.4.13
public==2019.4.13
query-string==2019.4.13
request==2019.4.13
requests==2.22.0
six==1.14.0
soupsieve==1.9.5
urllib3==1.25.7
virtualenv==20.0.1
Werkzeug==1.0.0
zipp==2.2.0
Le contenu de / etc / cron.d / qiita
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=ja_JP.UTF-8
# Create Qiita JSON (every day AM:10:00)
0 10 * * * python /usr/src/app/py/article.py >> /var/log/cron.log 2>&1
Comme ça!
Après cela, si vous le faites avec docker-compose up -d
, il démarrera, donc si vous le laissez seul, il ira à Qiita pour le scraping et créera un fichier json. Recommandé car cela peut être fait dans un environnement Docker simple!
Recommended Posts