app: Include amazon links.
This commit is contained in:
@@ -28,6 +28,7 @@ exports.createPages = async function ({ actions, graphql }) {
|
|||||||
category
|
category
|
||||||
image_url
|
image_url
|
||||||
description
|
description
|
||||||
|
amazon_url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
app/src/components/amazonurl.js
Normal file
13
app/src/components/amazonurl.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const getTaggetURL = (book) => {
|
||||||
|
return book.amazon_url + "?tag=vishnuks-20";
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ({ book }) => {
|
||||||
|
return (
|
||||||
|
<a href={getTaggetURL(book)} target="_blank">
|
||||||
|
<img style={{ "width": "30px" }} src="https://img.icons8.com/color/48/000000/amazon.png"/>
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -3,20 +3,21 @@ import React from "react"
|
|||||||
import StarRatings from "react-star-ratings"
|
import StarRatings from "react-star-ratings"
|
||||||
import { Card, Row, Col } from "react-bootstrap"
|
import { Card, Row, Col } from "react-bootstrap"
|
||||||
|
|
||||||
|
import AmazonURL from "../components/amazonurl"
|
||||||
|
|
||||||
const truncateContent = (content) => {
|
const truncateContent = (content) => {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return content.length > 600 ? content.substring(0, 600) + "..." : content
|
return content.length > 350 ? content.substring(0, 350) + "..." : content
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const BookCard = ({ book }) => (
|
const BookCard = ({ book }) => (
|
||||||
<Card style={{ width: "44rem", height: "24rem", marginBottom: "15px" }}>
|
<Card style={{ width: "44rem", height: "21rem", marginBottom: "15px" }}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={3}>
|
<Col xs={3}>
|
||||||
<Card.Img
|
<Card.Img
|
||||||
style={{ height: "12rem", width: "8rem", paddingLeft: "25px", paddingRight: "-15px", paddingTop: "30px"}}
|
style={{ height: "12rem", width: "8rem", paddingLeft: "25px", paddingRight: "-15px", paddingTop: "30px" }}
|
||||||
src={book.image_url}
|
src={book.image_url}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
@@ -32,7 +33,9 @@ const BookCard = ({ book }) => (
|
|||||||
starRatedColor="#fa604a"
|
starRatedColor="#fa604a"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
{book.author}
|
{book.author} <b>{book.year ? book.year: null}</b>
|
||||||
|
<br />
|
||||||
|
{book.amazon_url ? <AmazonURL book={book} />: null}
|
||||||
</Card.Subtitle>
|
</Card.Subtitle>
|
||||||
<p>
|
<p>
|
||||||
{truncateContent(book.description)}
|
{truncateContent(book.description)}
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ import BookCard from "../components/bookcard"
|
|||||||
|
|
||||||
export default ({ data, limit }) => {
|
export default ({ data, limit }) => {
|
||||||
return data.allBooksJson.edges.map(function(x, index) {
|
return data.allBooksJson.edges.map(function(x, index) {
|
||||||
console.log(index, limit)
|
const book = x.node;
|
||||||
if (!limit || index < limit) {
|
if (!limit || index < limit) {
|
||||||
return <BookCard book={x.node} key={x.node.id} />
|
if(!book.description || book.description.length < 10) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <BookCard book={book} key={book.id} />
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
BIN
app/src/images/amazon.png
Normal file
BIN
app/src/images/amazon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -59,6 +59,7 @@ export const query = graphql`
|
|||||||
category
|
category
|
||||||
description
|
description
|
||||||
image_url
|
image_url
|
||||||
|
amazon_url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
101
requirements.txt
Normal file
101
requirements.txt
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
appdirs==1.4.3
|
||||||
|
apturl==0.5.2
|
||||||
|
asgiref==3.2.7
|
||||||
|
astroid==2.4.1
|
||||||
|
bcrypt==3.1.7
|
||||||
|
beautifulsoup4==4.8.2
|
||||||
|
blinker==1.4
|
||||||
|
Brlapi==0.7.0
|
||||||
|
certifi==2019.11.28
|
||||||
|
chardet==3.0.4
|
||||||
|
Click==7.0
|
||||||
|
colorama==0.4.3
|
||||||
|
command-not-found==0.3
|
||||||
|
commonmark==0.9.1
|
||||||
|
configobj==5.0.6
|
||||||
|
cryptography==2.8
|
||||||
|
cupshelpers==1.0
|
||||||
|
dbus-python==1.2.16
|
||||||
|
defer==1.0.6
|
||||||
|
distlib==0.3.0
|
||||||
|
distro==1.4.0
|
||||||
|
distro-info===0.23ubuntu1
|
||||||
|
Django==3.0.6
|
||||||
|
duplicity==0.8.12.0
|
||||||
|
entrypoints==0.3
|
||||||
|
fasteners==0.14.1
|
||||||
|
filelock==3.0.12
|
||||||
|
future==0.18.2
|
||||||
|
html5lib==1.0.1
|
||||||
|
httplib2==0.14.0
|
||||||
|
idna==2.8
|
||||||
|
isort==4.3.21
|
||||||
|
kazam==1.4.5
|
||||||
|
keyring==18.0.1
|
||||||
|
language-selector==0.1
|
||||||
|
launchpadlib==1.10.13
|
||||||
|
lazr.restfulclient==0.14.2
|
||||||
|
lazr.uri==1.0.3
|
||||||
|
lazy-object-proxy==1.4.3
|
||||||
|
linecache2==1.0.0
|
||||||
|
lockfile==0.12.2
|
||||||
|
louis==3.12.0
|
||||||
|
lxml==4.5.0
|
||||||
|
macaroonbakery==1.3.1
|
||||||
|
Mako==1.1.0
|
||||||
|
MarkupSafe==1.1.0
|
||||||
|
mccabe==0.6.1
|
||||||
|
monotonic==1.5
|
||||||
|
mypy==0.761
|
||||||
|
mypy-extensions==0.4.3
|
||||||
|
netifaces==0.10.4
|
||||||
|
oauthlib==3.1.0
|
||||||
|
olefile==0.46
|
||||||
|
paramiko==2.6.0
|
||||||
|
pbr==5.4.5
|
||||||
|
pexpect==4.6.0
|
||||||
|
Pillow==7.0.0
|
||||||
|
protobuf==3.6.1
|
||||||
|
psutil==5.5.1
|
||||||
|
pycairo==1.16.2
|
||||||
|
pycups==1.9.73
|
||||||
|
PyGObject==3.36.0
|
||||||
|
PyJWT==1.7.1
|
||||||
|
pylint==2.5.1
|
||||||
|
pymacaroons==0.13.0
|
||||||
|
PyNaCl==1.3.0
|
||||||
|
pyRFC3339==1.1
|
||||||
|
python-apt==2.0.0+ubuntu0.20.4.1
|
||||||
|
python-dateutil==2.7.3
|
||||||
|
python-debian===0.1.36ubuntu1
|
||||||
|
pytz==2019.3
|
||||||
|
pyxdg==0.26
|
||||||
|
PyYAML==5.3.1
|
||||||
|
reportlab==3.5.34
|
||||||
|
requests==2.22.0
|
||||||
|
requests-unixsocket==0.2.0
|
||||||
|
screen-resolution-extra==0.0.0
|
||||||
|
SecretStorage==2.3.1
|
||||||
|
simplejson==3.16.0
|
||||||
|
six==1.14.0
|
||||||
|
soupsieve==1.9.5
|
||||||
|
sqlparse==0.3.1
|
||||||
|
ssh-import-id==5.10
|
||||||
|
systemd-python==234
|
||||||
|
testresources==2.0.0
|
||||||
|
toml==0.10.0
|
||||||
|
traceback2==1.4.0
|
||||||
|
typed-ast==1.4.1
|
||||||
|
typing-extensions==3.7.4.1
|
||||||
|
ubuntu-advantage-tools==20.3
|
||||||
|
ubuntu-drivers-common==0.0.0
|
||||||
|
ufw==0.36
|
||||||
|
unattended-upgrades==0.1
|
||||||
|
unittest2==1.1.0
|
||||||
|
urllib3==1.25.8
|
||||||
|
usb-creator==0.3.7
|
||||||
|
virtualenv==20.0.20
|
||||||
|
wadllib==1.3.3
|
||||||
|
webencodings==0.5.1
|
||||||
|
wrapt==1.12.1
|
||||||
|
xkit==0.0.0
|
||||||
610
utils/books.json
610
utils/books.json
File diff suppressed because it is too large
Load Diff
5184
utils/books_list.json
Normal file
5184
utils/books_list.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,4 @@
|
|||||||
# save this file as 'config.py' and then, fill it with you api key
|
# save this file as 'config.py' and then, fill it with you api key
|
||||||
GOODREADS_PUBLIC_API_KEY = "write here your goodreads public API key"
|
GOODREADS_PUBLIC_API_KEY = "write here your goodreads public API key"
|
||||||
|
GOOGLE_SEARCH_RAPIDAPI_HOST = ""
|
||||||
|
GOOGLESEARCH_RAPIDAPI_KEY = ""
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import urllib.error
|
|||||||
|
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
from config import GOODREADS_PUBLIC_API_KEY
|
from config import GOODREADS_PUBLIC_API_KEY, GOOGLE_SEARCH_RAPIDAPI_HOST, GOOGLE_SEARCH_RAPIDAPI_KEY
|
||||||
|
from googlesearch import search
|
||||||
|
|
||||||
def get_details(book_object):
|
def get_details(book_object):
|
||||||
|
|
||||||
@@ -15,7 +15,17 @@ def get_details(book_object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tree = ET.ElementTree(file=urllib.request.urlopen(url))
|
time_to_sleep = 1
|
||||||
|
while True:
|
||||||
|
response = urllib.request.urlopen(url)
|
||||||
|
print(response.getcode())
|
||||||
|
if response.getcode() == 429:
|
||||||
|
time_to_sleep = time_to_sleep * 2
|
||||||
|
print("Sleeping for {}".format(time_to_sleep))
|
||||||
|
time.sleep(time_to_sleep)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
tree = ET.ElementTree(file=response)
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
book = root.find("book")
|
book = root.find("book")
|
||||||
book_object["year"] = book.find("publication_year").text or ""
|
book_object["year"] = book.find("publication_year").text or ""
|
||||||
@@ -23,9 +33,23 @@ def get_details(book_object):
|
|||||||
book_object["rating"] = book.find("average_rating").text
|
book_object["rating"] = book.find("average_rating").text
|
||||||
book_object["pages"] = book.find("num_pages").text
|
book_object["pages"] = book.find("num_pages").text
|
||||||
book_object["image_url"] = book.find("image_url").text
|
book_object["image_url"] = book.find("image_url").text
|
||||||
if (description := book.find("description").text) :
|
if (description := book.find("description").text):
|
||||||
book_object["description"] = BeautifulSoup(description).text
|
book_object["description"] = BeautifulSoup(description).text
|
||||||
|
else:
|
||||||
|
book_object["description"] = ""
|
||||||
book_object["isbn"] = book.find("isbn").text
|
book_object["isbn"] = book.find("isbn").text
|
||||||
|
print("Fetching amazon link")
|
||||||
|
import requests
|
||||||
|
|
||||||
|
url = "https://google-search3.p.rapidapi.com/api/v1/search/q=site:amazon.com {} {}".format(book_object["title"], book_object["author"])
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
'x-rapidapi-host': GOOGLE_SEARCH_RAPIDAPI_HOST,
|
||||||
|
'x-rapidapi-key': GOOGLE_SEARCH_RAPIDAPI_KEY,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.request("GET", url, headers=headers)
|
||||||
|
book_object["amazon_url"] = response.json()["results"][0]["link"]
|
||||||
return True
|
return True
|
||||||
except urllib.error.HTTPError as e:
|
except urllib.error.HTTPError as e:
|
||||||
print(
|
print(
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ required_fields = [
|
|||||||
"image_url",
|
"image_url",
|
||||||
"description",
|
"description",
|
||||||
"category",
|
"category",
|
||||||
|
"amazon_url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -63,22 +64,11 @@ if __name__ == "__main__":
|
|||||||
indent=4,
|
indent=4,
|
||||||
separators=(",", ": "),
|
separators=(",", ": "),
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
print(f"❌ Error while fetching {title}")
|
|
||||||
time.sleep(1)
|
|
||||||
|
|
||||||
book_list = []
|
book_list = []
|
||||||
for _, book in existing_book_names_to_details.items():
|
for _, book in existing_book_names_to_details.items():
|
||||||
book_list.append(book)
|
book_list.append(book)
|
||||||
|
|
||||||
with open("books.json", "w") as f:
|
|
||||||
json.dump(
|
|
||||||
existing_book_names_to_details,
|
|
||||||
f,
|
|
||||||
sort_keys=True,
|
|
||||||
indent=4,
|
|
||||||
separators=(",", ": "),
|
|
||||||
)
|
|
||||||
|
|
||||||
with open("books_list.json", "w") as f:
|
with open("books_list.json", "w") as f:
|
||||||
json.dump(book_list, f, sort_keys=True, indent=4, separators=(",", ": "))
|
json.dump(book_list, f, sort_keys=True, indent=4, separators=(",", ": "))
|
||||||
|
else:
|
||||||
|
print(f"❌ Error while fetching {title}")
|
||||||
|
|||||||
Reference in New Issue
Block a user