Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
boramalper committed Jun 12, 2020
0 parents commit 116a9aa
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/venv/
/dist/
/.idea/
/MANIFEST
__pycache__
14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Contributing

## Uploading to PYPI
1. Create tar:

```bash
python setup.py sdist
```

2. Upload:

```bash
twine upload dist/*
```
13 changes: 13 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) 2020 newsmail.today <us@newsmail.today>

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# nm_iconfinder

Find icons of a website given a URL

## Usage
```python
from nm_iconfinder import icons

icons("https://blog.newsmail.today/")
```

1 change: 1 addition & 0 deletions nm_iconfinder/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from nm_iconfinder.nm_iconfinder import icons
69 changes: 69 additions & 0 deletions nm_iconfinder/nm_iconfinder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from typing import List, Optional

from base64 import b64encode
from urllib.parse import urljoin
from io import BytesIO

from bs4 import BeautifulSoup
from PIL import Image
import requests

TIMEOUT = 3 # seconds


class Icon:
"""
All icons are assumed to be square.
"""

def __init__(self, url: str, size: int, mimetype: str, data: bytes):
self.url = url
self.size = size
self.mimetype = mimetype
self.data = data
self.data_uri = "data:%s;base64,%s" % (mimetype, b64encode(data).decode("ascii"))

def __repr__(self):
if "icon" in self.mimetype:
format = "ico"
else:
format = self.mimetype.split("/", 1)[1]

return "Icon {0} {1}x{1}".format(format, self.size)

@classmethod
def from_url(cls, url: str) -> Optional["Icon"]:
try:
res = requests.get(url, timeout=TIMEOUT)
res.raise_for_status()
except requests.exceptions.RequestException:
return None

with BytesIO(res.content) as bio:
img = Image.open(bio)
width, height = img.size
# Ignore non-square Icons
if width != height:
return None

mimetype = res.headers["Content-Type"].split(";", 1)[0].strip()
return cls(url, width, mimetype, res.content)


def icons(url: str) -> List[Icon]:
try:
response = requests.get(url, timeout=TIMEOUT)
response.raise_for_status()
except requests.exceptions.RequestException:
return []

soup = BeautifulSoup(response.text, features="lxml")
links = soup.find_all("link", attrs={"rel": "shortcut icon", "href": True}) \
+ soup.find_all("link", attrs={"rel": "icon", "href": True}) \
+ soup.find_all("link", attrs={"rel": "apple-touch-icon-precomposed", "href": True}) \
+ soup.find_all("link", attrs={"rel": "apple-touch-icon", "href": True}) \
+ [{"href": "/favicon.ico"}]
hrefs = set(urljoin(url, link["href"]) for link in links)

icons_ = [Icon.from_url(urljoin(url, href)) for href in hrefs] # type: List[Optional[Icon]]
return sorted(filter(lambda i: i is not None, icons_), key=lambda i: i.size, reverse=True)
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
twine
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
beautifulsoup4
lxml
Pillow
requests
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[metadata]
description-file = README.md
27 changes: 27 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from distutils.core import setup

setup(
name='nm_iconfinder',
packages=['nm_iconfinder'],
version='0.1',
license='ISC',
description='Find icons of a website given a URL',
author='newsmail.today',
author_email='us@newsmail.today',
url='https://github.com/newsmail-today/iconfinder',
keywords=['icon', 'favicon', 'newsmail'],
install_requires=[
"beautifulsoup4",
"lxml",
"Pillow",
"requests",
],
classifiers=[
# Chose either "3 - Alpha", "4 - Beta" or "5 - Production/Stable" as the current state of your package
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: ISC License (ISCL)',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
],
)

0 comments on commit 116a9aa

Please sign in to comment.