{"id":473,"date":"2020-06-14T18:43:36","date_gmt":"2020-06-14T18:43:36","guid":{"rendered":"https:\/\/technobabble.us.to\/?p=473"},"modified":"2021-01-04T01:26:21","modified_gmt":"2021-01-04T01:26:21","slug":"python-inventory-checker","status":"publish","type":"post","link":"https:\/\/technobabble.us.to\/?p=473","title":{"rendered":"Python Inventory Search"},"content":{"rendered":"\n<p>I wrote a python script to query a website and check to see if an item is in stock. If it finds the product in question it will email me a report with a hyperlink so that I can click the link and place and order straight from my email. This script runs as a cron job (once every hour) and saves me the time of having to constantly check their website, wondering when they will get the next delivery. <\/p>\n\n\n\n<p>It was a great exercise in using the BeautifulSoup4 python library as well as using selenium for the first time which was needed to flesh out the javascript that is creating the dynamic content.   <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\nfrom selenium import webdriver\nfrom bs4 import BeautifulSoup as bs\nfrom selenium.webdriver.firefox.options import Options\nfrom selenium.common.exceptions import NoSuchElementException\nimport lxml\nimport smtplib\nimport time\n\noptions = Options()\noptions.headless = True\n\nmylist = &#x5B;]\nnot_found = ''\n\ndriver = webdriver.Firefox(options=options)\ndriver.get(&quot;https:\/\/www.website.com)\n\n# Try and fix the random timing errors --&gt; better way is with selenium waitfor\ntime.sleep(5)\n\n# Look for the state &quot;no product in stock&quot; --&gt; &quot;0 matches, that stinks&quot;\ntry:\n    not_found = driver.find_element_by_class_name(&quot;css-1ctldcn.ew1p50q2&quot;)\n    not_found_html = not_found.get_attribute('innerHTML')\n\n# handle the exception of product actually being found.\nexcept NoSuchElementException as e:\n    print (str(e))\n\n# print &quot;not found message&quot; and exit program\nif(not_found):\n    print (not_found_html)\n    driver.close()\n    exit()\n\ntry: \n\n    # They have stock; now find how many products they have at runtime.\n    products = driver.find_element_by_class_name(&quot;css-hecap1.ettsl931&quot;)\n    total_products = products.get_attribute('innerHTML')\n\n# handle the exception of product elements not being found and exit program\nexcept NoSuchElementException as e:\n    print (str(e))\n    driver.close()\n    exit()\n\n# Find all of the Grid Elements, or all of the products available - all products use the same grid ID\nelement = driver.find_element_by_class_name(&quot;css-19ofktj.e29d1tf2&quot;)\nhtml = element.get_attribute('innerHTML')\nsoup = bs(html, &quot;lxml&quot;)\n\nprint (total_products)\n\nfor a in soup.find_all('a', href=True):\n    mylist.append(&quot;Found the URL: https:\/\/www.website.com&quot; + a&#x5B;'href'])\n\n# Python 3 only\nprint (*mylist, sep=&quot;\\n&quot;)\n\n# See the whole tree with price and description for each item\n# prettyHTML = soup.prettify()\n# print (prettyHTML)\n\nport = 587  \nsender_email = &quot;SENDER@gmail.com&quot;\nreceiver_email = &quot;RECEIVER@email.com&quot;\n\nmessage = &quot;&quot;&quot;\\\nSubject: new products have arrived!\n\n{}. &quot;&quot;&quot; .format(total_products) + str(mylist)\n\nserver = smtplib.SMTP('smtp.gmail.com', 587)\nserver.ehlo()\nserver.starttls()\nserver.ehlo()\nserver.login(sender_email, &quot;SENDERPASSWORD&quot;)\nserver.sendmail(sender_email, receiver_email, message)\nserver.quit()\n\ndriver.close()\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>I wrote a python script to query a website and check to see if an item is in stock. If it finds the product in question it will email me a report with a hyperlink so that I can click &hellip; <a href=\"https:\/\/technobabble.us.to\/?p=473\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[],"class_list":["post-473","post","type-post","status-publish","format-standard","hentry","category-python"],"_links":{"self":[{"href":"https:\/\/technobabble.us.to\/index.php?rest_route=\/wp\/v2\/posts\/473","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/technobabble.us.to\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/technobabble.us.to\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/technobabble.us.to\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/technobabble.us.to\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=473"}],"version-history":[{"count":9,"href":"https:\/\/technobabble.us.to\/index.php?rest_route=\/wp\/v2\/posts\/473\/revisions"}],"predecessor-version":[{"id":753,"href":"https:\/\/technobabble.us.to\/index.php?rest_route=\/wp\/v2\/posts\/473\/revisions\/753"}],"wp:attachment":[{"href":"https:\/\/technobabble.us.to\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=473"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/technobabble.us.to\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=473"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/technobabble.us.to\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=473"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}