'Returns the list of recent URLs (of web documents) tagged with a given tag.
This is very similar to parsing Delicious\' RSS/JSON feeds directly,
but this function will return up to 2,000 links compared to a maximum
of 100 links when using the official feeds (with query parameter
count=100).
The return list of links will be sorted by recency in descending order,
i.e. newest items first.
Note that even when setting max_urls, get_urls() cannot guarantee that
it can retrieve *at least* this many URLs. It is really just an upper
bound.
@param tag: Retrieve links which have been tagged with the given tag.
If tag is not set (default), links will be retrieved from the
Delicious.com front page (aka "delicious hotlist").
@type tag: unicode/str
@param popular: If true (default), retrieve only popular links (i.e.
/popular/<tag>). Otherwise, the most recent links tagged with
the given tag will be retrieved (i.e. /tag/<tag>).
As of January 2009, it seems that Delicious.com modified the list
of popular tags to contain only up to a maximum of 15 URLs.
This also means that setting max_urls to values larger than 15
will not change the results of get_urls().
So if you are interested in more URLs, set the "popular" parameter
to false.
Note that if you set popular to False, the returned list of URLs
might contain duplicate items. This is due to the way Delicious.com
creates its /tag/<tag> Web pages. So if you need a certain
number of unique URLs, you have to take care of that in your
own code.
@type popular: bool
@param max_urls: Retrieve at most max_urls links. The default is 100,
which is the maximum number of links that can be retrieved by
parsing the official JSON feeds. The maximum value of max_urls
in practice is 2000 (currently). If it is set higher, Delicious
will return the same links over and over again, giving lots of
duplicate items.
@type max_urls: int
@param sleep_seconds: Optional, default: 1.
Wait the specified number of seconds between subsequent queries in
case that there are multiple pages of bookmarks for the given url.
Must be greater than or equal to 1 to comply with Delicious.com\'s
Terms of Use.
See also parameter \'max_urls\'.
@type sleep_seconds: int
@return: The list of recent URLs (of web documents) tagged with a given tag.'

def get_urls(self, tag=None, popular=True, max_urls=100, sleep_seconds=1):

    assert (sleep_seconds >= 1)
    urls = []
    path = None
    if ((tag is None) or ((tag is not None) and (max_urls > 0) and (max_urls <= 100))):
        max_json_count = 100
        if tag:
            if popular:
                path = ('/v2/json/popular/%s?count=%d' % (tag, max_json_count))
            else:
                path = ('/v2/json/tag/%s?count=%d' % (tag, max_json_count))
        else:
            path = ('/v2/json/?count=%d' % max_json_count)
        data = self._query(path, host='feeds.delicious.com')
        if data:
            posts = []
            try:
                posts = simplejson.loads(data)
            except TypeError:
                pass
            for post in posts:
                try:
                    url = post['u']
                    if url:
                        urls.append(url)
                except KeyError:
                    pass
    else:
        max_html_count = 100
        max_html_pages = 20
        if popular:
            path = ('/popular/%s?setcount=%d' % (tag, max_html_count))
        else:
            path = ('/tag/%s?setcount=%d' % (tag, max_html_count))
        page_index = 1
        urls = []
        while (path and (page_index <= max_html_pages)):
            data = self._query(path)
            path = None
            if data:
                soup = BeautifulSoup(data)
                links = soup.findAll('a', attrs={'class': re.compile('^taggedlink\\s*')})
                for link in links:
                    try:
                        url = link['href']
                        if url:
                            urls.append(url)
                    except KeyError:
                        pass
                soup = BeautifulSoup(data)
                paginations = soup.findAll('div', id='pagination')
                if paginations:
                    nexts = paginations[0].findAll('a', attrs={'class': 'pn    next'})
                    if (nexts and ((max_urls == 0) or (len(urls) < max_urls)) and (len(urls) > 0)):
                        path = nexts[0]['href']
                        path += ('&setcount=%d' % max_html_count)
                        page_index += 1
                        time.sleep(sleep_seconds)
    if (max_urls > 0):
        return urls[:max_urls]
    else:
        return urls
