Code Duplication    Length = 21-29 lines in 27 locations

comics.py 27 locations

@@ 974-1000 (lines=27) @@
971
        }
972
973
974
class ImogenQuest(GenericNavigableComic):
975
    """Class to retrieve Imogen Quest comics."""
976
    # Also on http://imoquest.tumblr.com
977
    name = 'imogen'
978
    long_name = 'Imogen Quest'
979
    url = 'http://imogenquest.net'
980
    get_first_comic_link = get_div_navfirst_a
981
    get_navi_link = get_a_rel_next
982
983
    @classmethod
984
    def get_comic_info(cls, soup, link):
985
        """Get information about a particular comics."""
986
        title = soup.find('h2', class_='post-title').string
987
        author = soup.find("span", class_="post-author").find("a").string
988
        date_str = soup.find('span', class_='post-date').string
989
        day = string_to_date(date_str, '%B %d, %Y')
990
        imgs = soup.find('div', class_='comicpane').find_all('img')
991
        assert all(i['alt'] == i['title'] for i in imgs)
992
        title2 = imgs[0]['title']
993
        return {
994
            'day': day.day,
995
            'month': day.month,
996
            'year': day.year,
997
            'img': [i['src'] for i in imgs],
998
            'title': title,
999
            'title2': title2,
1000
            'author': author,
1001
        }
1002
1003
@@ 1203-1226 (lines=24) @@
1200
    url = 'http://english.bouletcorp.com'
1201
1202
1203
class AmazingSuperPowers(GenericNavigableComic):
1204
    """Class to retrieve Amazing Super Powers comics."""
1205
    name = 'asp'
1206
    long_name = 'Amazing Super Powers'
1207
    url = 'http://www.amazingsuperpowers.com'
1208
    get_first_comic_link = get_a_navi_navifirst
1209
    get_navi_link = get_a_navi_navinext
1210
1211
    @classmethod
1212
    def get_comic_info(cls, soup, link):
1213
        """Get information about a particular comics."""
1214
        author = soup.find("span", class_="post-author").find("a").string
1215
        date_str = soup.find('span', class_='post-date').string
1216
        day = string_to_date(date_str, "%B %d, %Y")
1217
        imgs = soup.find('div', id='comic').find_all('img')
1218
        title = ' '.join(i['title'] for i in imgs)
1219
        assert all(i['alt'] == i['title'] for i in imgs)
1220
        return {
1221
            'title': title,
1222
            'author': author,
1223
            'img': [img['src'] for img in imgs],
1224
            'day': day.day,
1225
            'month': day.month,
1226
            'year': day.year
1227
        }
1228
1229
@@ 720-743 (lines=24) @@
717
        }
718
719
720
class OneOneOneOneComic(GenericComicNotWorking, GenericNavigableComic):
721
    """Class to retrieve 1111 Comics."""
722
    # Also on http://comics1111.tumblr.com
723
    # Also on https://tapastic.com/series/1111-Comics
724
    name = '1111'
725
    long_name = '1111 Comics'
726
    url = 'http://www.1111comics.me'
727
    _categories = ('ONEONEONEONE', )
728
    get_first_comic_link = get_div_navfirst_a
729
    get_navi_link = get_link_rel_next
730
731
    @classmethod
732
    def get_comic_info(cls, soup, link):
733
        """Get information about a particular comics."""
734
        title = soup.find('h1', class_='comic-title').find('a').string
735
        date_str = soup.find('header', class_='comic-meta entry-meta').find('a').string
736
        day = string_to_date(date_str, "%B %d, %Y")
737
        imgs = soup.find_all('meta', property='og:image')
738
        return {
739
            'title': title,
740
            'month': day.month,
741
            'year': day.year,
742
            'day': day.day,
743
            'img': [i['content'] for i in imgs],
744
        }
745
746
@@ 948-970 (lines=23) @@
945
        }
946
947
948
class TheGentlemanArmchair(GenericNavigableComic):
949
    """Class to retrieve The Gentleman Armchair comics."""
950
    name = 'gentlemanarmchair'
951
    long_name = 'The Gentleman Armchair'
952
    url = 'http://thegentlemansarmchair.com'
953
    get_first_comic_link = get_a_navi_navifirst
954
    get_navi_link = get_link_rel_next
955
956
    @classmethod
957
    def get_comic_info(cls, soup, link):
958
        """Get information about a particular comics."""
959
        title = soup.find('h2', class_='post-title').string
960
        author = soup.find("span", class_="post-author").find("a").string
961
        date_str = soup.find('span', class_='post-date').string
962
        day = string_to_date(date_str, "%B %d, %Y")
963
        imgs = soup.find('div', id='comic').find_all('img')
964
        return {
965
            'img': [i['src'] for i in imgs],
966
            'title': title,
967
            'author': author,
968
            'month': day.month,
969
            'year': day.year,
970
            'day': day.day,
971
        }
972
973
@@ 747-768 (lines=22) @@
744
        }
745
746
747
class AngryAtNothing(GenericDeletedComic, GenericNavigableComic):
748
    """Class to retrieve Angry at Nothing comics."""
749
    # Also on http://tapastic.com/series/Comics-yeah-definitely-comics-
750
    # Also on http://angryatnothing.tumblr.com
751
    name = 'angry'
752
    long_name = 'Angry At Nothing'
753
    url = 'http://www.angryatnothing.net'
754
    get_first_comic_link = get_div_navfirst_a
755
    get_navi_link = get_a_rel_next
756
757
    @classmethod
758
    def get_comic_info(cls, soup, link):
759
        """Get information about a particular comics."""
760
        title = soup.find('h1', class_='comic-title').find('a').string
761
        date_str = soup.find('header', class_='comic-meta entry-meta').find('a').string
762
        day = string_to_date(date_str, "%B %d, %Y")
763
        imgs = soup.find_all('meta', property='og:image')
764
        return {
765
            'title': title,
766
            'month': day.month,
767
            'year': day.year,
768
            'day': day.day,
769
            'img': [i['content'] for i in imgs],
770
        }
771
@@ 1904-1930 (lines=27) @@
1901
        }
1902
1903
1904
class PicturesInBoxes(GenericNavigableComic):
1905
    """Class to retrieve Pictures In Boxes comics."""
1906
    # Also on https://picturesinboxescomic.tumblr.com
1907
    name = 'picturesinboxes'
1908
    long_name = 'Pictures in Boxes'
1909
    url = 'http://www.picturesinboxes.com'
1910
    get_navi_link = get_a_navi_navinext
1911
    get_first_comic_link = simulate_first_link
1912
    first_url = 'http://www.picturesinboxes.com/2013/10/26/tetris/'
1913
1914
    @classmethod
1915
    def get_comic_info(cls, soup, link):
1916
        """Get information about a particular comics."""
1917
        title = soup.find('h2', class_='post-title').string
1918
        author = soup.find("span", class_="post-author").find("a").string
1919
        date_str = soup.find('span', class_='post-date').string
1920
        day = string_to_date(date_str, '%B %d, %Y')
1921
        imgs = soup.find('div', class_='comicpane').find_all('img')
1922
        assert imgs
1923
        assert all(i['title'] == i['alt'] == title for i in imgs)
1924
        return {
1925
            'day': day.day,
1926
            'month': day.month,
1927
            'year': day.year,
1928
            'img': [i['src'] for i in imgs],
1929
            'title': title,
1930
            'author': author,
1931
        }
1932
1933
@@ 1792-1816 (lines=25) @@
1789
        }
1790
1791
1792
class MouseBearComedy(GenericComicNotWorking):  # Website has changed
1793
    """Class to retrieve Mouse Bear Comedy comics."""
1794
    # Also on http://mousebearcomedy.tumblr.com
1795
    name = 'mousebear'
1796
    long_name = 'Mouse Bear Comedy'
1797
    url = 'http://www.mousebearcomedy.com'
1798
    get_first_comic_link = get_a_navi_navifirst
1799
    get_navi_link = get_a_navi_comicnavnext_navinext
1800
1801
    @classmethod
1802
    def get_comic_info(cls, soup, link):
1803
        """Get information about a particular comics."""
1804
        title = soup.find('h2', class_='post-title').string
1805
        author = soup.find("span", class_="post-author").find("a").string
1806
        date_str = soup.find("span", class_="post-date").string
1807
        day = string_to_date(date_str, '%B %d, %Y')
1808
        imgs = soup.find("div", id="comic").find_all("img")
1809
        assert all(i['alt'] == i['title'] == title for i in imgs)
1810
        return {
1811
            'day': day.day,
1812
            'month': day.month,
1813
            'year': day.year,
1814
            'img': [i['src'] for i in imgs],
1815
            'title': title,
1816
            'author': author,
1817
        }
1818
1819
@@ 2883-2907 (lines=25) @@
2880
    first_url = 'http://www.commitstrip.com/fr/2012/02/22/interview/'
2881
2882
2883
class CommitStripEn(GenericCommitStrip):
2884
    """Class to retrieve Commit Strips in English."""
2885
    name = 'commit_en'
2886
    long_name = 'Commit Strip (En)'
2887
    url = 'http://www.commitstrip.com/en'
2888
    first_url = 'http://www.commitstrip.com/en/2012/02/22/interview/'
2889
2890
2891
class GenericBoumerie(GenericNavigableComic):
2892
    """Generic class to retrieve Boumeries comics in different languages."""
2893
    # Also on http://boumeries.tumblr.com
2894
    get_first_comic_link = get_a_navi_navifirst
2895
    get_navi_link = get_link_rel_next
2896
    date_format = NotImplemented
2897
    lang = NotImplemented
2898
2899
    @classmethod
2900
    def get_comic_info(cls, soup, link):
2901
        """Get information about a particular comics."""
2902
        title = soup.find('h2', class_='post-title').string
2903
        short_url = soup.find('link', rel='shortlink')['href']
2904
        author = soup.find("span", class_="post-author").find("a").string
2905
        date_str = soup.find('span', class_='post-date').string
2906
        day = string_to_date(date_str, cls.date_format, cls.lang)
2907
        imgs = soup.find('div', id='comic').find_all('img')
2908
        assert all(i['alt'] == i['title'] for i in imgs)
2909
        return {
2910
            'short_url': short_url,
@@ 2629-2654 (lines=26) @@
2626
        return {
2627
            'img': [i['src'] for i in imgs],
2628
            'title': title,
2629
            'alt': alt,
2630
            'author': author,
2631
            'day': day.day,
2632
            'month': day.month,
2633
            'year': day.year
2634
        }
2635
2636
2637
class TheAwkwardYeti(GenericNavigableComic):
2638
    """Class to retrieve The Awkward Yeti comics."""
2639
    # Also on http://www.gocomics.com/the-awkward-yeti
2640
    # Also on http://larstheyeti.tumblr.com
2641
    # Also on https://tapastic.com/series/TheAwkwardYeti
2642
    name = 'yeti'
2643
    long_name = 'The Awkward Yeti'
2644
    url = 'http://theawkwardyeti.com'
2645
    _categories = ('YETI', )
2646
    get_first_comic_link = get_a_navi_navifirst
2647
    get_navi_link = get_link_rel_next
2648
2649
    @classmethod
2650
    def get_comic_info(cls, soup, link):
2651
        """Get information about a particular comics."""
2652
        title = soup.find('h2', class_='post-title').string
2653
        date_str = soup.find("span", class_="post-date").string
2654
        day = string_to_date(date_str, "%B %d, %Y")
2655
        imgs = soup.find("div", id="comic").find_all("img")
2656
        assert all(idx > 0 or i['alt'] == i['title'] for idx, i in enumerate(imgs))
2657
        return {
@@ 2571-2595 (lines=25) @@
2568
        return {
2569
            'img': [i['src'] for i in imgs],
2570
            'title': title,
2571
            'alt': alt,
2572
            'author': author,
2573
            'day': day.day,
2574
            'month': day.month,
2575
            'year': day.year
2576
        }
2577
2578
2579
class EveryDayBlues(GenericDeletedComic, GenericNavigableComic):
2580
    """Class to retrieve EveryDayBlues Comics."""
2581
    name = "blues"
2582
    long_name = "Every Day Blues"
2583
    url = "http://everydayblues.net"
2584
    get_first_comic_link = get_a_navi_navifirst
2585
    get_navi_link = get_link_rel_next
2586
2587
    @classmethod
2588
    def get_comic_info(cls, soup, link):
2589
        """Get information about a particular comics."""
2590
        title = soup.find("h2", class_="post-title").string
2591
        author = soup.find("span", class_="post-author").find("a").string
2592
        date_str = soup.find("span", class_="post-date").string
2593
        day = string_to_date(date_str, "%d. %B %Y", "de_DE.utf8")
2594
        imgs = soup.find("div", id="comic").find_all("img")
2595
        assert all(i['alt'] == i['title'] == title for i in imgs)
2596
        assert len(imgs) <= 1, imgs
2597
        return {
2598
            'img': [i['src'] for i in imgs],
@@ 2740-2768 (lines=29) @@
2737
        return {
2738
            'img': [i['src'] for i in imgs],
2739
            'title': title,
2740
            'alt': alt,
2741
            'author': author,
2742
            'day': day.day,
2743
            'month': day.month,
2744
            'year': day.year
2745
        }
2746
2747
2748
class TalesOfAbsurdity(GenericNavigableComic):
2749
    """Class to retrieve Tales Of Absurdity comics."""
2750
    # Also on http://tapastic.com/series/Tales-Of-Absurdity
2751
    # Also on http://talesofabsurdity.tumblr.com
2752
    name = 'absurdity'
2753
    long_name = 'Tales of Absurdity'
2754
    url = 'http://talesofabsurdity.com'
2755
    _categories = ('ABSURDITY', )
2756
    get_first_comic_link = get_a_navi_navifirst
2757
    get_navi_link = get_a_navi_comicnavnext_navinext
2758
2759
    @classmethod
2760
    def get_comic_info(cls, soup, link):
2761
        """Get information about a particular comics."""
2762
        title = soup.find('h2', class_='post-title').string
2763
        author = soup.find("span", class_="post-author").find("a").string
2764
        date_str = soup.find("span", class_="post-date").string
2765
        day = string_to_date(date_str, "%B %d, %Y")
2766
        imgs = soup.find("div", id="comic").find_all("img")
2767
        assert all(i['alt'] == i['title'] for i in imgs)
2768
        alt = imgs[0]['alt'] if imgs else ""
2769
        return {
2770
            'img': [i['src'] for i in imgs],
2771
            'title': title,
@@ 2678-2706 (lines=29) @@
2675
    def get_comic_info(cls, soup, link):
2676
        """Get information about a particular comics."""
2677
        post = soup.find('div', class_='post-content')
2678
        title = post.find('h2', class_='post-title').string
2679
        imgs = post.find("div", class_="entry").find_all("img")
2680
        return {
2681
            'title': title,
2682
            'img': [i['src'] for i in imgs],
2683
        }
2684
2685
2686
class MisterAndMe(GenericNavigableComic):
2687
    """Class to retrieve Mister & Me Comics."""
2688
    # Also on http://www.gocomics.com/mister-and-me
2689
    # Also on https://tapastic.com/series/Mister-and-Me
2690
    name = 'mister'
2691
    long_name = 'Mister & Me'
2692
    url = 'http://www.mister-and-me.com'
2693
    get_first_comic_link = get_a_comicnavbase_comicnavfirst
2694
    get_navi_link = get_link_rel_next
2695
2696
    @classmethod
2697
    def get_comic_info(cls, soup, link):
2698
        """Get information about a particular comics."""
2699
        title = soup.find('h2', class_='post-title').string
2700
        author = soup.find("span", class_="post-author").find("a").string
2701
        date_str = soup.find("span", class_="post-date").string
2702
        day = string_to_date(date_str, "%B %d, %Y")
2703
        imgs = soup.find("div", id="comic").find_all("img")
2704
        assert all(i['alt'] == i['title'] for i in imgs)
2705
        assert len(imgs) <= 1, imgs
2706
        alt = imgs[0]['alt'] if imgs else ""
2707
        return {
2708
            'img': [i['src'] for i in imgs],
2709
            'title': title,
@@ 2966-2992 (lines=27) @@
2963
        return {
2964
            'title': title,
2965
            'description': desc,
2966
            'url2': short_url,
2967
            'img': [i['src'] for i in imgs],
2968
            'month': day.month,
2969
            'year': day.year,
2970
            'day': day.day,
2971
        }
2972
2973
2974
class Optipess(GenericNavigableComic):
2975
    """Class to retrieve Optipess comics."""
2976
    name = 'optipess'
2977
    long_name = 'Optipess'
2978
    url = 'http://www.optipess.com'
2979
    get_first_comic_link = get_a_navi_navifirst
2980
    get_navi_link = get_link_rel_next
2981
2982
    @classmethod
2983
    def get_comic_info(cls, soup, link):
2984
        """Get information about a particular comics."""
2985
        title = soup.find('h2', class_='post-title').string
2986
        author = soup.find("span", class_="post-author").find("a").string
2987
        comic = soup.find('div', id='comic')
2988
        imgs = comic.find_all('img') if comic else []
2989
        alt = imgs[0]['title'] if imgs else ""
2990
        assert all(i['alt'] == i['title'] == alt for i in imgs)
2991
        date_str = soup.find('span', class_='post-date').string
2992
        day = string_to_date(date_str, "%B %d, %Y")
2993
        return {
2994
            'title': title,
2995
            'alt': alt,
@@ 2599-2625 (lines=27) @@
2596
        assert len(imgs) <= 1, imgs
2597
        return {
2598
            'img': [i['src'] for i in imgs],
2599
            'title': title,
2600
            'author': author,
2601
            'day': day.day,
2602
            'month': day.month,
2603
            'year': day.year
2604
        }
2605
2606
2607
class BiterComics(GenericNavigableComic):
2608
    """Class to retrieve Biter Comics."""
2609
    name = "biter"
2610
    long_name = "Biter Comics"
2611
    url = "http://www.bitercomics.com"
2612
    get_first_comic_link = get_a_navi_navifirst
2613
    get_navi_link = get_link_rel_next
2614
2615
    @classmethod
2616
    def get_comic_info(cls, soup, link):
2617
        """Get information about a particular comics."""
2618
        title = soup.find("h1", class_="entry-title").string
2619
        author = soup.find("span", class_="author vcard").find("a").string
2620
        date_str = soup.find("span", class_="entry-date").string
2621
        day = string_to_date(date_str, "%B %d, %Y")
2622
        imgs = soup.find("div", id="comic").find_all("img")
2623
        assert all(i['alt'] == i['title'] for i in imgs)
2624
        assert len(imgs) == 1, imgs
2625
        alt = imgs[0]['alt']
2626
        return {
2627
            'img': [i['src'] for i in imgs],
2628
            'title': title,
@@ 2049-2075 (lines=27) @@
2046
    _categories = ('TUNEYTOONS', )
2047
2048
2049
class CompletelySeriousComics(GenericNavigableComic):
2050
    """Class to retrieve Completely Serious comics."""
2051
    name = 'completelyserious'
2052
    long_name = 'Completely Serious Comics'
2053
    url = 'http://completelyseriouscomics.com'
2054
    get_first_comic_link = get_a_navi_navifirst
2055
    get_navi_link = get_a_navi_navinext
2056
2057
    @classmethod
2058
    def get_comic_info(cls, soup, link):
2059
        """Get information about a particular comics."""
2060
        title = soup.find('h2', class_='post-title').string
2061
        author = soup.find('span', class_='post-author').contents[1].string
2062
        date_str = soup.find('span', class_='post-date').string
2063
        day = string_to_date(date_str, '%B %d, %Y')
2064
        imgs = soup.find('div', class_='comicpane').find_all('img')
2065
        assert imgs
2066
        alt = imgs[0]['title']
2067
        assert all(i['title'] == i['alt'] == alt for i in imgs)
2068
        return {
2069
            'month': day.month,
2070
            'year': day.year,
2071
            'day': day.day,
2072
            'img': [i['src'] for i in imgs],
2073
            'title': title,
2074
            'alt': alt,
2075
            'author': author,
2076
        }
2077
2078
@@ 2772-2797 (lines=26) @@
2769
        return {
2770
            'img': [i['src'] for i in imgs],
2771
            'title': title,
2772
            'alt': alt,
2773
            'author': author,
2774
            'day': day.day,
2775
            'month': day.month,
2776
            'year': day.year
2777
        }
2778
2779
2780
class EndlessOrigami(GenericComicNotWorking, GenericNavigableComic):  # Nav not working
2781
    """Class to retrieve Endless Origami Comics."""
2782
    name = "origami"
2783
    long_name = "Endless Origami"
2784
    url = "http://endlessorigami.com"
2785
    get_first_comic_link = get_a_navi_navifirst
2786
    get_navi_link = get_link_rel_next
2787
2788
    @classmethod
2789
    def get_comic_info(cls, soup, link):
2790
        """Get information about a particular comics."""
2791
        title = soup.find('h2', class_='post-title').string
2792
        author = soup.find("span", class_="post-author").find("a").string
2793
        date_str = soup.find("span", class_="post-date").string
2794
        day = string_to_date(date_str, "%B %d, %Y")
2795
        imgs = soup.find("div", id="comic").find_all("img")
2796
        assert all(i['alt'] == i['title'] for i in imgs)
2797
        alt = imgs[0]['alt'] if imgs else ""
2798
        return {
2799
            'img': [i['src'] for i in imgs],
2800
            'title': title,
@@ 2260-2285 (lines=26) @@
2257
        return reversed(get_soup_at_url(archive_url).find('tbody').find_all('tr'))
2258
2259
2260
class HappleTea(GenericNavigableComic):
2261
    """Class to retrieve Happle Tea Comics."""
2262
    name = 'happletea'
2263
    long_name = 'Happle Tea'
2264
    url = 'http://www.happletea.com'
2265
    get_first_comic_link = get_a_navi_navifirst
2266
    get_navi_link = get_link_rel_next
2267
2268
    @classmethod
2269
    def get_comic_info(cls, soup, link):
2270
        """Get information about a particular comics."""
2271
        imgs = soup.find('div', id='comic').find_all('img')
2272
        post = soup.find('div', class_='post-content')
2273
        title = post.find('h2', class_='post-title').string
2274
        author = post.find('a', rel='author').string
2275
        date_str = post.find('span', class_='post-date').string
2276
        day = string_to_date(date_str, "%B %d, %Y")
2277
        assert all(i['alt'] == i['title'] for i in imgs)
2278
        return {
2279
            'title': title,
2280
            'img': [i['src'] for i in imgs],
2281
            'alt': ''.join(i['alt'] for i in imgs),
2282
            'month': day.month,
2283
            'year': day.year,
2284
            'day': day.day,
2285
            'author': author,
2286
        }
2287
2288
@@ 2441-2465 (lines=25) @@
2438
        }
2439
2440
2441
class LonnieMillsap(GenericNavigableComic):
2442
    """Class to retrieve Lonnie Millsap's comics."""
2443
    name = 'millsap'
2444
    long_name = 'Lonnie Millsap'
2445
    url = 'http://www.lonniemillsap.com'
2446
    get_navi_link = get_link_rel_next
2447
    get_first_comic_link = simulate_first_link
2448
    first_url = 'http://www.lonniemillsap.com/?p=42'
2449
2450
    @classmethod
2451
    def get_comic_info(cls, soup, link):
2452
        """Get information about a particular comics."""
2453
        title = soup.find('h2', class_='post-title').string
2454
        post = soup.find('div', class_='post-content')
2455
        author = post.find("span", class_="post-author").find("a").string
2456
        date_str = post.find("span", class_="post-date").string
2457
        day = string_to_date(date_str, "%B %d, %Y")
2458
        imgs = post.find("div", class_="entry").find_all("img")
2459
        return {
2460
            'title': title,
2461
            'author': author,
2462
            'img': [i['src'] for i in imgs],
2463
            'month': day.month,
2464
            'year': day.year,
2465
            'day': day.day,
2466
        }
2467
2468
@@ 2137-2161 (lines=25) @@
2134
        }
2135
2136
2137
class ChuckleADuck(GenericNavigableComic):
2138
    """Class to retrieve Chuckle-A-Duck comics."""
2139
    name = 'chuckleaduck'
2140
    long_name = 'Chuckle-A-duck'
2141
    url = 'http://chuckleaduck.com'
2142
    get_first_comic_link = get_div_navfirst_a
2143
    get_navi_link = get_link_rel_next
2144
2145
    @classmethod
2146
    def get_comic_info(cls, soup, link):
2147
        """Get information about a particular comics."""
2148
        date_str = soup.find('span', class_='post-date').string
2149
        day = string_to_date(remove_st_nd_rd_th_from_date(date_str), "%B %d, %Y")
2150
        author = soup.find('span', class_='post-author').string
2151
        div = soup.find('div', id='comic')
2152
        imgs = div.find_all('img') if div else []
2153
        title = imgs[0]['title'] if imgs else ""
2154
        assert all(i['title'] == i['alt'] == title for i in imgs)
2155
        return {
2156
            'month': day.month,
2157
            'year': day.year,
2158
            'day': day.day,
2159
            'img': [i['src'] for i in imgs],
2160
            'title': title,
2161
            'author': author,
2162
        }
2163
2164
@@ 3294-3317 (lines=24) @@
3291
    @classmethod
3292
    def get_comic_info(cls, soup, link):
3293
        """Get information about a particular comics."""
3294
        title = soup.find('title').string
3295
        imgs = soup.find_all('meta', property='og:image')
3296
        return {
3297
            'img': [i['content'] for i in imgs],
3298
            'title': title,
3299
        }
3300
3301
3302
class Ubertool(GenericNavigableComic):
3303
    """Class to retrieve Ubertool comics."""
3304
    # Also on https://ubertool.tumblr.com
3305
    # Also on https://tapastic.com/series/ubertool
3306
    name = 'ubertool'
3307
    long_name = 'Ubertool'
3308
    url = 'http://ubertoolcomic.com'
3309
    _categories = ('UBERTOOL', )
3310
    get_first_comic_link = get_a_comicnavbase_comicnavfirst
3311
    get_navi_link = get_a_comicnavbase_comicnavnext
3312
3313
    @classmethod
3314
    def get_comic_info(cls, soup, link):
3315
        """Get information about a particular comics."""
3316
        title = soup.find('h2', class_='post-title').string
3317
        date_str = soup.find('span', class_='post-date').string
3318
        day = string_to_date(date_str, "%B %d, %Y")
3319
        imgs = soup.find('div', id='comic').find_all('img')
3320
        return {
@@ 694-716 (lines=23) @@
691
        }
692
693
694
class PenelopeBagieu(GenericNavigableComic):
695
    """Class to retrieve comics from Penelope Bagieu's blog."""
696
    name = 'bagieu'
697
    long_name = 'Ma vie est tout a fait fascinante (Bagieu)'
698
    url = 'http://www.penelope-jolicoeur.com'
699
    _categories = ('FRANCAIS', )
700
    get_navi_link = get_link_rel_next
701
    get_first_comic_link = simulate_first_link
702
    first_url = 'http://www.penelope-jolicoeur.com/2007/02/ma-vie-mon-oeuv.html'
703
704
    @classmethod
705
    def get_comic_info(cls, soup, link):
706
        """Get information about a particular comics."""
707
        date_str = soup.find('h2', class_='date-header').string
708
        day = string_to_date(date_str, "%A %d %B %Y", "fr_FR.utf8")
709
        imgs = soup.find('div', class_='entry-body').find_all('img')
710
        title = soup.find('h3', class_='entry-header').string
711
        return {
712
            'title': title,
713
            'img': [i['src'] for i in imgs],
714
            'month': day.month,
715
            'year': day.year,
716
            'day': day.day,
717
        }
718
719
@@ 3567-3587 (lines=21) @@
3564
            'day': day.day,
3565
            'month': day.month,
3566
            'year': day.year,
3567
        }
3568
3569
3570
class GenericBlogspotComic(GenericNavigableComic):
3571
    """Generic class to retrieve comics from Blogspot."""
3572
    get_first_comic_link = simulate_first_link
3573
    first_url = NotImplemented
3574
    _categories = ('BLOGSPOT', )
3575
3576
    @classmethod
3577
    def get_navi_link(cls, last_soup, next_):
3578
        """Get link to next or previous comic."""
3579
        return last_soup.find('a', id='Blog1_blog-pager-newer-link' if next_ else 'Blog1_blog-pager-older-link')
3580
3581
3582
class TuMourrasMoinsBete(GenericBlogspotComic):
3583
    """Class to retrieve Tu Mourras Moins Bete comics."""
3584
    name = 'mourrasmoinsbete'
3585
    long_name = 'Tu Mourras Moins Bete'
3586
    url = 'http://tumourrasmoinsbete.blogspot.fr'
3587
    _categories = ('FRANCAIS', )
3588
    first_url = 'http://tumourrasmoinsbete.blogspot.fr/2008/06/essai.html'
3589
3590
    @classmethod
@@ 2801-2821 (lines=21) @@
2798
        return {
2799
            'img': [i['src'] for i in imgs],
2800
            'title': title,
2801
            'alt': alt,
2802
            'author': author,
2803
            'day': day.day,
2804
            'month': day.month,
2805
            'year': day.year
2806
        }
2807
2808
2809
class PlanC(GenericNavigableComic):
2810
    """Class to retrieve Plan C comics."""
2811
    name = 'planc'
2812
    long_name = 'Plan C'
2813
    url = 'http://www.plancomic.com'
2814
    get_first_comic_link = get_a_navi_navifirst
2815
    get_navi_link = get_a_navi_comicnavnext_navinext
2816
2817
    @classmethod
2818
    def get_comic_info(cls, soup, link):
2819
        """Get information about a particular comics."""
2820
        title = soup.find('h2', class_='post-title').string
2821
        date_str = soup.find("span", class_="post-date").string
2822
        day = string_to_date(date_str, "%B %d, %Y")
2823
        imgs = soup.find('div', id='comic').find_all('img')
2824
        return {
@@ 1934-1959 (lines=26) @@
1931
        }
1932
1933
1934
class Penmen(GenericComicNotWorking, GenericNavigableComic):
1935
    """Class to retrieve Penmen comics."""
1936
    name = 'penmen'
1937
    long_name = 'Penmen'
1938
    url = 'http://penmen.com'
1939
    get_navi_link = get_link_rel_next
1940
    get_first_comic_link = simulate_first_link
1941
    first_url = 'http://penmen.com/index.php/2016/09/12/penmen-announces-grin-big-brand-clothing/'
1942
1943
    @classmethod
1944
    def get_comic_info(cls, soup, link):
1945
        """Get information about a particular comics."""
1946
        title = soup.find('title').string
1947
        imgs = soup.find('div', class_='entry-content').find_all('img')
1948
        short_url = soup.find('link', rel='shortlink')['href']
1949
        tags = ' '.join(t.string for t in soup.find_all('a', rel='tag'))
1950
        date_str = soup.find('time')['datetime'][:10]
1951
        day = string_to_date(date_str, "%Y-%m-%d")
1952
        return {
1953
            'title': title,
1954
            'short_url': short_url,
1955
            'img': [i['src'] for i in imgs],
1956
            'tags': tags,
1957
            'month': day.month,
1958
            'year': day.year,
1959
            'day': day.day,
1960
        }
1961
1962
@@ 1875-1900 (lines=26) @@
1872
        }
1873
1874
1875
class SafelyEndangered(GenericNavigableComic):
1876
    """Class to retrieve Safely Endangered comics."""
1877
    # Also on http://tumblr.safelyendangered.com
1878
    name = 'endangered'
1879
    long_name = 'Safely Endangered'
1880
    url = 'http://www.safelyendangered.com'
1881
    get_navi_link = get_link_rel_next
1882
    get_first_comic_link = simulate_first_link
1883
    first_url = 'http://www.safelyendangered.com/comic/ignored/'
1884
1885
    @classmethod
1886
    def get_comic_info(cls, soup, link):
1887
        """Get information about a particular comics."""
1888
        title = soup.find('h2', class_='post-title').string
1889
        date_str = soup.find('span', class_='post-date').string
1890
        day = string_to_date(date_str, '%B %d, %Y')
1891
        imgs = soup.find('div', id='comic').find_all('img')
1892
        alt = imgs[0]['alt']
1893
        assert all(i['alt'] == i['title'] for i in imgs)
1894
        return {
1895
            'day': day.day,
1896
            'month': day.month,
1897
            'year': day.year,
1898
            'img': [i['src'] for i in imgs],
1899
            'title': title,
1900
            'alt': alt,
1901
        }
1902
1903
@@ 1230-1256 (lines=27) @@
1227
        }
1228
1229
1230
class ToonHole(GenericNavigableComic):
1231
    """Class to retrieve Toon Holes comics."""
1232
    # Also on http://tapastic.com/series/TOONHOLE
1233
    name = 'toonhole'
1234
    long_name = 'Toon Hole'
1235
    url = 'http://www.toonhole.com'
1236
    get_first_comic_link = get_a_comicnavbase_comicnavfirst
1237
    get_navi_link = get_a_comicnavbase_comicnavnext
1238
1239
    @classmethod
1240
    def get_comic_info(cls, soup, link):
1241
        """Get information about a particular comics."""
1242
        date_str = soup.find('div', class_='entry-meta').contents[0].strip()
1243
        day = string_to_date(date_str, "%B %d, %Y")
1244
        imgs = soup.find('div', id='comic').find_all('img')
1245
        if imgs:
1246
            img = imgs[0]
1247
            title = img['alt']
1248
            assert img['title'] == title
1249
        else:
1250
            title = ""
1251
        return {
1252
            'title': title,
1253
            'month': day.month,
1254
            'year': day.year,
1255
            'day': day.day,
1256
            'img': [convert_iri_to_plain_ascii_uri(i['src']) for i in imgs],
1257
        }
1258
1259
@@ 3476-3500 (lines=25) @@
3473
    @classmethod
3474
    def get_comic_info(cls, soup, link):
3475
        """Get information about a particular comics."""
3476
        title = soup.find("h1", class_="entry-title").string
3477
        imgs = soup.find('div', class_='entry-content').find_all('img')
3478
        return {
3479
            'title': title,
3480
            'img': [i['src'] for i in imgs],
3481
        }
3482
3483
3484
class MacadamValley(GenericNavigableComic):
3485
    """Class to retrieve Macadam Valley comics."""
3486
    name = 'macadamvalley'
3487
    long_name = 'Macadam Valley'
3488
    url = 'http://macadamvalley.com'
3489
    get_navi_link = get_a_rel_next
3490
    get_first_comic_link = simulate_first_link
3491
    first_url = 'http://macadamvalley.com/le-debut-de-la-fin/'
3492
3493
    @classmethod
3494
    def get_comic_info(cls, soup, link):
3495
        """Get information about a particular comics."""
3496
        title = soup.find("h1", class_="entry-title").string
3497
        img = soup.find('div', class_='entry-content').find('img')
3498
        date_str = soup.find('time', class_='entry-date')['datetime']
3499
        date_str = date_str[:10]
3500
        day = string_to_date(date_str, "%Y-%m-%d")
3501
        author = soup.find('a', rel='author').string
3502
        return {
3503
            'title': title,