from collections import namedtuple
import re
from urllib import parse

from bs4 import BeautifulSoup

__author__ = 'zz'


island_netloc_table = {}
island_class_table = {}


DivInfo = namedtuple('DivInfo', ['content', 'link', 'response_num', 'image'])


class IslandNotDetectError(Exception):
    pass





class IslandMeta(type):

    def __init__(cls, name, bases, ns):
        if name != 'BaseIsland':
            island_name = ns.get('_island_name')
            island_netloc = ns.get('_island_netloc')
            assert island_name , 'Not define _island_name in {} class'.format(name)
            assert island_netloc , 'Not define _island_netloc in {} class'.format(name)

             # register island and netloc
            island_netloc_table.update({island_netloc: island_name})

            # register island class
            island_class_table.update({island_name: cls})

        super().__init__(name, bases, ns)


class BaseIsland(metaclass=IslandMeta):

    _island_name = ''
    _island_netloc = ''
    _island_scheme = 'http'
    _count_pattern = re.compile(r'\s(\d+)\s')
    json_data = False
    show_image = True

    def __init__(self, current_url, res):
        if not self.json_data:
            self.pd = BeautifulSoup(res.content)
        else:
            self.pd = res.json()

        self.current_url = current_url

    @property
    def root_url(self):
        return parse.urlunsplit((self._island_scheme, self._island_netloc, '', '', ''))

    def get_div_response_num(self, tip):
        """
        return response count
        """
        text = tip.text
        match = self._count_pattern.search(text)
        if match:
            return match.group(1)
        else:
            # may be the text is 'sega'
            return 0



    def get_tips(self, pd):
        """
        :param pd: a BeautifulSoup object or json object, determine by json_data
        return a list of  object that contain tips content
        """
        raise NotImplementedError

    def get_div_link(self, tip):
        """
        tip is a BeautifulSoup object contain response tip
        return the link href string, eg, 'http://xx.com', or /xx/xx.html """
        raise NotImplementedError

    def get_div_content(self, tip):
        """
        return content
        """
        raise NotImplementedError

    def get_div_image(self, tip):
        raise NotImplementedError

    def get_next_page(self):
        """
        return (url, page_num)
        """
        raise NotImplementedError

    def next_page_valid(self, next_page_url, page_num):
        raise NotImplementedError

    def next_page(self, max_page):
        """
        return next page url
        """
        url, page_num = self.get_next_page()
        if url and page_num <= max_page and self.next_page_valid(url, page_num):
            return url
        else:
            return None

    def island_split_page(self):
        """
        must return DivInfo object
        """
        result = []

        pd = self.pd
        tips = self.get_tips(pd)
        for tip in tips:
            response_num = int(self.get_div_response_num(tip))
            link = self.complete_link(self.get_div_link(tip))
            content = self.get_div_content(tip)
            image = self.get_div_image(tip) if self.show_image else ''
            image = self.complete_link(image)

            div = DivInfo(content=content, link=link, response_num=response_num, image=image)
            result.append(div)

        return result


    def complete_link(self, url):
        if not url:
            return ''
        return parse.urljoin(self.root_url, url)


    @staticmethod
    def init_start_url(start_url):
        """
        :param start_url:
        :return:返回初始化的url， 对特别的首页加上是加上分页后缀
        """
        return start_url



@@ -1339,16 +1339,258 @@
 nt_url%0A%0A
+    @property%0A    def current_page_url(self):%0A        url = getattr(self, '_current_page_url', self.current_url)%0A        return url%0A%0A    @current_page_url.setter%0A    def current_page_url(self, value):%0A        self._current_page_url = value%0A%0A%0A
     @pro
@@ -2878,16 +2878,39 @@
 max_page
+, current_page_url=None
 ):%0A     
@@ -2949,32 +2949,115 @@
 url%0A        %22%22%22%0A
+        if current_page_url:%0A            self.current_page_url = current_page_url%0A%0A
         url, pag

add current_page_url argument to next_page