Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

import re 

 

from scrapy.spider import BaseSpider 

from scrapy.http import Request, XmlResponse 

from scrapy.utils.sitemap import Sitemap, sitemap_urls_from_robots 

from scrapy.utils.gz import gunzip, is_gzipped 

from scrapy import log 

 

class SitemapSpider(BaseSpider): 

 

    sitemap_urls = () 

    sitemap_rules = [('', 'parse')] 

    sitemap_follow = [''] 

 

    def __init__(self, *a, **kw): 

        super(SitemapSpider, self).__init__(*a, **kw) 

        self._cbs = [] 

        for r, c in self.sitemap_rules: 

21            if isinstance(c, basestring): 

                c = getattr(self, c) 

            self._cbs.append((regex(r), c)) 

        self._follow = [regex(x) for x in self.sitemap_follow] 

 

    def start_requests(self): 

        return (Request(x, callback=self._parse_sitemap) for x in self.sitemap_urls) 

 

    def _parse_sitemap(self, response): 

        if response.url.endswith('/robots.txt'): 

            for url in sitemap_urls_from_robots(response.body): 

                yield Request(url, callback=self._parse_sitemap) 

        else: 

            body = self._get_sitemap_body(response) 

            if body is None: 

                log.msg("Ignoring invalid sitemap: %s" % response, log.WARNING) 

                return 

 

            s = Sitemap(body) 

            if s.type == 'sitemapindex': 

                for loc in iterloc(s): 

                    if any(x.search(loc) for x in self._follow): 

                        yield Request(loc, callback=self._parse_sitemap) 

            elif s.type == 'urlset': 

                for loc in iterloc(s): 

                    for r, c in self._cbs: 

                        if r.search(loc): 

                            yield Request(loc, callback=c) 

                            break 

 

    def _get_sitemap_body(self, response): 

        """Return the sitemap body contained in the given response, or None if the 

        response is not a sitemap. 

        """ 

        if isinstance(response, XmlResponse): 

            return response.body 

        elif is_gzipped(response): 

            return gunzip(response.body) 

        elif response.url.endswith('.xml'): 

            return response.body 

        elif response.url.endswith('.xml.gz'): 

            return gunzip(response.body) 

 

def regex(x): 

65    if isinstance(x, basestring): 

        return re.compile(x) 

    return x 

 

def iterloc(it): 

    for d in it: 

        yield d['loc']