IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

BeautifulSoup met <U+0092> à la place d'une apostrophe , ce qui affiche ÿ


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 651
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 651
    Par défaut BeautifulSoup met <U+0092> à la place d'une apostrophe , ce qui affiche ÿ
    Bonjour,

    j'ai ce code simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #!/usr/bin/python3
    # -*-coding: utf-8 -*-
     
    import requests
    from bs4 import BeautifulSoup as bs
     
    with requests.get('https://www.developpez.net/forums/f806/systemes/autres-systemes/mobiles/') as r:
    	soup = bs(r.content,'html.parser')
    	with open('/tmp/dvp.html', 'w') as f:
    		f.write(str(soup))
    le HTML qui en résulte montre que les apostrophes sont convertit en "private use two" (des "quotes") : ","name":"La part de march\u00e9 de l\u0092iPhone grimpe \u00e0 55 % aux USA alors que les ventes.

    que puis-je faire au niveau de mon code (à part faire un replace()) pour avoir un "encodage" correct ?
    si c'est le fait du forum, à qui puis-je m'adresser pour qu'il cesse cette pratique ?; )
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  2. #2
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 211
    Par défaut
    Hello,
    ce n'est pas beautifulsoup qui est en cause mais plutôt la chaîne qu'on lui donne en entrée :
    Dans google chrome si on fait Afficher le code source de la page on trouve que :
    "name":"La part de march\u00e9 de l\u0092iPhone grimpe \u00e0 55 % aux USA alors que les ventes d\u0092appareils Android chutent fortement"
    se trouve dans un script
    <script type="application/ld+json">
    Si dans google chrome on utilise Plus d'outils/outils de développement qui permet de visualiser le code de la page dont les scripts ont été exécutés on trouve :
    La part de marché de l’iPhone grimpe à 55 % aux USA alors que les ventes d’appareils Android chutent fortement
    ce qui est correct.

    il faut un module comme selenium pour obtenir la page dont les scripts on été interprétés par un navigateur.
    voir ici : scrape-content-from-dynamic-websites

    To scrape content from a static page, we use BeautifulSoup as our package for scraping, and it works flawlessly for static pages. We use requests to load page into our python script. Now, if the page we are trying to load is dynamic in nature and we request this page by requests library, it would send the JS code to be executed locally. Requests package does not execute this JS code and just gives it as the page source.
    BeautifulSoup does not catch the interactions with DOM via Java Script. Let’s suppose, if you have a table that is generated by JS. BeautifulSoup will not be able to capture it, while Selenium can.
    If there was just a need to scrape static websites, we would’ve used just bs4. But, for dynamically generated webpages, we use selenium.
    Ami calmant, J.P

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,

    Citation Envoyé par N_BaH Voir le message
    que puis-je faire au niveau de mon code (à part faire un replace()) pour avoir un "encodage" correct ?
    si c'est le fait du forum, à qui puis-je m'adresser pour qu'il cesse cette pratique ?; )
    Un solution sera de décoder la chaine de bytes reçue (r.content) avec l'encoding unicode_escape (i.e récupérer l'unicode retourné par r.content.decode('unicode_escape')) ou d'ajouter from_encoding='unicode_escape' à l'appel à BS.

    Est-ce que cet encodage est correct? A mon sens, si on fait le scrapping d'un site, on doit se débrouiller pour rendre consommable le contenu qu'on récupère... ce qui le maintiennent se contentent d'assurer que le rendu des contenus sont lisibles par différents navigateurs.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 651
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 651
    Par défaut
    Citation Envoyé par jurassic pork
    il faut un module comme selenium pour obtenir la page dont les scripts on été interprétés par un navigateur.
    je trouve selenium lourd; je le réserve pour les cas où le code de la page n'est pas accessible sans "interface graphique".
    ici, le code est accessible, il n'y que quelques caractères (je crois qu'il y en a au moins un autre) qui sont modifié entre ce qui est entré (je suppose) par le PO et ce que je reçois.

    Citation Envoyé par wiztricks
    ou d'ajouter from_encoding='unicode_escape' à l'appel à BS
    c'est sans effet.
    et r.content.decode('unicode_escape') provoque une erreur : <stdin>:8: DeprecationWarning: invalid escape sequence '\/'.

    soit dit en passant, je ne parviens pas à faire un replace()
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    721
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2006
    Messages : 721
    Par défaut
    Je me tournerais plutôt vers la normalisation Unicode, par exemple unicodedata.normalize('NFKD', <string>)

  6. #6
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 651
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 651
    Par défaut
    unicodedata.normalize ne change pas grand-chose.

    par contre, ça a mis en évidence que pour remplacer \u0092, il faut faire un replace('\\u0092','\\u0027')
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    c'est sans effet.
    et r.content.decode('unicode_escape') provoque une erreur : <stdin>:8: DeprecationWarning: invalid escape sequence '\/'.
    Chez moi, çà marche et pour le warning je vous suggère la lecture de cet article sur OVF.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> b'zzz\\u0092Xyz\\u00e9'.decode('unicode_escape')
    'zzz\x92Xyzé'
    >>>
    Le \x92 est une question de glyph inexistante (comparé au é). On peut le remplacer dans un 2ème temps:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> _.replace('\x92', '*')
    'zzz*Xyzé'
    >>>
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Expert confirmé
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    4 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 4 211
    Par défaut
    Hello,
    si on regarde le code source de la page, on s'aperçoit que suivant les articles, les apostrophes utilisées dans les titres ne sont pas toujours du même type : donc l'introduction de ce \u0092 serait dû aux auteurs des articles ? le \u0092 ne correspond pas au code "standard" de l'apostrophe.
    The character ’, or U+0092, falls under the Unicode category "C1 Controls and Latin-1 Supplement". Officially, this Unicode code point is designated as a control character, specifically "Private Use Two" in the C1 control code set. Its usage is not standardized and it can be used for any purpose defined by a specific implementation. It's worth noting that in many contexts, this code point is incorrectly used to represent the typographical apostrophe or right single quotation mark (’), due to legacy issues with some software and systems. The standard Unicode characters for these marks are U+2019 (right single quotation mark) and U+02BC (modifier letter apostrophe), respectively.
    Ami calmant, J.P

  9. #9
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    La situation est bien obscure entre la quasi-intégralité de la page encodée en utf-8, la balise <meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"/>, la partie json qui présente des soit-disant code-point UNICODE mais qui sont en réalité des octets d'iso-8859-1 déguisés en code-point, ajoutons à ça la magie noire pratiquée par BeautifulSoup pour être "arrangeant". Bref, j'ai trouvé ça, mais franchement, je ne peux pas te garantir que ça fonctionnera pour toutes les pages du site.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #!/usr/bin/python3
    # -*-coding: utf-8 -*-
     
    import requests
    from bs4 import BeautifulSoup as bs, UnicodeDammit as ud
     
    with requests.get('https://www.developpez.net/forums/f806/systemes/autres-systemes/mobiles/') as r:
        markup=ud(r.content, ['iso-8859-1'], smart_quotes_to='html').unicode_markup
        soup = bs(markup, features='html.parser')
     
        with open('/tmp/dvp.html', 'w') as fo:
            fo.write(str(soup))

Discussions similaires

  1. [Apache] Mise en place d'une page de maintenance
    Par divail dans le forum Apache
    Réponses: 5
    Dernier message: 02/02/2006, 09h58
  2. Réponses: 2
    Dernier message: 06/10/2005, 16h10
  3. Réponses: 9
    Dernier message: 12/08/2005, 15h10
  4. Mise en place d'une solution Data Guard 9i R2
    Par user_oracle dans le forum Oracle
    Réponses: 4
    Dernier message: 16/02/2005, 10h12
  5. [VB.NET] Mise en place d'une progress bar
    Par Hoegaarden dans le forum Windows Forms
    Réponses: 14
    Dernier message: 19/10/2004, 09h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo