Ajouter votre site web favori d’actualités

calibre contient une structure de création puissante, flexible et facile à utiliser pour télécharger des actualités sur Internet et les convertir en livre numérique. Ce qui suit vous montrera, au moyen d’exemples, comment obtenir les actualités de divers sites web.

Pour avoir une compréhension de la façon d’employer cette structure de création, suivez les exemples ci-dessous dans l’ordre :

Récupération entièrement automatique

Si votre source d’actualité est assez simple, calibre est capable d’en effectuer la récupération de manière complètement automatique. Tout ce que vous avez à faire est de fournir l’URL. calibre recueille toutes les informations nécessaires pour télécharger une source d’actualités dans une recette. Pour intégrer à calibre une nouvelle source d’actualité, vous devez créer une recette pour celle-ci. Voyons quelques exemples :

Le blog calibre

Le blog calibre est un blog de postes qui décrivent beaucoup de fonctionnalités utiles de calibre d’une manière simple et accessible pour les nouveaux utilisateurs de calibre. Pour pouvoir télécharger ce blog dans un livre numérique, nous nous référons au flux RSS du blog:

https://blog.calibre-ebook.com/feeds/posts/default

J’ai obtenu l’URL RSS en regardant sous « Subscribe to » en bas de la page du blog et en choisissant Posts → Atom. Pour faire en sorte que calibre télécharge les flux et les convertissent en livre numérique, vous devrez faire une clic droit sur le bouton Récupérer des actualités et puis le bouton Ajouter une source personnalisée d’informations. Une boite de dialogue semblable à celle montrée ci-dessous devrait s’ouvrir.

_images/custom_news.png

Tout d’abord entrez Blog calibre dans le champ Titre de la recette. Ceci sera le titre du livre numérique qui sera créé à partir des articles des flux ci-dessus.

Les deux champs suivants (Article le plus ancien et Max. Nombre d’articles par flux) donnent la possibilité de contrôler combien d’articles pourront être téléchargés de chaque flux. Ils sont assez explicites.

Pour ajouter les flux à la recette, entrer le titre du flux et l’URL du flux et cliquez sur le bouton Ajouter un flux. Une fois que vous avez ajouté le flux, cliquez simplement sur le bouton Sauvegarder et vous avez fini ! Fermez la boîte de dialogue.

Pour tester votre nouvelle recette, cliquez le bouton Récupérer des informations et dans le sous menu Personnaliser les sources d’actualités cliquez guilabel:Blog calibre. Après quelques minutes, le nouveau livre numérique de postes de blog apparaîtra dans la vue de la bibliothèque principale (si votre lecteur est connecté, il sera déposé sur le lecteur plutôt que dans la bibliothèque). Sélectionnez-le et appuyer le bouton Visualiser pour le lire !

La raison pour laquelle cela fonctionne si bien, avec si peu d’efforts, est parce que le blog fournit un flux RSS à contenu plein, c’est à dire, dont le contenu de l’article est inclut dans le flux lui-même. Pour la plupart des sites d’actualités qui fournissent des actualités de cette façon, avec des flux à contenu plein, vous n’avez pas besoin de faire beaucoup plus d’efforts pour les convertir en livres numériques. Maintenant nous allons regarder à des sources d’actualités qui ne fournissent pas des flux à contenu plein. Dans de tels flux, L’article complet est une page web et le flux contient uniquement un lien vers la page web avec un petit résumé de l’article.

bbc.co.uk

Essayons les deux flux suivant de The BBC:

Suivez la procédure comme exposée dans Le blog calibre pour créer une recette pour The BBC (en utilisant les flux ci-dessus). Regardez le livre numérique téléchargé,nous voyons que calibre a réalisé un travail honorable d’extraire seulement le contenu qui vous intéresse depuis la page web de chaque article. Cependant, le processus d’extraction n’est pas parfait. Parfois il laisse du contenu indésirable comme des menus et des aides à la navigation ou enlève du contenu qui aurait dû apparaître seul, comme des titres d’article. Pour obtenir une extraction parfaite, nous aurons besoin d’adapter le processus de récupération, tel que décrit dans la section suivante.

Personnaliser le processus de récupération

Quand vous voulez perfectionner le processus de téléchargement, ou télécharger du contenu d’un site web particulièrement complexe, vous pouvez vous servir de toutes la puissance et de la flexibilité de la structure recette. Afin de faire cela, dans la boîte de dialogue Ajouter des sources d’actualités personnalisées, cliquez simplement sur le bouton Basculer vers le mode Avancé.

La personnalisation la plus facile et souvent la plus productive est d’employer la version imprimable des articles en ligne. La version imprimable est habituellement moins compliqué et se traduit beaucoup plus souplement en un livre numérique. Essayons d’employer la version imprimable des articles de The BBC.

Utilisation de la version imprimable de bbc.co.uk

La première étape est de regarder le livre numérique que nous avons précédemment téléchargé depuis bbc.co.uk. A la fin de chaque article, dans le livre numérique il y a un petit texte de présentation vous indiquant d’où l’article a été téléchargé. Copier et coller cette URL dans un navigateur. Maintenant sur la page Web de l’article recherchez un lien qui pointe vers la « version imprimable ». Cliquez le pour voir la version imprimable de l’article. Il parait beaucoup plus ordonné ! Comparez maintenant les deux URLs. Pour moi elles étaient :

Aussi il semble que pour obtenir la version imprimable, nous avons besoin de préfixer que URL d’article avec :

newsvote.bbc.co.uk/mpapps/pagetools/print/

Maintenant dans le Mode Avancé de la boîte de dialogue Personnaliser les sources d’actualités, vous devriez voir quelque chose comme (rappeler vous de sélectionner la recette The BBC avant de basculer vers le mode avancé) :

_images/bbc_advanced.png

Vous pouvez voir que les champs du Mode de base ont été traduits en code de Python d’une façon simple. Nous devons ajouter des instructions à cette recette pour employer la version imprimable des articles. Tout ce qui est nécessaire est d’ajouter les deux lignes suivantes :

def print_version(self, url):
    return url.replace('https://', 'https://newsvote.bbc.co.uk/mpapps/pagetools/print/')

C’est du Python, donc l’indentation est importante. Après que vous ayez ajouté les lignes, elles devraient ressembler à :

_images/bbc_altered.png

Ci-dessus, def print_version(self, url) définit une méthode qui est appelée par calibre pour chaque article. url est l’URL de l’article original. Ce que print_version fait est de prendre cette url et de la remplacer avec l’URL qui pointe vers la version imprimable de l’article. Pour apprendre à propos de Python voir le tutoriel.

Maintenant, cliquez sur le bouton Ajouter/Mettre à jour la recette et vos changements seront enregistrés. Téléchargez à nouveau le livre numérique. Vous devriez obtenir un livre numérique beaucoup plus amélioré. Un des problèmes avec la nouvelle version est que les polices sur la page Web de la version imprimable sont trop petites. Ceci est automatiquement fixé en convertissant en livre numérique, mais même après le processus de fixation, la taille de la police des menus et la barre de navigation peut être trop grande relativement au texte d’article. Pour fixer ceci, nous ferons encore plus de personnalisation dans la prochaine section.

Remplacer les styles d’article

Dans la section précédente, nous avons vu que la taille de la police pour des articles de la version imprimable de The BBC était trop petite. Dans la plupart des sites Web, le The BBC inclus, cette taille de la police est placée au moyen de feuilles de style CSS. Nous pouvons désactiver la récupération de telles feuilles de style n ajoutant la ligne:

no_stylesheets = True

La recette ressemble maintenant à :

_images/bbc_altered1.png

La nouvelle version parait assez bonne. Si vous êtes un perfectionniste, vous voudrez lire la prochaine section, qui traite de modifier réellement le contenu téléchargé.

Découper et émincer

calibre a des capacités très puissantes et flexibles quand il s’agit de manipuler le contenu téléchargé. Pour montrer quelques uns de ces derniers, regardons encore notre vieille amie la recette The BBC. Regardez le code source (HTML) de quelques articles (version imprimable), nous voyons qu’il contient un pied de page qui n’apporte aucune information utile

<div class="footer">
...
</div>

Ceci peut être supprimé en ajoutant:

remove_tags    = [dict(name='div', attrs={'class':'footer'})]

à la recette. Finalement, remplaçons certains des CSS que nous avons désactivés plus tôt, avec notre propre CSS qui est plus adapté pour la conversion en livre numérique:

extra_css      = '.headline {font-size: x-large;} \n .fact { padding-top: 10pt  }'

Avec ces ajouts, notre recette est devenue « une production de qualité », en effet ele est très proche de la recette réelle utilisée par calibre pour la BBC, montrée ci-dessous :

##
# Title:        BBC News, Sport, and Blog Calibre Recipe
# Contact:      mattst - jmstanfield@gmail.com
##
# License:      GNU General Public License v3 - http://www.gnu.org/copyleft/gpl.html
# Copyright:    mattst - jmstanfield@gmail.com
##
# Written:      November 2011
# Last Edited:  2011-11-19
##

__license__ = 'GNU General Public License v3 - http://www.gnu.org/copyleft/gpl.html'
__copyright__ = 'mattst - jmstanfield@gmail.com'


'''
BBC News, Sport, and Blog Calibre Recipe
'''

# Import the regular expressions module.
import re

# Import the BasicNewsRecipe class which this class extends.
from calibre.web.feeds.recipes import BasicNewsRecipe


def classes(classes):
    q = frozenset(classes.split(' '))
    return dict(attrs={
        'class': lambda x: x and frozenset(x.split()).intersection(q)})


class BBCNews(BasicNewsRecipe):

    #
    #    **** IMPORTANT USERS READ ME ****
    #
    #  First select the feeds you want then scroll down below the feeds list
    #  and select the values you want for the other user preferences, like
    #  oldest_article and such like.
    #
    #
    #  Select the BBC rss feeds which you want in your ebook.
    #  Selected feed have NO '#' at their start, de-selected feeds begin with a '#'.
    #
    #  Eg.  ("News Home", "http://feeds.bbci.co.uk/... - include feed.
    #  Eg. #("News Home", "http://feeds.bbci.co.uk/... - do not include feed.
    #
    # There are 68 feeds below which constitute the bulk of the available rss
    # feeds on the BBC web site. These include 5 blogs by editors and
    # correspondents, 16 sports feeds, 15 'sub' regional feeds (Eg. North West
    # Wales, Scotland Business), and 7 Welsh language feeds.
    #
    # Some of the feeds are low volume (Eg. blogs), or very low volume (Eg. Click)
    # so if "oldest_article = 1.5" (only articles published in the last 36 hours)
    # you may get some 'empty feeds' which will not then be included in the ebook.
    #
    # The 15 feeds currently selected below are simply my default ones.
    #
    # Note: With all 68 feeds selected, oldest_article set to 2,
    # max_articles_per_feed set to 100, and simultaneous_downloads set to 10,
    # the ebook creation took 29 minutes on my speedy 100 mbps net connection,
    # fairly high-end desktop PC running Linux (Ubuntu Lucid-Lynx).
    # More realistically with 15 feeds selected, oldest_article set to 1.5,
    # max_articles_per_feed set to 100, and simultaneous_downloads set to 20,
    # it took 6 minutes. If that's too slow increase 'simultaneous_downloads'.
    #
    # Select / de-select the feeds you want in your ebook.
    #
    feeds = [
        ("News Home", "http://feeds.bbci.co.uk/news/rss.xml"),
        ("UK", "http://feeds.bbci.co.uk/news/uk/rss.xml"),
        ("World", "http://feeds.bbci.co.uk/news/world/rss.xml"),
        # ("England", "http://feeds.bbci.co.uk/news/england/rss.xml"),
        # ("Scotland", "http://feeds.bbci.co.uk/news/scotland/rss.xml"),
        # ("Wales", "http://feeds.bbci.co.uk/news/wales/rss.xml"),
        # ("N. Ireland", "http://feeds.bbci.co.uk/news/northern_ireland/rss.xml"),
        # ("Africa", "http://feeds.bbci.co.uk/news/world/africa/rss.xml"),
        # ("Asia", "http://feeds.bbci.co.uk/news/world/asia/rss.xml"),
        # ("Europe", "http://feeds.bbci.co.uk/news/world/europe/rss.xml"),
        # ("Latin America", "http://feeds.bbci.co.uk/news/world/latin_america/rss.xml"),
        # ("Middle East", "http://feeds.bbci.co.uk/news/world/middle_east/rss.xml"),
        ("US & Canada", "http://feeds.bbci.co.uk/news/world/us_and_canada/rss.xml"),
        ("Politics", "http://feeds.bbci.co.uk/news/politics/rss.xml"),
        ("Science/Environment",
         "http://feeds.bbci.co.uk/news/science_and_environment/rss.xml"),
        ("Technology", "http://feeds.bbci.co.uk/news/technology/rss.xml"),
        ("Magazine", "http://feeds.bbci.co.uk/news/magazine/rss.xml"),
        ("Entertainment/Arts",
         "http://feeds.bbci.co.uk/news/entertainment_and_arts/rss.xml"),
        # ("Health", "http://feeds.bbci.co.uk/news/health/rss.xml"),
        # ("Education/Family", "http://feeds.bbci.co.uk/news/education/rss.xml"),
        ("Business", "http://feeds.bbci.co.uk/news/business/rss.xml"),
        ("Special Reports", "http://feeds.bbci.co.uk/news/special_reports/rss.xml"),
        ("Also in the News", "http://feeds.bbci.co.uk/news/also_in_the_news/rss.xml"),
        # ("Newsbeat", "http://www.bbc.co.uk/newsbeat/rss.xml"),
        # ("Click", "http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/programmes/click_online/rss.xml"),
        # ("Blog: Mark D'Arcy (Parliamentary Correspondent)", "http://feeds.bbci.co.uk/news/correspondents/markdarcy/rss.sxml"),
        # ("Blog: Robert Peston (Business Editor)", "http://feeds.bbci.co.uk/news/correspondents/robertpeston/rss.sxml"),
        # ("Blog: Stephanie Flanders (Economics Editor)", "http://feeds.bbci.co.uk/news/correspondents/stephanieflanders/rss.sxml"),
        ("Sport Front Page",
         "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/front_page/rss.xml"),
        # ("Football", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/football/rss.xml"),
        # ("Cricket", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/cricket/rss.xml"),
        # ("Rugby Union", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/rugby_union/rss.xml"),
        # ("Rugby League", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/rugby_league/rss.xml"),
        # ("Tennis", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/tennis/rss.xml"),
        # ("Golf", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/golf/rss.xml"),
        # ("Motorsport", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/motorsport/rss.xml"),
        # ("Boxing", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/boxing/rss.xml"),
        # ("Athletics", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/athletics/rss.xml"),
        # ("Snooker", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/other_sports/snooker/rss.xml"),
        # ("Horse Racing", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/other_sports/horse_racing/rss.xml"),
        # ("Cycling", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/other_sports/cycling/rss.xml"),
        # ("Disability Sport", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/other_sports/disability_sport/rss.xml"),
        # ("Other Sport", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/other_sports/rss.xml"),
        # ("Olympics 2012", "http://newsrss.bbc.co.uk/rss/sportonline_uk_edition/other_sports/olympics_2012/rss.xml"),
        # ("N. Ireland Politics", "http://feeds.bbci.co.uk/news/northern_ireland/northern_ireland_politics/rss.xml"),
        # ("Scotland Politics", "http://feeds.bbci.co.uk/news/scotland/scotland_politics/rss.xml"),
        # ("Scotland Business", "http://feeds.bbci.co.uk/news/scotland/scotland_business/rss.xml"),
        # ("E. Scotland, Edinburgh & Fife", "http://feeds.bbci.co.uk/news/scotland/edinburgh_east_and_fife/rss.xml"),
        # ("W. Scotland & Glasgow", "http://feeds.bbci.co.uk/news/scotland/glasgow_and_west/rss.xml"),
        # ("Highlands & Islands", "http://feeds.bbci.co.uk/news/scotland/highlands_and_islands/rss.xml"),
        # ("NE. Scotland, Orkney & Shetland", "http://feeds.bbci.co.uk/news/scotland/north_east_orkney_and_shetland/rss.xml"),
        # ("South Scotland", "http://feeds.bbci.co.uk/news/scotland/south_scotland/rss.xml"),
        # ("Central Scotland & Tayside", "http://feeds.bbci.co.uk/news/scotland/tayside_and_central/rss.xml"),
        # ("Wales Politics", "http://feeds.bbci.co.uk/news/wales/wales_politics/rss.xml"),
        # ("NW. Wales", "http://feeds.bbci.co.uk/news/wales/north_west_wales/rss.xml"),
        # ("NE. Wales", "http://feeds.bbci.co.uk/news/wales/north_east_wales/rss.xml"),
        # ("Mid. Wales", "http://feeds.bbci.co.uk/news/wales/mid_wales/rss.xml"),
        # ("SW. Wales", "http://feeds.bbci.co.uk/news/wales/south_west_wales/rss.xml"),
        # ("SE. Wales", "http://feeds.bbci.co.uk/news/wales/south_east_wales/rss.xml"),
        # ("Newyddion - News in Welsh", "http://feeds.bbci.co.uk/newyddion/rss.xml"),
        # ("Gwleidyddiaeth", "http://feeds.bbci.co.uk/newyddion/gwleidyddiaeth/rss.xml"),
        # ("Gogledd-Ddwyrain", "http://feeds.bbci.co.uk/newyddion/gogledd-ddwyrain/rss.xml"),
        # ("Gogledd-Orllewin", "http://feeds.bbci.co.uk/newyddion/gogledd-orllewin/rss.xml"),
        # ("Canolbarth", "http://feeds.bbci.co.uk/newyddion/canolbarth/rss.xml"),
        # ("De-Ddwyrain", "http://feeds.bbci.co.uk/newyddion/de-ddwyrain/rss.xml"),
        # ("De-Orllewin", "http://feeds.bbci.co.uk/newyddion/de-orllewin/rss.xml"),
    ]

    #    **** SELECT YOUR USER PREFERENCES ****

    # Title to use for the ebook.
    #
    title = 'BBC News'

    # A brief description for the ebook.
    #
    description = u'BBC web site ebook created using rss feeds.'

    # The max number of articles which may be downloaded from each feed.
    # I've never seen more than about 70 articles in a single feed in the
    # BBC feeds.
    #
    max_articles_per_feed = 100

    # The max age of articles which may be downloaded from each feed. This is
    # specified in days - note fractions of days are allowed, Eg. 2.5 (2 and a
    # half days). My default of 1.5 days is the last 36 hours, the point at
    # which I've decided 'news' becomes 'old news', but be warned this is not
    # so good for the blogs, technology, magazine, etc., and sports feeds.
    # You may wish to extend this to 2-5 but watch out ebook creation time will
    # increase as well. Setting this to 30 will get everything (AFAICT) as long
    # as max_articles_per_feed remains set high (except for 'Click' which is
    # v. low volume and its currently oldest article is 4th Feb 2011).
    #
    oldest_article = 1.5

    # Number of simultaneous downloads. 20 is consistantly working fine on the
    # BBC News feeds with no problems. Speeds things up from the defualt of 5.
    # If you have a lot of feeds and/or have increased oldest_article above 2
    # then you may wish to try increasing simultaneous_downloads to 25-30,
    # Or, of course, if you are in a hurry. [I've not tried beyond 20.]
    #
    simultaneous_downloads = 20

    # Timeout for fetching files from the server in seconds. The default of
    # 120 seconds, seems somewhat excessive.
    #
    timeout = 30

    # The format string for the date shown on the ebook's first page.
    # List of all values: http://docs.python.org/library/time.html
    # Default in news.py has a leading space so that's mirrored here.
    # As with 'feeds' select/de-select by adding/removing the initial '#',
    # only one timefmt should be selected, here's a few to choose from.
    #
    # [Fri, 14 Nov 2011] (Calibre default)
    timefmt = ' [%a, %d %b %Y]'
    # timefmt = ' [%a, %d %b %Y %H:%M]'       # [Fri, 14 Nov 2011 18:30]
    # timefmt = ' [%a, %d %b %Y %I:%M %p]'    # [Fri, 14 Nov 2011 06:30 PM]
    # timefmt = ' [%d %b %Y]'                 # [14 Nov 2011]
    # timefmt = ' [%d %b %Y %H:%M]'           # [14 Nov 2011 18.30]
    # timefmt = ' [%Y-%m-%d]'                 # [2011-11-14]
    # timefmt = ' [%Y-%m-%d-%H-%M]'           # [2011-11-14-18-30]

    #
    #    **** IMPORTANT ****
    #
    #    DO NOT EDIT BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING.
    #
    #    DO NOT EDIT BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING.
    #
    #    I MEAN IT, YES I DO, ABSOLUTELY, AT YOU OWN RISK. :)
    #
    #    **** IMPORTANT ****
    #

    # Author of this recipe.
    __author__ = 'mattst'

    # Specify English as the language of the RSS feeds (ISO-639 code).
    language = 'en_GB'

    # Set tags.
    tags = 'news, sport, blog'

    # Set publisher and publication type.
    publisher = 'BBC'
    publication_type = 'newspaper'

    # Disable stylesheets from site.
    no_stylesheets = True

    # Specifies an override encoding for sites that have an incorrect charset
    # specified. Default of 'None' says to auto-detect. Some other BBC recipes
    # use 'utf8', which works fine (so use that if necessary) but auto-detecting
    # with None is working fine, so stick with that for robustness.
    encoding = None

    # Sets whether a feed has full articles embedded in it. The BBC feeds do
    # not.
    use_embedded_content = False

    # Removes empty feeds - why keep them!?
    remove_empty_feeds = True
    ignore_duplicate_articles = {'title', 'url'}
    resolve_internal_links = True

    # Create a custom title which fits nicely in the Kindle title list.
    # Requires "import time" above class declaration, and replacing
    # title with custom_title in conversion_options (right column only).
    # Example of string below: "BBC News - 14 Nov 2011"
    #
    # custom_title = "BBC News - " + time.strftime('%d %b %Y')

    # Conversion options for advanced users. Avoid setting 'linearize_tables'
    # as that plays havoc with the 'old style' table based pages.
    conversion_options = {
        # 'title'       : title,
        # 'comments'    : description,
        # 'tags'        : tags,
        # 'language'    : language,
        # 'publisher'   : publisher,
        # 'authors'     : publisher,
        'smarten_punctuation' : True
    }

    # Specify extra CSS - overrides ALL other CSS (IE. Added last).
    extra_css = 'body { font-family: verdana, helvetica, sans-serif; } \
                 .introduction, .first { font-weight: bold; } \
                 .cross-head { font-weight: bold; font-size: 125%; } \
                 .cap, .caption { display: block; font-size: 80%; font-style: italic; } \
                 .cap, .caption, .caption img, .caption span { display: block; text-align: center; margin: 5px auto; } \
                 .byl, .byd, .byline img, .byline-name, .byline-title, .author-name, .author-position, \
                    .correspondent-portrait img, .byline-lead-in, .name, .bbc-role { display: block; \
                    text-align: center; font-size: 80%; font-style: italic; margin: 1px auto; } \
                 .story-date, .published { font-size: 80%; } \
                 table { width: 100%; } \
                 td img { display: block; margin: 5px auto; } \
                 ul { padding-top: 10px; } \
                 ol { padding-top: 10px; } \
                 li { padding-top: 5px; padding-bottom: 5px; } \
                 h1 { text-align: center; font-size: 175%; font-weight: bold; } \
                 h2 { text-align: center; font-size: 150%; font-weight: bold; } \
                 h3 { text-align: center; font-size: 125%; font-weight: bold; } \
                 h4, h5, h6 { text-align: center; font-size: 100%; font-weight: bold; }'

    # Remove various tag attributes to improve the look of the ebook pages.
    remove_attributes = ['border', 'cellspacing', 'align', 'cellpadding', 'colspan',
                         'valign', 'vspace', 'hspace', 'alt', 'width', 'height']

    # Remove the (admittedly rarely used) line breaks, "<br />", which sometimes
    # cause a section of the ebook to start in an unsightly fashion or, more
    # frequently, a "<br />" will muck up the formatting of a correspondant's byline.
    # "<br />" and "<br clear/>" are far more frequently used on the table formatted
    # style of pages, and really spoil the look of the ebook pages.
    preprocess_regexps = [(re.compile(r'<br[ ]*/>', re.IGNORECASE), lambda m: ''),
                          (re.compile(r'<br[ ]*clear.*/>', re.IGNORECASE), lambda m: '')]

    # Create regular expressions for tag keeping and removal to make the matches more
    # robust against minor changes and errors in the HTML, Eg. double spaces, leading
    # and trailing spaces, missing hyphens, and such like.
    # Python regular expression ('re' class) page:
    # http://docs.python.org/library/re.html

    # ***************************************
    # Regular expressions for keep_only_tags:
    # ***************************************

    # The BBC News HTML pages use variants of 'storybody' to denote the section of a HTML
    # page which contains the main text of the article. Match storybody variants: 'storybody',
    # 'story-body', 'story body','storybody ', etc.
    storybody_reg_exp = '^.*story[_ -]*body.*$'

    # The BBC sport and 'newsbeat' (features) HTML pages use 'blq_content' to hold the title
    # and published date. This is one level above the usual news pages which have the title
    # and date within 'story-body'. This is annoying since 'blq_content' must also be kept,
    # resulting in a lot of extra things to be removed by remove_tags.
    blq_content_reg_exp = '^.*blq[_ -]*content.*$'

    # The BBC has an alternative page design structure, which I suspect is an out-of-date
    # design but which is still used in some articles, Eg. 'Click' (technology), 'FastTrack'
    # (travel), and in some sport pages. These alternative pages are table based (which is
    # why I think they are an out-of-date design) and account for -I'm guesstimaking- less
    # than 1% of all articles. They use a table class 'storycontent' to hold the article
    # and like blq_content (above) have required lots of extra removal by
    # remove_tags.
    story_content_reg_exp = '^.*story[_ -]*content.*$'

    # Keep the sections of the HTML which match the list below. The HTML page created by
    # Calibre will fill <body> with those sections which are matched. Note that the
    # blq_content_reg_exp must be listed before storybody_reg_exp in keep_only_tags due to
    # it being the parent of storybody_reg_exp, that is to say the div class/id 'story-body'
    # will be inside div class/id 'blq_content' in the HTML (if 'blq_content' is there at
    # all). If they are the other way around in keep_only_tags then blq_content_reg_exp
    # will end up being discarded.
    keep_only_tags = [dict(name='table', attrs={'class': re.compile(story_content_reg_exp, re.IGNORECASE)}),
                      dict(name='div',   attrs={'class': re.compile(
                           blq_content_reg_exp, re.IGNORECASE)}),
                      dict(name='div',   attrs={'id': re.compile(
                           blq_content_reg_exp, re.IGNORECASE)}),
                      dict(name='div',   attrs={'class': re.compile(
                           storybody_reg_exp, re.IGNORECASE)}),
                      dict(name='div',   attrs={'id': re.compile(storybody_reg_exp, re.IGNORECASE)})]

    # ************************************
    # Regular expressions for remove_tags:
    # ************************************

    # Regular expression to remove share-help and variant tags. The share-help class
    # is used by the site for a variety of 'sharing' type links, Eg. Facebook, delicious,
    # twitter, email. Removed to avoid page clutter.
    share_help_reg_exp = '^.*share[_ -]*help.*$'

    # Regular expression to remove embedded-hyper and variant tags. This class is used to
    # display links to other BBC News articles on the same/similar subject.
    embedded_hyper_reg_exp = '^.*embed*ed[_ -]*hyper.*$'

    # Regular expression to remove hypertabs and variant tags. This class is used to
    # display a tab bar at the top of an article which allows the user to switch to
    # an article (viewed on the same page) providing further info., 'in depth' analysis,
    # an editorial, a correspondant's blog entry, and such like. The ability to handle
    # a tab bar of this nature is currently beyond the scope of this recipe and
    # possibly of Calibre itself (not sure about that - TO DO - check!).
    hypertabs_reg_exp = '^.*hyper[_ -]*tabs.*$'

    # Regular expression to remove story-feature and variant tags. Eg. 'story-feature',
    # 'story-feature related narrow', 'story-feature wide', 'story-feature narrow'.
    # This class is used to add additional info. boxes, or small lists, outside of
    # the main story. TO DO: Work out a way to incorporate these neatly.
    story_feature_reg_exp = '^.*story[_ -]*feature.*$'

    # Regular expression to remove video and variant tags, Eg. 'videoInStoryB',
    # 'videoInStoryC'. This class is used to embed video.
    video_reg_exp = '^.*video.*$'

    # Regular expression to remove audio and variant tags, Eg. 'audioInStoryD'.
    # This class is used to embed audio.
    audio_reg_exp = '^.*audio.*$'

    # Regular expression to remove pictureGallery and variant tags, Eg. 'pictureGallery'.
    # This class is used to embed a photo slideshow. See also 'slideshow'
    # below.
    picture_gallery_reg_exp = '^.*picture.*$'

    # Regular expression to remove slideshow and variant tags, Eg. 'dslideshow-enclosure'.
    # This class is used to embed a slideshow (not necessarily photo) but both
    # 'slideshow' and 'pictureGallery' are used for slideshows.
    slideshow_reg_exp = '^.*slide[_ -]*show.*$'

    # Regular expression to remove social-links and variant tags. This class is used to
    # display links to a BBC bloggers main page, used in various columnist's blogs
    # (Eg. Nick Robinson, Robert Preston).
    social_links_reg_exp = '^.*social[_ -]*links.*$'

    # Regular expression to remove quote and (multi) variant tags, Eg. 'quote',
    # 'endquote', 'quote-credit', 'quote-credit-title', etc. These are usually
    # removed by 'story-feature' removal (as they are usually within them), but
    # not always. The quotation removed is always (AFAICT) in the article text
    # as well but a 2nd copy is placed in a quote tag to draw attention to it.
    # The quote class tags may or may not appear in div's.
    quote_reg_exp = '^.*quote.*$'

    # Regular expression to remove hidden and variant tags, Eg. 'hidden'.
    # The purpose of these is unclear, they seem to be an internal link to a
    # section within the article, but the text of the link (Eg. 'Continue reading
    # the main story') never seems to be displayed anyway. Removed to avoid clutter.
    # The hidden class tags may or may not appear in div's.
    hidden_reg_exp = '^.*hidden.*$'

    # Regular expression to remove comment and variant tags, Eg. 'comment-introduction'.
    # Used on the site to display text about registered users entering
    # comments.
    comment_reg_exp = '^.*comment.*$'

    # Regular expression to remove form and variant tags, Eg. 'comment-form'.
    # Used on the site to allow registered BBC users to fill in forms, typically
    # for entering comments about an article.
    form_reg_exp = '^.*form.*$'

    # Extra things to remove due to the addition of 'blq_content' in
    # keep_only_tags.

    # <div class="story-actions"> Used on sports pages for 'email' and 'print'.
    story_actions_reg_exp = '^.*story[_ -]*actions.*$'

    # <div class="bookmark-list"> Used on sports pages instead of 'share-help' (for
    # social networking links).
    bookmark_list_reg_exp = '^.*bookmark[_ -]*list.*$'

    # <div id="secondary-content" class="content-group">
    # NOTE: Don't remove class="content-group" that is needed.
    # Used on sports pages to link to 'similar stories'.
    secondary_content_reg_exp = '^.*secondary[_ -]*content.*$'

    # <div id="featured-content" class="content-group">
    # NOTE: Don't remove class="content-group" that is needed.
    # Used on sports pages to link to pages like 'tables', 'fixtures', etc.
    featured_content_reg_exp = '^.*featured[_ -]*content.*$'

    # <div id="navigation">
    # Used on sports pages to link to pages like 'tables', 'fixtures', etc.
    # Used sometimes instead of "featured-content" above.
    navigation_reg_exp = '^.*navigation.*$'

    # <a class="skip" href="#blq-container-inner">Skip to top</a>
    # Used on sports pages to link to the top of the page.
    skip_reg_exp = '^.*skip.*$'

    # Extra things to remove due to the addition of 'storycontent' in keep_only_tags,
    # which are the alterative table design based pages. The purpose of some of these
    # is not entirely clear from the pages (which are a total mess!).

    # Remove mapping based tags, Eg. <map id="world_map">
    # The dynamic maps don't seem to work during ebook creation. TO DO:
    # Investigate.
    map_reg_exp = '^.*map.*$'

    # Remove social bookmarking variation, called 'socialBookMarks'.
    social_bookmarks_reg_exp = '^.*social[_ -]*bookmarks.*$'

    # Remove page navigation tools, like 'search', 'email', 'print', called
    # 'blq-mast'.
    blq_mast_reg_exp = '^.*blq[_ -]*mast.*$'

    # Remove 'sharesb', I think this is a generic 'sharing' class. It seems to appear
    # alongside 'socialBookMarks' whenever that appears. I am removing it as well
    # under the assumption that it can appear alone as well.
    sharesb_reg_exp = '^.*sharesb.*$'

    # Remove class 'o'. The worst named user created css class of all time. The creator
    # should immediately be fired. I've seen it used to hold nothing at all but with
    # 20 or so empty lines in it. Also to hold a single link to another article.
    # Whatever it was designed to do it is not wanted by this recipe. Exact
    # match only.
    o_reg_exp = '^o$'

    # Remove 'promotopbg' and 'promobottombg', link lists. Have decided to
    # use two reg expressions to make removing this (and variants) robust.
    promo_top_reg_exp = '^.*promotopbg.*$'
    promo_bottom_reg_exp = '^.*promobottombg.*$'

    # Remove 'nlp', provides heading for link lists. Requires an exact match due to
    # risk of matching those letters in something needed, unless I see a variation
    # of 'nlp' used at a later date.
    nlp_reg_exp = '^nlp$'

    # Remove 'mva', provides embedded floating content of various types. Variant 'mvb'
    # has also now been seen. Requires an exact match of 'mva' or 'mvb' due to risk of
    # matching those letters in something needed.
    mva_or_mvb_reg_exp = '^mv[ab]$'

    # Remove 'mvtb', seems to be page navigation tools, like 'blq-mast'.
    mvtb_reg_exp = '^mvtb$'

    # Remove 'blq-toplink', class to provide a link to the top of the page.
    blq_toplink_reg_exp = '^.*blq[_ -]*top[_ -]*link.*$'

    # Remove 'products and services' links, Eg. desktop tools, alerts, and so on.
    # Eg. Class="servicev4 ukfs_services" - what a mess of a name. Have decided to
    # use two reg expressions to make removing this (and variants) robust.
    prods_services_01_reg_exp = '^.*servicev4.*$'
    prods_services_02_reg_exp = '^.*ukfs[_ -]*services.*$'

    # Remove -what I think is- some kind of navigation tools helper class, though I am
    # not sure, it's called: 'blq-rst blq-new-nav'. What I do know is it pops up
    # frequently and it is not wanted. Have decided to use two reg expressions to make
    # removing this (and variants) robust.
    blq_misc_01_reg_exp = '^.*blq[_ -]*rst.*$'
    blq_misc_02_reg_exp = '^.*blq[_ -]*new[_ -]*nav.*$'

    # Remove 'puffbox' - this may only appear inside 'storyextra', so it may not
    # need removing - I have no clue what it does other than it contains links.
    # Whatever it is - it is not part of the article and is not wanted.
    puffbox_reg_exp = '^.*puffbox.*$'

    # Remove 'sibtbg' and 'sibtbgf' - some kind of table formatting classes.
    sibtbg_reg_exp = '^.*sibtbg.*$'

    # Remove 'storyextra' - links to relevant articles and external sites.
    storyextra_reg_exp = '^.*story[_ -]*extra.*$'

    remove_tags = [
        classes('sharetools share-tools--no-event-tag'),
        dict(name='div',  attrs={'class': re.compile(story_feature_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            share_help_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            embedded_hyper_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            hypertabs_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            video_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            audio_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            picture_gallery_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            slideshow_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            quote_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            hidden_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            comment_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            story_actions_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            bookmark_list_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'id': re.compile(
            secondary_content_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'id': re.compile(
            featured_content_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'id': re.compile(
            navigation_reg_exp, re.IGNORECASE)}),
        dict(name='form', attrs={'id': re.compile(
            form_reg_exp, re.IGNORECASE)}),
        dict(attrs={'class': re.compile(
            quote_reg_exp, re.IGNORECASE)}),
        dict(attrs={'class': re.compile(
            hidden_reg_exp, re.IGNORECASE)}),
        dict(attrs={'class': re.compile(
            social_links_reg_exp, re.IGNORECASE)}),
        dict(attrs={'class': re.compile(
            comment_reg_exp, re.IGNORECASE)}),
        dict(attrs={'class': re.compile(
            skip_reg_exp, re.IGNORECASE)}),
        dict(name='map', attrs={'id': re.compile(
            map_reg_exp, re.IGNORECASE)}),
        dict(name='map', attrs={'name': re.compile(
            map_reg_exp, re.IGNORECASE)}),
        dict(name='div', attrs={'id': re.compile(
            social_bookmarks_reg_exp, re.IGNORECASE)}),
        dict(name='div', attrs={'id': re.compile(
            blq_mast_reg_exp, re.IGNORECASE)}),
        dict(name='div', attrs={'class': re.compile(
            sharesb_reg_exp, re.IGNORECASE)}),
        dict(name='div', attrs={
            'class': re.compile(o_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            promo_top_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            promo_bottom_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={
            'class': re.compile(nlp_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            mva_or_mvb_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            mvtb_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            blq_toplink_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            prods_services_01_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            prods_services_02_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            blq_misc_01_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            blq_misc_02_reg_exp, re.IGNORECASE)}),
        dict(name='div',  attrs={'class': re.compile(
            puffbox_reg_exp, re.IGNORECASE)}),
        dict(attrs={'class': re.compile(
            sibtbg_reg_exp, re.IGNORECASE)}),
        dict(attrs={'class': re.compile(
            storyextra_reg_exp, re.IGNORECASE)})
    ]

    # Uses url to create and return the 'printer friendly' version of the url.
    # In other words the 'print this page' address of the page.
    #
    # There are 3 types of urls used in the BBC site's rss feeds. There is just
    # 1 type for the standard news while there are 2 used for sports feed urls.
    # Note: Sports urls are linked from regular news feeds (Eg. 'News Home') when
    # there is a major story of interest to 'everyone'. So even if no BBC sports
    # feeds are added to 'feeds' the logic of this method is still needed to avoid
    # blank / missing / empty articles which have an index title and then no
    # body.
    def print_version(self, url):

        # Handle sports page urls type 01:
        if (url.find("go/rss/-/sport1/") != -1):
            temp_url = url.replace("go/rss/-/", "")

        # Handle sports page urls type 02:
        elif (url.find("go/rss/int/news/-/sport1/") != -1):
            temp_url = url.replace("go/rss/int/news/-/", "")

        # Handle regular news page urls:
        else:
            temp_url = url.replace("go/rss/int/news/-/", "")

        # Always add "?print=true" to the end of the url.
        print_url = temp_url + "?print=true"

        return print_url

    def canonicalize_internal_url(self, url, is_link=True):
        if url.endswith('?print=true'):
            url = url.rpartition('?')[0]
        return BasicNewsRecipe.canonicalize_internal_url(self, url, is_link=is_link)

    # Remove articles in feeds based on a string in the article title or url.
    #
    # Code logic written by: Starson17 - posted in: "Recipes - Re-usable code"
    # thread, in post with title: "Remove articles from feed", see url:
    # http://www.mobileread.com/forums/showpost.php?p=1165462&postcount=6
    # Many thanks and all credit to Starson17.
    #
    # Starson17's code has obviously been altered to suite my requirements.
    def parse_feeds(self):

        # Call parent's method.
        feeds = BasicNewsRecipe.parse_feeds(self)

        # Loop through all feeds.
        for feed in feeds:

            # Loop through all articles in feed.
            for article in feed.articles[:]:

                # Match key words and remove article if there's a match.

                # Most BBC rss feed video only 'articles' use upper case 'VIDEO'
                # as a title prefix. Just match upper case 'VIDEO', so that
                # articles like 'Video game banned' won't be matched and
                # removed.
                if 'VIDEO' in article.title:
                    feed.articles.remove(article)

                # Most BBC rss feed audio only 'articles' use upper case 'AUDIO'
                # as a title prefix. Just match upper case 'AUDIO', so that
                # articles like 'Hi-Def audio...' won't be matched and removed.
                elif 'AUDIO' in article.title:
                    feed.articles.remove(article)

                # Most BBC rss feed photo slideshow 'articles' use 'In Pictures',
                # 'In pictures', and 'in pictures', somewhere in their title.
                # Match any case of that phrase.
                elif 'IN PICTURES' in article.title.upper():
                    feed.articles.remove(article)

                # As above, but user contributed pictures. Match any case.
                elif 'YOUR PICTURES' in article.title.upper():
                    feed.articles.remove(article)

                # 'Sportsday Live' are articles which contain a constantly and
                # dynamically updated 'running commentary' during a live sporting
                # event. Match any case.
                elif 'SPORTSDAY LIVE' in article.title.upper():
                    feed.articles.remove(article)

                # Sometimes 'Sportsday Live' (above) becomes 'Live - Sport Name'.
                # These are being matched below using 'Live - ' because removing all
                # articles with 'live' in their titles would remove some articles
                # that are in fact not live sports pages. Match any case.
                elif 'LIVE - ' in article.title.upper():
                    feed.articles.remove(article)

                # 'Quiz of the week' is a Flash player weekly news quiz. Match only
                # the 'Quiz of the' part in anticipation of monthly and yearly
                # variants. Match any case.
                elif 'QUIZ OF THE' in article.title.upper():
                    feed.articles.remove(article)

                # Remove articles with 'scorecards' in the url. These are BBC sports
                # pages which just display a cricket scorecard. The pages have a mass
                # of table and css entries to display the scorecards nicely. Probably
                # could make them work with this recipe, but might take a whole day
                # of work to sort out all the css - basically a formatting
                # nightmare.
                elif 'scorecards' in article.url:
                    feed.articles.remove(article)

        return feeds

# End of class and file.

Cette recette explore seulement la partie émergée de l’iceberg quand il s’agit de la puissance de calibre. Pour mieux explorer les capacités de calibre nous examinerons un exemple plus complexe de vie réelle dans la prochaine section.

Exemple de la vie réelle

Un exemple de la vie réelle raisonnablement complexe qui expose plus de l”API de BasicNewsRecipe est la recette pour The New York Times

import string, re
from calibre import strftime
from calibre.web.feeds.recipes import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup

class NYTimes(BasicNewsRecipe):

    title       = 'The New York Times'
    __author__  = 'Kovid Goyal'
    description = 'Daily news from the New York Times'
    timefmt = ' [%a, %d %b, %Y]'
    needs_subscription = True
    remove_tags_before = dict(id='article')
    remove_tags_after  = dict(id='article')
    remove_tags = [dict(attrs={'class':['articleTools', 'post-tools', 'side_tool', 'nextArticleLink clearfix']}),
                dict(id=['footer', 'toolsRight', 'articleInline', 'navigation', 'archive', 'side_search', 'blog_sidebar', 'side_tool', 'side_index']),
                dict(name=['script', 'noscript', 'style'])]
    encoding = 'cp1252'
    no_stylesheets = True
    extra_css = 'h1 {font: sans-serif large;}\n.byline {font:monospace;}'

    def get_browser(self):
        br = BasicNewsRecipe.get_browser()
        if self.username is not None and self.password is not None:
            br.open('https://www.nytimes.com/auth/login')
            br.select_form(name='login')
            br['USERID']   = self.username
            br['PASSWORD'] = self.password
            br.submit()
        return br

    def parse_index(self):
        soup = self.index_to_soup('https://www.nytimes.com/pages/todayspaper/index.html')

        def feed_title(div):
            return ''.join(div.findAll(text=True, recursive=False)).strip()

        articles = {}
        key = None
        ans = []
        for div in soup.findAll(True,
             attrs={'class':['section-headline', 'story', 'story headline']}):

             if div['class'] == 'section-headline':
                 key = string.capwords(feed_title(div))
                 articles[key] = []
                 ans.append(key)

             elif div['class'] in ['story', 'story headline']:
                 a = div.find('a', href=True)
                 if not a:
                     continue
                 url = re.sub(r'\?.*', '', a['href'])
                 url += '?pagewanted=all'
                 title = self.tag_to_string(a, use_alt=True).strip()
                 description = ''
                 pubdate = strftime('%a, %d %b')
                 summary = div.find(True, attrs={'class':'summary'})
                 if summary:
                     description = self.tag_to_string(summary, use_alt=False)

                 feed = key if key is not None else 'Uncategorized'
                 if not articles.has_key(feed):
                     articles[feed] = []
                 if not 'podcasts' in url:
                     articles[feed].append(
                               dict(title=title, url=url, date=pubdate,
                                    description=description,
                                    content=''))
        ans = self.sort_index_by(ans, {'The Front Page':-1, 'Dining In, Dining Out':1, 'Obituaries':2})
        ans = [(key, articles[key]) for key in ans if articles.has_key(key)]
        return ans

    def preprocess_html(self, soup):
        refresh = soup.find('meta', {'http-equiv':'refresh'})
        if refresh is None:
            return soup
        content = refresh.get('content').partition('=')[2]
        raw = self.browser.open('https://www.nytimes.com'+content).read()
        return BeautifulSoup(raw.decode('cp1252', 'replace'))

Nous voyons plusieurs nouvelles fonctionnalités dans cette recipe. En premier, nous avons:

timefmt = ' [%a, %d %b, %Y]'

Ceci règle le temps affiché sur la page de garde du livre numérique créé au format , Day, Day_Number Month, Year. Voir timefmt.

Voyons maintenant un groupe de directives pour nettoyer l”:term:` HTML` téléchargé:

remove_tags_before = dict(name='h1')
remove_tags_after  = dict(id='footer')
remove_tags = ...

Celle-ci supprime tout avant la première balise <h1> et tout ce qui se trouve après le première balise dont l’id est footer. Voir remove_tags, remove_tags_before, remove_tags_after.

La prochaine fonctionnalité intéressante est:

needs_subscription = True
...
def get_browser(self):
    ...

needs_subscription = True dit à calibre que cette recette nécessite un nom d’utilisateur et un mot de passe pour accéder au contenu. Ceci amène calibre à demander après un nom d’utilisateur et un mot de passe à chaque fois que vous essayez d’utiliser cette recette. Le code dans calibre.web.feeds.news.BasicNewsRecipe.get_browser() fait réellement l’ouverture de session sur le site Web de NYT. Une fois connecté, calibre utilisera la même instance, connectée, du navigateur pour récupérer tout le contenu. Voir mécaniser pour comprendre le code dans get_browser.

Une autre nouvelle fonctionnalité est la méthode calibre.web.feeds.news.BasicNewsRecipe.parse_index(). Sont travail est d’aller sur https://www.nytimes.com/pages/todayspaper/index.html et de récupérer la liste des articles qui apparaissent dans le journal du jour. Beaucoup plus complexe que d’utiliser simplement le RSS, la recette crée un livre numérique qui correspond pratiquement au journal du jour. parse_index fait une forte utilisation de BeautifulSoup pour examiner la page web quotidienne. Vous pouvez aussi en utiliser d’autres, de plus modernes analyseurs si vous n’aimez pas BeautifulSoup. calibre est fourni avec lxml et html5lib, qui sont les analyseurs recommandés. Pour les utiliser, remplacer l’appel à index_to_soup() avec le suivant:

raw = self.index_to_soup(url, raw=True)
# For html5lib
import html5lib
root = html5lib.parse(raw, namespaceHTMLElements=False, treebuilder='lxml')
# For the lxml html 4 parser
from lxml import html
root = html.fromstring(raw)

La nouvelle fonctionnalité finale est la méthode calibre.web.feeds.news.BasicNewsRecipe.preprocess_html(). Elle peut être employée pour exécuter des transformations quelconques sur chaque page HTML téléchargée. Ici elle est employée pour éviter les publicités que le nytimes place avant chaque article.

Astuces pour développer de nouvelles recettes

La meilleure manière de développer de nouvelles recettes est d’utiliser l’interface de commande en ligne. Créer la recette en utilisant votre éditeur Python favori et sauvegardez la dans un fichier nommé myrecipe.recipe. L’extension .recipe est obligatoire. Vous pouvez télécharger le contenu qu’utilise cette recette avec la commande:

ebook-convert myrecipe.recipe .epub --test -vv --debug-pipeline debug

La commande ebook-convert téléchargera toutes les pages web et les enregistrera dans le fichier EPUB myrecipe.epub. L’option -vv fait en sorte que ebook-convert renvoie beaucoup d’informations sur ce qu’il fait. L’option ebook-convert-recipe-input --test fait qu’il ne télécharge que quelques articles d’au maximum deux flux. En outre, ebook-convert déposera l’HTML téléchargé dans le répertoire debug/input, où debug est le répertoire que vous avez spécifié dans l’option ebook-convert --debug-pipeline.

Une fois le téléchargement terminé, vous pouvez regarder l’HTML téléchargé en ouvrant le fichier debug/input/index.html dans un navigateur. Une fois que vous êtes satisfait que le téléchargement et le pré-traitement se sont déroulés correctement, vous pouvez générer des livres numériques dans différents formats comme montré ci-dessous:

ebook-convert myrecipe.recipe myrecipe.epub
ebook-convert myrecipe.recipe myrecipe.mobi
...

Si vous êtes satisfait de votre recette et que vous sentez qu’il y a suffisamment de demandes pour l’inclure dans le jeu de recettes intégrées, déposez votre recette sur le forum calibre de recettes pour la partager avec les autres utilisateurs de calibre.

Note

Sous macOS, les outils en de ligne de commande sont à l’intérieur de la suite logicielle calibre, par exemple, si vous installez calibre dans /Applications les outils de ligne de commande sont dans /Applications/calibre.app/Contents/console.app/Contents/MacOS/.

Voir aussi

ebook-convert
L’interface en ligne de commande pour toute conversion de livre numérique

Lectures recommandées

Pour en apprendre plus sur l’écriture avancée de recettes utilisant quelques unes des facilités disponibles dans BasicNewsRecipe, vous devriez consulter les sources suivantes :

Documentation API
Documentation sur la classe BasicNewsRecipe et toutes ses méthodes importantes et champs.
BasicNewsRecipe
Le code source de BasicNewsRecipe
Recettes intégrées
Le code source des recettes intégrées qui est fourni avec calibre
Le forum de recettes calibre
Un bon nombre d’auteurs bien informés des recettes calibre traînent ici.