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

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

""" 

This module implements the TextResponse class which adds encoding handling and 

discovering (through HTTP headers) to base Response class. 

 

See documentation in docs/topics/request-response.rst 

""" 

 

from w3lib.encoding import html_to_unicode, resolve_encoding, \ 

    html_body_declared_encoding, http_content_type_encoding, to_unicode 

from scrapy.http.response import Response 

from scrapy.utils.python import memoizemethod_noargs 

from scrapy.conf import settings 

 

 

class TextResponse(Response): 

 

    _DEFAULT_ENCODING = settings['DEFAULT_RESPONSE_ENCODING'] 

 

    def __init__(self, *args, **kwargs): 

        self._encoding = kwargs.pop('encoding', None) 

        self._cached_benc = None 

        self._cached_ubody = None 

        super(TextResponse, self).__init__(*args, **kwargs) 

 

    def _set_url(self, url): 

        if isinstance(url, unicode): 

28            if self.encoding is None: 

                raise TypeError('Cannot convert unicode url - %s has no encoding' % 

                    type(self).__name__) 

            self._url = url.encode(self.encoding) 

        else: 

            super(TextResponse, self)._set_url(url) 

 

    def _set_body(self, body): 

        self._body = '' 

        if isinstance(body, unicode): 

38            if self.encoding is None: 

                raise TypeError('Cannot convert unicode body - %s has no encoding' % 

                    type(self).__name__) 

            self._body = body.encode(self._encoding) 

        else: 

            super(TextResponse, self)._set_body(body) 

 

    def replace(self, *args, **kwargs): 

        kwargs.setdefault('encoding', self.encoding) 

        return Response.replace(self, *args, **kwargs) 

 

    @property 

    def encoding(self): 

        return self._declared_encoding() or self._body_inferred_encoding() 

 

    def _declared_encoding(self): 

        return self._encoding or self._headers_encoding() \ 

            or self._body_declared_encoding() 

 

    def body_as_unicode(self): 

        """Return body as unicode""" 

        if self._cached_ubody is None: 

            self._cached_ubody = to_unicode(self.body, self.encoding) 

        return self._cached_ubody 

 

    @memoizemethod_noargs 

    def _headers_encoding(self): 

        content_type = self.headers.get('Content-Type') 

        return http_content_type_encoding(content_type) 

 

    def _body_inferred_encoding(self): 

        if self._cached_benc is None: 

            content_type = self.headers.get('Content-Type') 

            benc, ubody = html_to_unicode(content_type, self.body, \ 

                    auto_detect_fun=self._auto_detect_fun, \ 

                    default_encoding=self._DEFAULT_ENCODING) 

            self._cached_benc = benc 

            self._cached_ubody = ubody 

        return self._cached_benc 

 

    def _auto_detect_fun(self, text): 

        for enc in (self._DEFAULT_ENCODING, 'utf-8', 'cp1252'): 

            try: 

                text.decode(enc) 

            except UnicodeError: 

                continue 

            return resolve_encoding(enc) 

 

    @memoizemethod_noargs 

    def _body_declared_encoding(self): 

        return html_body_declared_encoding(self.body)