[Python] Une fonction qui aligne la largeur en insérant un espace dans le texte qui est un mélange de pleine largeur et demi-largeur.

introduction

J'écrivais un programme pour obtenir une liste des titres et des URL du site Yahoo News et afficher chaque élément sur une seule ligne, mais j'ai eu un peu de difficulté à aligner les colonnes d'URL proprement, donc pour l'avenir J'écrirai un article en.

Obtenez les données des sites suivants. 2020-10-15_09h07_43.png

Le texte final à obtenir est le suivant. 2020-10-15_09h13_18.png

Environnement de développement

Utilisez Python 3.7. L'environnement de développement est Visual Studio Community 2019.

code

import requests
import unicodedata
from urllib.parse import urljoin
from bs4 import BeautifulSoup

def main():
    base_url = 'https://news.yahoo.co.jp/'
    categories = {
        'Majeur': '',
        'National': 'categories/domestic',
        #'Divertissement': 'categories/entertainment',
        #'international': 'categories/world',
        #'Économie': 'categories/business',
        }

    #Traitement en boucle par catégorie
    for cat in categories:
        url = urljoin(base_url, categories[cat])

        r = requests.get(url)
        soup = BeautifulSoup(r.content, 'lxml') # html.parser

        ul_tag = soup.find('div', class_='topicsList')\
                     .find('ul', class_='topicsList_main')

        print(f'==={cat}===')

        for item in ul_tag.find_all('li', class_='topicsListItem'):
            a = item.find('a')
            topic_url = a['href']
            topic_headline = a.text.strip()
            
            #print(f'{topic_headline:<18}[{topic_url}]')
            text = text_align(topic_headline, 30)
            print(f'{text}[{topic_url}]')

        print()

def get_han_count(text):
    '''
Calculez la longueur de la chaîne de caractères avec "2" pour les caractères pleine largeur et "1" pour les caractères demi-largeur.
    '''
    count = 0

    for char in text:
        if unicodedata.east_asian_width(char) in 'FWA':
            count += 2
        else:
            count += 1

    return count

def text_align(text, width, *, align=-1, fill_char=' '):
    '''
Texte mixte pleine largeur / demi-largeur
Remplissez les blancs pour qu'il ait la longueur spécifiée (conversion demi-largeur)
    
    width:Spécifiez le nombre de caractères dans la conversion demi-largeur
    align: -1 -> left, 1 -> right
    fill_char:Spécifiez le caractère à remplir

    return:Texte rempli de blancs ('abcde     ')
    '''

    fill_count = width - get_han_count(text)
    if (fill_count <= 0): return text

    if align < 0:
        return text + fill_char*fill_count
    else:
        return fill_char*fill_count + text

if __name__ == '__main__':
    main()

Au départ, le format du texte de sortie était le suivant.

for item in ul_tag.find_all('li', class_='topicsListItem'):
    a = item.find('a')
    topic_url = a['href']
    topic_headline = a.text.strip()
            
    #Ce code déplacera la colonne URL.
    print(f'{topic_headline:<18}[{topic_url}]')

Dans ce cas, la sortie sera la suivante. 2020-10-15_09h23_08.png

Des spécifications telles que print (f '{topic_headline: <18} [{topic_url}]') traiteront les caractères pleine largeur et demi-largeur sans distinction.

Par conséquent, j'ai créé une fonction pour faire la distinction entre le texte pleine largeur et demi-largeur et insérer le blanc requis.

def get_han_count(text):
    '''
Calculez la longueur de la chaîne de caractères avec "2" pour les caractères pleine largeur et "1" pour les caractères demi-largeur.
    '''
    count = 0

    for char in text:
        if unicodedata.east_asian_width(char) in 'FWA':
            count += 2
        else:
            count += 1

    return count

def text_align(text, width, *, align=-1, fill_char=' '):
    '''
Texte mixte pleine largeur / demi-largeur
Remplissez les blancs pour qu'il ait la longueur spécifiée (conversion demi-largeur)
    
    width:Spécifiez le nombre de caractères dans la conversion demi-largeur
    align: -1 -> left, 1 -> right
    fill_char:Spécifiez le caractère à remplir

    return:Texte rempli de blancs ('abcde     ')
    '''

    fill_count = width - get_han_count(text)
    if (fill_count <= 0): return text

    if align < 0:
        return text + fill_char*fill_count
    else:
        return fill_char*fill_count + text

Enfin, formatez-le avec un code comme celui-ci:

for item in ul_tag.find_all('li', class_='topicsListItem'):
    a = item.find('a')
    topic_url = a['href']
    topic_headline = a.text.strip()
            
    text = text_align(topic_headline, 30)
    print(f'{text}[{topic_url}]')

Cela a résolu le problème. Pour le moment, text_align () a permis de spécifier une option pour insérer un blanc sur le côté gauche et un symbole autre qu'un blanc.

Comment sortir dans un éditeur de texte, etc.

En passant, je pense que la sortie d'un programme Python est généralement une invite de commande, mais dans ce cas, vous voudrez peut-être l'exporter vers un éditeur de texte ou un traitement de texte et l'enregistrer.

Dans un tel cas, vous pouvez utiliser le logiciel Paster pour coller directement à la position de carryt comme un éditeur. 2020-10-15_09h50_53.png

Ensuite, les données seront collées directement comme indiqué ci-dessous. 2020-10-15_09h13_18.png

À la fin

Cette fois, c'était un thème de format texte, donc je n'ai pas expliqué le code lié au scraping, mais presque toutes les méthodes find () étaient suffisantes.

Vous êtes libre d'utiliser le code source ci-dessus, mais veuillez le faire à vos propres risques.

Site de référence

Pour savoir comment utiliser la fonction qui fait la distinction entre pleine largeur et demi-largeur (ʻunicodedata.east_asian_width () `), je me suis référé au site suivant.

Comptez le nombre de caractères (largeur) comme 1 caractère demi-largeur et 2 caractères pleine largeur en Python

Lorsque vous effectuez un scraping Web, assurez-vous de vérifier le fichier robots.txt du site cible.

text:news.yahoo.co.jp/robots.txt


User-agent: *
Disallow: /comment/plugin/
Disallow: /comment/violation/
Disallow: /polls/widgets/
Disallow: /articles/*/comments
Sitemap: https://news.yahoo.co.jp/sitemaps.xml
Sitemap: https://news.yahoo.co.jp/sitemaps/article.xml
Sitemap: https://news.yahoo.co.jp/byline/sitemap.xml
Sitemap: https://news.yahoo.co.jp/polls/sitemap.xml

Recommended Posts

[Python] Une fonction qui aligne la largeur en insérant un espace dans le texte qui est un mélange de pleine largeur et demi-largeur.
Une fonction qui mesure le temps de traitement d'une méthode en python
Comment mettre un espace demi-largeur avant les lettres et les chiffres en Python.
Fonction Eval () qui calcule une chaîne de caractères comme expression en python
Divise la chaîne de caractères par le nombre de caractères spécifié. En Ruby et Python.
Corriger les fluctuations de notation demi-largeur et pleine largeur en Python
[Python] Changer la couleur du texte et la couleur d'arrière-plan d'un mot clé spécifique dans la sortie d'impression
Traitement pleine largeur et demi-largeur des données CSV en Python
Décale la chaîne de l'alphabet de N caractères en Python
Que signifie le dernier () dans une fonction en Python?
Une bibliothèque qui surveille la vie et la mort d'autres machines en envoyant un ping à partir de Python
J'ai aussi essayé d'imiter la fonction monade et la monade d'état avec le générateur en Python
Découvrez la largeur apparente d'une chaîne en python
Une fonction qui divise l'itérable en N morceaux en Python
Un programme qui supprime des caractères spécifiques du texte saisi
Créez le code qui renvoie "A et prétendant B" en python
Comment écrire une classe méta qui prend en charge à la fois python2 et python3
Code et leçons apprises pour les fonctions qui ouvrent des dossiers Windows spéciaux dans les ctypes Python3
[Python] Une fonction qui recherche la chaîne de caractères entière avec une expression régulière et obtient toutes les chaînes de caractères correspondantes.
Créer une fonction en Python
Comptez bien le nombre de caractères thaïlandais et arabes en Python
Utilisez la bibliothèque unicodedata de Python pour afficher les caractères pleine largeur et demi-largeur
Lire la sortie standard d'un sous-processus ligne par ligne en Python