[PYTHON] Créons un environnement Docker qui stocke les informations de tendance Qiita!

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

* A propos du format JSON de Qiita pour enregistrer

--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.

ʻAuthor`: Obtenez les auteurs tendance pour Qiita

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 Qiita

Les 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.

Créons un environnement où Python peut être exécuté avec Docker

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

Obtenons la tendance de Qiita en grattant (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.

  1. Obtenez les balises et les auteurs des articles tendance
  2. Enregistrez le contenu acquis au format JSON
#!/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.

Créez une partie Docker pour exécuter Python (répertoire docker)

Création de docker-compose.yml

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

Créer un Dockerfile

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"]

Créez le fichier requirements.txt qui récapitule les packages requis pour exécuter Python

É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

paramètres cron

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

Créons un environnement Docker qui stocke les informations de tendance Qiita!
[Docker] Créez un environnement jupyterLab (python) en 3 minutes!
Créer un environnement Python
Créer un environnement Docker qui peut utiliser PyTorch et JupyterLab
Créons un script qui s'enregistre avec Ideone.com en Python.
Créez un environnement de développement Python simple avec VSCode et Docker Desktop
Créer une application Todo avec Django ① Créer un environnement avec Docker
J'ai essayé de créer un environnement serveur qui fonctionne sous Windows 10
Une histoire que Qiita voulait vraiment voir dans un environnement proxy
J'essaierai de créer une structure de répertoires Python que je ne regretterai pas plus tard
Créer un environnement go à l'aide de Docker
Créer un environnement Python sur Mac (2017/4)
Créez un environnement virtuel avec Python!
Créer un environnement Linux sur Windows 10
Créer un environnement python dans centos
Créons une base de données clients où le code QR est automatiquement émis en Python
Créer un bot pour retweeter les informations sur le virus corona
Comment créer un environnement NVIDIA Docker
Créez un environnement python sur votre Mac
[Python] Créez un environnement virtuel avec Anaconda
Créons un groupe gratuit avec Python
[Python] Créer un environnement Batch à l'aide d'AWS-CDK
Obtenez un environnement local pour DynamoDB avec Docker
Raclons un site dynamique avec Docker
Créer un environnement Python + uWSGI + Nginx avec Docker
Créer une application Python-GUI dans Docker (PySimpleGUI)
Créer un nouveau dict qui combine des dictés
[Linux] Créer un environnement Jenkins avec Docker
[Python] Créez un LineBot qui s'exécute régulièrement
Créez un bot qui stimule les tendances Twitter
Créer un service Web avec Docker + Flask
Introduction à docker Création d'un environnement ubuntu dans ubuntu
Utiliser WebDAV dans un environnement Docker portable
[Linux] Construction de l'environnement Docker avec Amazon Linux 2