From 9a530df0058795b79af190e6538bf3851cb99d5d Mon Sep 17 00:00:00 2001 From: progenitor Date: Sat, 7 Oct 2023 20:02:45 +0530 Subject: [PATCH] First commit! --- Workshop4- Homework/myworld/db.sqlite3 | Bin 0 -> 135168 bytes .../myworld/docker-compose.yml | 66 +++++++++ .../myworld/dockerfiles/Dockerfile | 14 ++ Workshop4- Homework/myworld/manage.py | 22 +++ Workshop4- Homework/myworld/members.zip | Bin 0 -> 9319 bytes .../myworld/members/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 159 bytes .../members/__pycache__/admin.cpython-310.pyc | Bin 0 -> 2331 bytes .../members/__pycache__/apps.cpython-310.pyc | Bin 0 -> 2630 bytes .../__pycache__/models.cpython-310.pyc | Bin 0 -> 2674 bytes .../members/__pycache__/tasks.cpython-310.pyc | Bin 0 -> 2289 bytes .../members/__pycache__/urls.cpython-310.pyc | Bin 0 -> 556 bytes .../members/__pycache__/views.cpython-310.pyc | Bin 0 -> 2840 bytes Workshop4- Homework/myworld/members/admin.py | 52 ++++++++ Workshop4- Homework/myworld/members/apps.py | 90 +++++++++++++ .../members/migrations/0001_initial.py | 22 +++ ...bstats_students_delete_members_and_more.py | 78 +++++++++++ .../myworld/members/migrations/__init__.py | 0 .../__pycache__/0001_initial.cpython-310.pyc | Bin 0 -> 699 bytes ...ts_delete_members_and_more.cpython-310.pyc | Bin 0 -> 2257 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 170 bytes Workshop4- Homework/myworld/members/models.py | 63 +++++++++ Workshop4- Homework/myworld/members/tasks.py | 83 ++++++++++++ Workshop4- Homework/myworld/members/tests.py | 3 + Workshop4- Homework/myworld/members/urls.py | 11 ++ Workshop4- Homework/myworld/members/views.py | 80 +++++++++++ .../myworld/myworld/__init__.py | 5 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 201 bytes .../__pycache__/celery.cpython-310.pyc | Bin 0 -> 694 bytes .../__pycache__/settings.cpython-310.pyc | Bin 0 -> 2390 bytes .../myworld/__pycache__/urls.cpython-310.pyc | Bin 0 -> 1006 bytes .../myworld/__pycache__/wsgi.cpython-310.pyc | Bin 0 -> 536 bytes Workshop4- Homework/myworld/myworld/asgi.py | 16 +++ Workshop4- Homework/myworld/myworld/celery.py | 33 +++++ .../myworld/myworld/settings.py | 126 ++++++++++++++++++ Workshop4- Homework/myworld/myworld/urls.py | 23 ++++ Workshop4- Homework/myworld/myworld/wsgi.py | 16 +++ Workshop4- Homework/myworld/p_file.prof | Bin 0 -> 13860 bytes Workshop4- Homework/myworld/script.py | 27 ++++ Workshop4- Homework/myworld/web_scrapper.py | 86 ++++++++++++ .../__pycache__/celery.cpython-310.pyc | Bin 0 -> 384 bytes .../__pycache__/run_tasks.cpython-310.pyc | Bin 0 -> 417 bytes .../__pycache__/tasks.cpython-310.pyc | Bin 0 -> 491 bytes Workshop4- Homework/test_celery/celery.py | 7 + Workshop4- Homework/test_celery/run_tasks.py | 13 ++ Workshop4- Homework/test_celery/tasks.py | 11 ++ 46 files changed, 947 insertions(+) create mode 100644 Workshop4- Homework/myworld/db.sqlite3 create mode 100644 Workshop4- Homework/myworld/docker-compose.yml create mode 100644 Workshop4- Homework/myworld/dockerfiles/Dockerfile create mode 100755 Workshop4- Homework/myworld/manage.py create mode 100644 Workshop4- Homework/myworld/members.zip create mode 100644 Workshop4- Homework/myworld/members/__init__.py create mode 100644 Workshop4- Homework/myworld/members/__pycache__/__init__.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/__pycache__/admin.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/__pycache__/apps.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/__pycache__/models.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/__pycache__/tasks.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/__pycache__/urls.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/__pycache__/views.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/admin.py create mode 100644 Workshop4- Homework/myworld/members/apps.py create mode 100644 Workshop4- Homework/myworld/members/migrations/0001_initial.py create mode 100644 Workshop4- Homework/myworld/members/migrations/0002_blog_job_joblogs_jobstats_students_delete_members_and_more.py create mode 100644 Workshop4- Homework/myworld/members/migrations/__init__.py create mode 100644 Workshop4- Homework/myworld/members/migrations/__pycache__/0001_initial.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/migrations/__pycache__/0002_blog_job_joblogs_jobstats_students_delete_members_and_more.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/migrations/__pycache__/__init__.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/members/models.py create mode 100644 Workshop4- Homework/myworld/members/tasks.py create mode 100644 Workshop4- Homework/myworld/members/tests.py create mode 100644 Workshop4- Homework/myworld/members/urls.py create mode 100644 Workshop4- Homework/myworld/members/views.py create mode 100644 Workshop4- Homework/myworld/myworld/__init__.py create mode 100644 Workshop4- Homework/myworld/myworld/__pycache__/__init__.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/myworld/__pycache__/celery.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/myworld/__pycache__/settings.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/myworld/__pycache__/urls.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/myworld/__pycache__/wsgi.cpython-310.pyc create mode 100644 Workshop4- Homework/myworld/myworld/asgi.py create mode 100644 Workshop4- Homework/myworld/myworld/celery.py create mode 100644 Workshop4- Homework/myworld/myworld/settings.py create mode 100644 Workshop4- Homework/myworld/myworld/urls.py create mode 100644 Workshop4- Homework/myworld/myworld/wsgi.py create mode 100644 Workshop4- Homework/myworld/p_file.prof create mode 100644 Workshop4- Homework/myworld/script.py create mode 100644 Workshop4- Homework/myworld/web_scrapper.py create mode 100644 Workshop4- Homework/test_celery/__pycache__/celery.cpython-310.pyc create mode 100644 Workshop4- Homework/test_celery/__pycache__/run_tasks.cpython-310.pyc create mode 100644 Workshop4- Homework/test_celery/__pycache__/tasks.cpython-310.pyc create mode 100644 Workshop4- Homework/test_celery/celery.py create mode 100644 Workshop4- Homework/test_celery/run_tasks.py create mode 100644 Workshop4- Homework/test_celery/tasks.py diff --git a/Workshop4- Homework/myworld/db.sqlite3 b/Workshop4- Homework/myworld/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..db2d4f3759b4a13456b4b75fe70ea5be6f9c0ce2 GIT binary patch literal 135168 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 K0T6gZ1pXHj{hRLq literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/docker-compose.yml b/Workshop4- Homework/myworld/docker-compose.yml new file mode 100644 index 0000000..f2aa4ee --- /dev/null +++ b/Workshop4- Homework/myworld/docker-compose.yml @@ -0,0 +1,66 @@ +version: "3" +services: + web_service: + build: + context: ./ + dockerfile: ./dockerfiles/Dockerfile + image: workshop1_web + container_name: workshop_web_container + stdin_open: true # docker attach container_id + tty: true + environment: + - RABBITMQ_DEFAULT_USER=myuser + - RABBITMQ_DEFAULT_PASS=mypassword + - BROKER_HOST=service-rabbitmq + - RABBITMQ_DEFAULT_VHOST=extractor + - BROKER_PORT=5672 + ports: + - "8000:8000" + volumes: + - .:/root/workspace/site + + psql-db: + image: 'postgres:14' + container_name: psql-db + environment: + - PGPASSWORD=123456 + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=123456 + ports: + - '5446:5432' + volumes: + - db:/var/lib/postgresql/data + + service-rabbitmq: + container_name: "service_rabbitmq" + image: rabbitmq:3.8-management-alpine + environment: + - RABBITMQ_DEFAULT_USER=myuser + - RABBITMQ_DEFAULT_PASS=mypassword + - RABBITMQ_DEFAULT_VHOST=extractor + - BROKER_HOST=service-rabbitmq + ports: + - '5673:5673' + - '15676:15672' + worker: + build: + context: ./ + dockerfile: ./dockerfiles/Dockerfile + image: workshop1_web + container_name: worker + stdin_open: true # docker attach container_id + tty: true + environment: + - RABBITMQ_DEFAULT_USER=myuser + - RABBITMQ_DEFAULT_PASS=mypassword + - BROKER_HOST=service-rabbitmq + - RABBITMQ_DEFAULT_VHOST=extractor + - BROKER_PORT=5672 + ports: + - "4356:8000" + volumes: + - .:/root/workspace/site + +volumes: + db: + driver: local diff --git a/Workshop4- Homework/myworld/dockerfiles/Dockerfile b/Workshop4- Homework/myworld/dockerfiles/Dockerfile new file mode 100644 index 0000000..3cfa40a --- /dev/null +++ b/Workshop4- Homework/myworld/dockerfiles/Dockerfile @@ -0,0 +1,14 @@ +FROM python:3.10.2-alpine3.15 +# Install required packages +# For psycopg2 +RUN apk update && \ +apk --no-cache add --virtual build-deps-alpine build-base && \ +apk --no-cache add --virtual postgresql-deps libpq-dev +# Install requirements +RUN pip install --upgrade pip +RUN pip install Django psycopg2==2.9.3 bs4 html5lib requests python-dateutil celery pytz +# Create directories +RUN mkdir -p /root/workspace/src +COPY ./ /root/workspace/site +# Switch to project directory +WORKDIR /root/workspace/site diff --git a/Workshop4- Homework/myworld/manage.py b/Workshop4- Homework/myworld/manage.py new file mode 100755 index 0000000..ffd27b1 --- /dev/null +++ b/Workshop4- Homework/myworld/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myworld.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/Workshop4- Homework/myworld/members.zip b/Workshop4- Homework/myworld/members.zip new file mode 100644 index 0000000000000000000000000000000000000000..338399d72180dde91ceb9c104eec6431eef2b213 GIT binary patch literal 9319 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 literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/__init__.py b/Workshop4- Homework/myworld/members/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Workshop4- Homework/myworld/members/__pycache__/__init__.cpython-310.pyc b/Workshop4- Homework/myworld/members/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..397ecc3e3d85d8a15bf55c38b0e64a8e738aa540 GIT binary patch literal 159 zcmd1j<>g`k0w<506cGIwL?8o3AjbiSi&=m~3PUi1CZpdU||3NO%5eX literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/__pycache__/admin.cpython-310.pyc b/Workshop4- Homework/myworld/members/__pycache__/admin.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df3d1ccbc1d53d5e4945fec425572d99a553d5a3 GIT binary patch literal 2331 zcmaJ@OOG2x5T2fw$K%J^P67dPSd0P;2%DD#f@Il1Bm@e3NWx_iX4ZP;h|b2!6I&arhUjgqe9@;B@7=JX{xkH{ikS9NUS#DnMk`MTH`I!Y zQc3N8n^$w~{8&wN1Ie{&E_HyD8!A;2ziWWFBR~qAwq_L+sY>=$kxxnO=0l2iaU7jR zBCMEkE4Dd{9d5@ichD49cdsti=UyRWB43BI45UiRv=F+Pr^nMq$~g!rbqlIIPs&v> z5up8|nq;}q{shu;x*stZ;8}Zz=uTo(B#91_q^S5R7dUSx$?a8|lX6<+8LH=*T;}OL z-7>3LmMZ~=7QBIq40(QW3{|DZcPqFhm+4fDWv0Zq5M+TIn;?#s_n?g*_&AP;1eVJJ zW_YK@1zISGF=$;~P{iv1c-m8$LYLYga*;}r@Kj+WCMc1p41?mQE45#NZcjnr7B>Ru z`8I0XgEL4^Y_Df;67K>MDg}7!c=d{5Hty`=kVH-r#_h)zCe7h4{<_=~PU3MNDPmo? zX71uVh#R~a2Rw|MyoJeaYwzj;VKXJQ#}CaZKHuSx=aDEZImNiG><4V&JYwAW&3(qAZC|`_a6>-uK&DuX`JrFft*6R%*r{!(M@44BNvRH zP1LR(sX*JyTam3@De{?is>xy_J`@`5z^d$#L1f)|cF;6-kC6K>+a27cc0sluQ8+n! zVxiUSDSL?abNhk)yTzS9(2Lss{%AB_R1-;cGydlG<@*nxpFho|gVu1z2$EBWj`r)y zf{S>L@#oNicWM3}674Qiwg0jk;hjv}O^gyk!4cWoW<7S$tNl6Ij-BhP@}~CciVk#u zR@N04;^%-hL6{3fS%XWr$||X531JXhK`l~N@HW}=K9Mn!$c9g8{u#}g+1!glpyG#f zL|!BELR|MHq8N`7n80kQvZ~Z!n&;KsM5S{Huah((L~kL^c~$23l36BlE;sx(MQY$Z zM9D22lFkdPfCY~4`ix%JHnm6+r$e6XdKK~ra+kXX@Lue5A0ghr+y*){AvN(k6(bO# zPQr1o#sNjIh5>wlI|t!#=Nhso;qW0c;3Fb0`VJUuHci&(Qxolv>BF-phmT%t!zZ|P zGiqoDlc{}7l3Gdl8kxGKDwXEz^qt$tWg>o2kWR6Qn5@C)C>^o5L2yWxxAvmo<@Aw0 z_=3onL?}tRBSi|+{r}6(S17lQLsFBZ>`-n@R%qvytQ_AQ#~rdRND5ZuXxD(#!I0?A z3`>-dW5A1+cgS*bUDoz{FWYZWwTowN#Q6k7S8#(;Q};+(?L}wfE?=bOyc$ibQb9HW z>JoJGaFI)(A_I>IwKc%M7#0LbbZh<93Q)@QqW&>QWw{*Dm1zoFhd+@j)BeqcVOlj1 zT!EqkWCwOHymWK`Vvcu~fd4XI2bb!LZinJ0sYA7`3#^Urz#g~*Z_povUBAod9k71@ Dqp2P2 literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/__pycache__/apps.cpython-310.pyc b/Workshop4- Homework/myworld/members/__pycache__/apps.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19d6611b34d2898affa3ad358b0a51871ace68f7 GIT binary patch literal 2630 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 literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/__pycache__/views.cpython-310.pyc b/Workshop4- Homework/myworld/members/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d25bb3ef935bfb174895c63fc6b1335f7577ff65 GIT binary patch literal 2840 zcmZ`*OOF#r5T2g5$78SYvXBQshCtAu#Ln}E5<);xa&RIRCCW(AXm+}Hcg#FYcRPUP zl_J4)r5tiZ5qpV*a>>ugZ|G}I+#^Lok&>$Ruy_f~sLNH;-PMo!>MPfsPGG?E_iuf6 zCNzvc(O7*PFfKzAzk{F#C52Ivm=J@S)GEx}}t?b1;Vz7YuG@$K$^K*lSv~%B}9Y*e1_egx~NMDz( zLEl=_*QY&t?7k7N(>`5?-{bW7rV(vChFu#GQT8`EyZxA;VJd%9&M2#-Q1+Fg-huA$ zOHo(XnV8mfbM%-_rviRGc1Q9w!(l#WH0Lan z%BQ)QrZU^bfmK?v4EM46SYTX+CQgH3Mog#?o7BZyy-#9`+SGwl*p$F2Jk@S?jHei9 zHcWZ?_@H3>44U`_#E!9N&o>q(??_`pCg#GVWS{KWRcm4K6U{e^n)vNoqguBO_-5U` zNDO?XO)ZS%1Cu(`-8Wt1J7d$hjb5FFebxB>#GbowCk{0H^`QCCTF?UOJ#hEDh4Zkz z@D2bWw?^R2UpU%Z3%$Wvf-zi4o7Y8=RI_r6;Z?d@Jgu@_>d%m4kvu%s$e_kLMC{#s#T;jI3{!4dZ-GDFL&FoZEQ7Ace}EN* z9Pdzh_0|N!C1B;ekc_MFYR$yBme=m&LUI?z@RKNBLGdaI^vqvFq20QG0#?z;SGHiq zw(>Z;HDf}?4ji$n^`N-loFXY}%8H~w-^am4>@^+Arm0LH8T=f4eR6)p>spR(*Zd}c zC}Sg$OExMQ-j*2s01yzv>0M>*FxiFi;vxu}n8YSMXkB9e*d-^3`LAvI#5QgCwtU?u zq2DL-wG}K4!AEAo{HG7cJ`fCe?$B;d=-Se6)EmD%P{-gH^YyeS z2HQC+s2E_3AWs2k8c)hA0T}5H%l`t9@eLTR*hKK_^&JaBO6c~}K?61GtyushX zZjBKH6MsVw%s5LWi%fn7znw*aL0yXTIK-aTLcR%_K>wFWpSUDgdEF;HZ{AxC5>ANB z@i=mnpJ>o0i3$>g)2v{ihe>j4mKK-}NwVD6+lPxDU7jOk+PFII+&2O%+|b`LFpoS4 zh0D+cLiLcL2sMG1ENVe6+sa4&L{d5eBCIIrU4!UnP@3=o#~qk^W@DM!vKk9m2m0*B zvbE(%b7C#bg|)DOMVx)8G7{kP&^<8rTwo+%A7G^Zp1<&ciF{xpADGAoCUPIxd#!~B zOw`g$G?XFr7Du2MwZ|#|n&C2mTB>W0JLVCLn4i72 zEZK|>(uxkI^>kK1#OOfovVlyu3O3{yVBkuWERM0^AED4!N?w@T$EJ57=2fEaQ)E1y zegQL<+lNHwm%uubDwt#zG`)R925x@=Y`Z+bJuLs`c)mVLX_;4tMPO2IjUtOA<0u#U0k6*mO&$N=?(%A93={MQ1L70@30UK3LxpsbRy*}jR~wGI#BvHN z30*lgBvrc^v@7LQ--GESljKKU0jUEYC-oWaU;9TGI HPlnEa6uOUS literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/admin.py b/Workshop4- Homework/myworld/members/admin.py new file mode 100644 index 0000000..e66a10e --- /dev/null +++ b/Workshop4- Homework/myworld/members/admin.py @@ -0,0 +1,52 @@ +from django.contrib import admin +from .models import Students, Blog, Job, JobLogs, JobStats +from django.urls import reverse +from django.utils.html import format_html + +class DjStudentAdmin(admin.ModelAdmin): + list_display = ("first_name", "last_name", "address", "roll_number", "mobile", "branch") + list_filter = ("branch",) + +class DjBlogAdmin(admin.ModelAdmin): + list_display = ("title", "release_date", "blog_time", "author", "created_date") + list_filter = ("author",) + + +class DjJob(admin.ModelAdmin): + def run(self, obj): + return format_html('RUN', reverse('scraping', args=(str(obj.pk)))) + + def view_stats(self, obj): + path = "../jobstats/?q={}".format(obj.pk) + return format_html(f'''stats''') + + run.short_description = 'Run' + run.allow_tags = True + view_stats.short_description = 'Stats' + view_stats.allow_tags = True + + list_display = ("job_name", "start_date", "end_date", "no_of_blogs", "start_no", "created_date", "run", "view_stats") + list_filter = ("job_name", "start_date") + readonly_fields = ("created_date",) + +class DjJobStats(admin.ModelAdmin): + def view_logs(self, obj): + path = "../joblogs/?q={}".format(obj.pk) + return format_html(f'''Logs''') + + view_logs.short_description = 'Stats' + view_logs.allow_tags = True + list_display = ("job", "status", "view_logs", "total_blogs", "no_of_blogs_extracted", "start_date", "end_date") + search_fields = ('job__pk',) + +class DjJobLogs(admin.ModelAdmin): + list_display = ("date", "log", "function_name") + search_fields = ('job_stats__pk',) + + +# Register your models here. +admin.site.register(Blog, DjBlogAdmin) +admin.site.register(Students, DjStudentAdmin) +admin.site.register(Job, DjJob) +admin.site.register(JobStats, DjJobStats) +admin.site.register(JobLogs, DjJobLogs) diff --git a/Workshop4- Homework/myworld/members/apps.py b/Workshop4- Homework/myworld/members/apps.py new file mode 100644 index 0000000..21366a2 --- /dev/null +++ b/Workshop4- Homework/myworld/members/apps.py @@ -0,0 +1,90 @@ +from django.apps import AppConfig +import psycopg2 +import requests +import re +from bs4 import BeautifulSoup, element +import datetime +from dateutil.parser import parse + + +db_name = 'member_db' +db_user = 'postgres' +db_pass = '123456' +db_host = 'psql-db' +db_port = '5432' + +conn = psycopg2.connect(dbname=db_name, user=db_user, password=db_pass, host=db_host, port=db_port) + +def add_row_to_blog(title, author, date, time): + sql = """INSERT INTO members_blog (title, release_date, blog_time, author, created_date) VALUES (%s, %s::DATE, %s::TIME, %s, NOW())""" + + with conn: + with conn.cursor() as curs: + time=time.replace('\u202f',"") + curs.execute(sql, (title, date, time, author)) + +def truncate_table(): + print("Truncating contents all the tables") + with conn: + with conn.cursor() as curs: + curs.execute("TRUNCATE members_blog CASCADE;") + +def start_extraction(start_date=None, end_date=None): + print("Extraction started") + url = "https://blog.python.org/" + + data = requests.get(url) + page_soup = BeautifulSoup(data.text, 'html.parser') + + if start_date: + start_date = parse(start_date) + if end_date: + end_date = parse(end_date) + + blogs = page_soup.select('div.date-outer') + truncate_table() + for blog in blogs: + date = blog.select('.date-header span')[0].get_text() + + converted_date = parse(date) + + if start_date and converted_date < start_date: + continue + if end_date and converted_date > end_date: + continue + + post = blog.select('.post')[0] + + title = "" + title_bar = post.select('.post-title') + if len(title_bar) > 0: + title = title_bar[0].text + else: + title = post.select('.post-body')[0].contents[0].text + + # getting the author and blog time + post_footer = post.select('.post-footer')[0] + + author = post_footer.select('.post-author span')[0].text + + time = post_footer.select('abbr')[0].text + + add_row_to_blog(title, author, date, time) + + print("\nTitle:", title.strip('\n')) + print("Date:", date, ) + print("Time:", time) + print("Author:", author) + + # print("Number of blogs read:", count) + print( + "\n---------------------------------------------------------------------------------------------------------------\n") + +if __name__ == "__main__": + start_extraction() + + +class MembersConfig(AppConfig): + default_auto_field='django.db.models.BigAutoField' + name = 'members' + diff --git a/Workshop4- Homework/myworld/members/migrations/0001_initial.py b/Workshop4- Homework/myworld/members/migrations/0001_initial.py new file mode 100644 index 0000000..0a7cee3 --- /dev/null +++ b/Workshop4- Homework/myworld/members/migrations/0001_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2 on 2023-05-23 05:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Members', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('firstname', models.CharField(max_length=255)), + ('lastname', models.CharField(max_length=255)), + ], + ), + ] diff --git a/Workshop4- Homework/myworld/members/migrations/0002_blog_job_joblogs_jobstats_students_delete_members_and_more.py b/Workshop4- Homework/myworld/members/migrations/0002_blog_job_joblogs_jobstats_students_delete_members_and_more.py new file mode 100644 index 0000000..a5a46ad --- /dev/null +++ b/Workshop4- Homework/myworld/members/migrations/0002_blog_job_joblogs_jobstats_students_delete_members_and_more.py @@ -0,0 +1,78 @@ +# Generated by Django 4.2.5 on 2023-09-26 07:44 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Blog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=500)), + ('release_date', models.DateTimeField(verbose_name='Realse Date')), + ('blog_time', models.CharField(max_length=50)), + ('author', models.CharField(max_length=200)), + ('created_date', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Created Date')), + ], + ), + migrations.CreateModel( + name='Job', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('job_name', models.CharField(max_length=500)), + ('start_date', models.DateTimeField(null=True, verbose_name='Blog start date')), + ('end_date', models.DateTimeField(null=True, verbose_name='Blog end date')), + ('start_no', models.IntegerField(null=True, verbose_name='No of blogs to skip')), + ('no_of_blogs', models.IntegerField(null=True, verbose_name='No of blogs to extract')), + ('created_date', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Job created date')), + ], + ), + migrations.CreateModel( + name='JobLogs', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('log', models.TextField(verbose_name='job logs')), + ('function_name', models.TextField(verbose_name='Function name')), + ('date', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Log date')), + ], + ), + migrations.CreateModel( + name='JobStats', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('status', models.CharField(max_length=50)), + ('total_blogs', models.IntegerField(null=True, verbose_name='Total blogs found')), + ('no_of_blogs_extracted', models.IntegerField(null=True, verbose_name='No of blogs extracted')), + ('start_date', models.DateTimeField(null=True, verbose_name='Extraction start date')), + ('end_date', models.DateTimeField(null=True, verbose_name='Extraction start date')), + ('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.job')), + ], + ), + migrations.CreateModel( + name='Students', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('first_name', models.CharField(max_length=200)), + ('last_name', models.CharField(max_length=200)), + ('address', models.CharField(max_length=200)), + ('roll_number', models.IntegerField()), + ('mobile', models.CharField(max_length=10)), + ('branch', models.CharField(choices=[('BA', 'BA'), ('B.COM', 'B.COM'), ('MBA', 'MBA'), ('CA', 'CA')], max_length=10, null=True)), + ], + ), + migrations.DeleteModel( + name='Members', + ), + migrations.AddField( + model_name='joblogs', + name='job_stats', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='members.jobstats'), + ), + ] diff --git a/Workshop4- Homework/myworld/members/migrations/__init__.py b/Workshop4- Homework/myworld/members/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Workshop4- Homework/myworld/members/migrations/__pycache__/0001_initial.cpython-310.pyc b/Workshop4- Homework/myworld/members/migrations/__pycache__/0001_initial.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..350ce33b738936c3a76ee8bb087e079e18ac0f5a GIT binary patch literal 699 zcmYjP&2G~`5Z+xoiS4)*2h^eZW!Zi=V zEA5q2-vA*&89PPItadct&S-wVS$%L2F_K>w1)K=Rezss=d;({5?J+4}zzbILl$RnE zoV{Tn!28a?L%#C9d8r5fJ2vXwP%Ik>7nLeES)+7iUBA?Tg`KyqeF+Ji(Y05kkfj`0 zDuAb6&Qc$HtA1Mo2de-$9Upqo-}(yy19}S~fN;wRMf)iCV7L`IPa}w_odXw6|Mzj_ z22(6&Xsi5sH{+5(Z!$8%(O*WWhJ_B zp^R->^X8U1A90#C`yvah@@DCRBHKBM1;2~$FBBGFFGoWc$S#GHE|QXHSrvY-@YP|L(ex>r4G{bpY!-bP&W_D(zYrNaQ z4`v=wY^Q#|O_sXEq&7N7Dx^*FzETstHjVtC&9zw^tFEkmC z$4}&4m#6i{v_GX!*B+4ym@nw~fuXi@7AiLs(^1u1{gsP1Ft1IqzHC WS&u1~3!d*tdcoWDZJh_=$omIm%fX-k literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/migrations/__pycache__/0002_blog_job_joblogs_jobstats_students_delete_members_and_more.cpython-310.pyc b/Workshop4- Homework/myworld/members/migrations/__pycache__/0002_blog_job_joblogs_jobstats_students_delete_members_and_more.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8e6d3cb922bf8950fe0d80bbd08188c3e4d6d31 GIT binary patch literal 2257 zcmZuyNpl-T6rSlBNi$k($4Q)oRqTjGa#je05Lu2>0qj&^pLCfT>9yohM$@LJl|=_G zaHI4efE)jV1HYlKoP6WJg%sQCMYf#sOlj2L>(}pnZ|QDUtCbym{`g^)-dlE@-xXMV zd<1v!mpAbP4!Ef^cDwGFbcw4lNxiOr&jAno?;Y@|J1TtVbqhdtokrmh*EkI#%j0Co zW09~dm&Gvyn&vxwHMjVzBDjOU{1I^+>U3Rjx&+*z+x4hFLW|(h;-~~Zz6B^kY32_I z1Skt2g!0TqR6!I%6>1tS>A7V)x1!M*i&nL!vUL{D&Ab5_7UBGiXisaWdb*(3&plnV z>o36zGlHI9wD={9Uq)O;>#tb+s>OASkNv-9{g;mXzkaI!H_$=_-n6m3rP13Ky@M#! znR(Y*^N*}GPPO(Pt_WbBoA(hZwjWq_A6neBcph!b;(4@lypH-+S{p5milgPx3S5RO zDl5a|n6946;+keLugUcj=*9{35iR~${>i~if2`#<3pp3Ca``ugQ4$r6#o zsq{BeHk2fRy)8-ZZ#H~cjVFRdeNJORK~@fUGLHGv=plV7!<=$lluW6tKBBzGavEjv zn971kL`suCUECrrZjty&l+tV{_GOjRl*XtBXl`2hn#O5P>zfD~F0bJhkzo%RL?Ri} z!z&6G(f>Zpe>~V~?X4K>FDvO|?x7*Vnv?gM_A#OYaNTlfj7f z4Bc`rVlIr$WtD)s7St8T2H_Xbv*8xd42)V$t0B}%GB6f0Ha)w;>TFO~LF9G8>iNUu zKvpsqu|cGT)3xU`=o7)?zL>5csk)8NSS_LCE3_j$v^G_I>&mRG4JKJ%9XXo*w6+cZ>XUs zOZ|P8^l8rVc5rl=Wog@N3+%>=DD0MyxXyWqgGl8spROzfr6p*ptdD*jfLPq3Bl2kX6VH-E& zmTF=dcJ^a#hBdW+_Hf4-SiPSKI;3_o+{03tiSicXG#O@J;@&O7D9(mV62P6HYl8KY zrA~Xd)84!*E1SAZ+Pe(e0M-IKp!T-=#o;?DZR+!E)Z&bZ)?>yW<_B?~w(>;Kmd#V^ z_=;@dVRJ<{UZnDAldJx9A~C_HA#9gK)3@^A4IIK=b+^9#g1 zN0wakuDaxz|F2&$vK807DE$ki)ww3(zY&KgwJtuVwd9u3>e`VMeR;&iHLm|p@T=z1 zD9X?zvk5(2J5#PpN5ZCVj=VWfGrxz-_1fbUn$ZKCkijj}CAabTbn+s8R!HEkdH(}> CLYMCV literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/migrations/__pycache__/__init__.cpython-310.pyc b/Workshop4- Homework/myworld/members/migrations/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c09359e3b93067c560db2d7a604ab5796296315 GIT binary patch literal 170 zcmd1j<>g`k0w<506cGIwL?8o3AjbiSi&=m~3PUi1CZpdAw ml9``ZtREkr3Dg-MuUAlci^C>2KczG$)edA$F%ytrVE_O%q$$Dx literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/members/models.py b/Workshop4- Homework/myworld/members/models.py new file mode 100644 index 0000000..3d5a455 --- /dev/null +++ b/Workshop4- Homework/myworld/members/models.py @@ -0,0 +1,63 @@ +from django.db import models + +BRANCH_CHOICES = ( + ("BA", "BA"), + ("B.COM", "B.COM"), + ("MBA", "MBA"), + ("CA", "CA"), +) + + +# Create your models here. +class Students(models.Model): + first_name = models.CharField(max_length=200) + last_name = models.CharField(max_length=200) + address = models.CharField(max_length=200) + roll_number = models.IntegerField() + mobile = models.CharField(max_length=10) + branch = models.CharField(max_length=10, choices=BRANCH_CHOICES, null=True) + + def __str__(self): + return self.first_name + " " + self.last_name + + +class Blog(models.Model): + title = models.CharField(max_length=500) + release_date = models.DateTimeField('Realse Date') + blog_time = models.CharField(max_length=50) + author = models.CharField(max_length=200) + created_date = models.DateTimeField('Created Date', auto_now_add=True, null=True) + + def __str__(self): + return self.title + + +class Job(models.Model): + job_name = models.CharField(max_length=500) + start_date = models.DateTimeField('Blog start date', null=True) + end_date = models.DateTimeField('Blog end date', null=True) + start_no = models.IntegerField(verbose_name="No of blogs to skip", null=True) + no_of_blogs = models.IntegerField(verbose_name="No of blogs to extract", null=True) + created_date = models.DateTimeField('Job created date', auto_now_add=True, null=True) + + def __str__(self): + return self.job_name + + +class JobStats(models.Model): + job = models.ForeignKey(Job, on_delete=models.CASCADE) + status = models.CharField(max_length=50) + total_blogs = models.IntegerField(verbose_name="Total blogs found", null=True) + no_of_blogs_extracted = models.IntegerField(verbose_name='No of blogs extracted', null=True) + start_date = models.DateTimeField('Extraction start date', null=True) + end_date = models.DateTimeField('Extraction start date', null=True) + + def __str__(self): + return self.job + + +class JobLogs(models.Model): + job_stats = models.ForeignKey(JobStats, on_delete=models.CASCADE) + log = models.TextField(verbose_name="job logs") + function_name = models.TextField(verbose_name="Function name") + date = models.DateTimeField('Log date', null=True, auto_now_add=True) diff --git a/Workshop4- Homework/myworld/members/tasks.py b/Workshop4- Homework/myworld/members/tasks.py new file mode 100644 index 0000000..4961583 --- /dev/null +++ b/Workshop4- Homework/myworld/members/tasks.py @@ -0,0 +1,83 @@ +import datetime +from myworld.celery import app +from .models import Job, Blog, JobStats, JobLogs +import requests +from bs4 import BeautifulSoup +from dateutil.parser import parse +import pytz + +utc=pytz.UTC + +@app.task(bind=True, name="extract") +def extract(self, job_id): + job_obj = Job.objects.get(pk=job_id) + job_stats_obj = JobStats(job=job_obj, status="IN PROGRESS", start_date=datetime.datetime.now(), no_of_blogs_extracted=0) + job_stats_obj.save() + JobLogs(job_stats=job_stats_obj, log="Extraction stated", function_name="extract", date=datetime.datetime.now()).save() + start_date = job_obj.start_date + end_date = job_obj.end_date + start_id = job_obj.start_no + no_of_articles = job_obj.no_of_blogs + url = "https://blog.python.org/" + try: + data = requests.get(url) + page_soup = BeautifulSoup(data.text, 'html.parser') + + blogs = page_soup.select('div.date-outer') + article_count = 0 + counter = 1 + for blog in blogs: + article_count += 1 + if start_id and article_count < int(start_id): + continue + if no_of_articles and counter > int(no_of_articles): + continue + date = blog.select('.date-header span')[0].get_text() + + converted_date = parse(date) + JobLogs(job_stats=job_stats_obj, log=f"Extracting {article_count}", function_name="extract", date=datetime.datetime.now()).save() + if start_date and utc.localize(converted_date) < start_date: + continue + if end_date and utc.localize(converted_date) > end_date: + continue + + post = blog.select('.post')[0] + + title = "" + title_bar = post.select('.post-title') + if len(title_bar) > 0: + title = title_bar[0].text + else: + title = post.select('.post-body')[0].contents[0].text + + # getting the author and blog time + post_footer = post.select('.post-footer')[0] + + author = post_footer.select('.post-author span')[0].text + + time = post_footer.select('abbr')[0].text + + blog_obj = Blog(title=title, author=author, release_date=date, blog_time=time) + blog_obj.save() + job_stats_obj.no_of_blogs_extracted += job_stats_obj.no_of_blogs_extracted + job_stats_obj.save() + + print("\nTitle:", title.strip('\n')) + print("Date:", date, ) + print("Time:", time) + print("Author:", author) + counter += 1 + JobLogs(job_stats=job_stats_obj, log=f"Total {counter} articles extracted: ", function_name="extract", date=datetime.datetime.now()).save() + job_stats_obj.end_date = datetime.datetime.now() + job_stats_obj.total_blogs = article_count + job_stats_obj.status = "COMPLETED" + job_stats_obj.save() + JobLogs(job_stats=job_stats_obj, log="Extraction Done", function_name="extract", date=datetime.datetime.now()).save() + except Exception as ex: + JobLogs(job_stats=job_stats_obj, log=str(ex), function_name="extract", date=datetime.datetime.now()).save() + job_stats_obj.end_date = datetime.datetime.now() + job_stats_obj.total_blogs = article_count + job_stats_obj.status = "FAILED" + job_stats_obj.save() + JobLogs(job_stats=job_stats_obj, log="Extraction Done", function_name="extract", date=datetime.datetime.now()).save() + diff --git a/Workshop4- Homework/myworld/members/tests.py b/Workshop4- Homework/myworld/members/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/Workshop4- Homework/myworld/members/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/Workshop4- Homework/myworld/members/urls.py b/Workshop4- Homework/myworld/members/urls.py new file mode 100644 index 0000000..50c5bd5 --- /dev/null +++ b/Workshop4- Homework/myworld/members/urls.py @@ -0,0 +1,11 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('rest/student/', views.StudentView.as_view()), + path('rest/student/', views.StudentView.as_view()), + path('rest/student/', views.StudentView.as_view()), + path('start_python_blog_scraping', views.python_blog_scrap, name='triger'), + path('blog/', views.BlogView.as_view()), + path('python_blog_scraping/', views.python_blog_scraping, name="scraping") +] diff --git a/Workshop4- Homework/myworld/members/views.py b/Workshop4- Homework/myworld/members/views.py new file mode 100644 index 0000000..77b1bcf --- /dev/null +++ b/Workshop4- Homework/myworld/members/views.py @@ -0,0 +1,80 @@ +from django.views import View +from .models import Students, Blog +from django.http import JsonResponse +from django.views.decorators.csrf import csrf_exempt +from django.utils.decorators import method_decorator +from . import apps +from members.tasks import extract +from django.shortcuts import redirect + + +@method_decorator(csrf_exempt, name='dispatch') +class StudentView(View): + + def get(self, request, rolno=None, branch=None): + student_model_list = [] + try: + if rolno: + student_model_list = Students.objects.filter(roll_number=rolno) + elif branch: + student_model_list = Students.objects.filter(branch=branch) + except Students.DoesNotExist: + return JsonResponse({'status': 'failed', "students": None}, status=400) + students = [] + for student in student_model_list: + data = { + "first_name" : student.first_name, + "last_name": student.last_name, + "address": student.address, + "roll_number": student.roll_number, + "mobile": student.mobile, + "branch": student.branch + } + students.append(data) + return JsonResponse({'status': 'success', "students": students}, status=200) + def post(self, request): + if not request.POST.get('first_name') or not request.POST.get('last_name') or not request.POST.get('address') or not request.POST.get('roll_number') or not request.POST.get('mobile'): + return JsonResponse({'status': 'failed', "message" : "all fields required"}, status=500) + Students.objects.create( + first_name= request.POST.get('first_name'), + last_name= request.POST.get('last_name'), + address= request.POST.get('address'), + roll_number= request.POST.get('roll_number'), + mobile= request.POST.get('mobile'), + branch= request.POST.get('branch')) + return JsonResponse({'status': 'sucess'}, status=200) + + +@method_decorator(csrf_exempt, name='dispatch') + +class BlogView(View): + def post(self, request): + start_date = request.POST.get('start_date', None) + end_date = request.POST.get('end_date', None) + no_of_articles = request.POST.get('no_of_articles', None) + start_id = request.POST.get('start_id', None) + + apps.start_extraction(start_date=start_date, end_date=end_date, no_of_articles=no_of_articles, start_id=start_id) + + blog_model_list = Blog.objects.filter() + + blogs = [] + for blog in blog_model_list: + data = { + "Title": blog.title, + "Release Date": blog.release_date, + "Author": blog.author, + "Blog time": blog.blog_time + } + blogs.append(data) + + return JsonResponse({'status': 'success', "students": blogs}, status=200) + +def python_blog_scrap(request): + apps.start_extraction() + return JsonResponse({'status': 'sucess', "message" : "Extracted and populated the table."}, status=200) + + +def python_blog_scraping(request, job_id): + extract.delay(job_id) + return redirect('/admin/members/job/') diff --git a/Workshop4- Homework/myworld/myworld/__init__.py b/Workshop4- Homework/myworld/myworld/__init__.py new file mode 100644 index 0000000..15d7c50 --- /dev/null +++ b/Workshop4- Homework/myworld/myworld/__init__.py @@ -0,0 +1,5 @@ +# This will make sure the app is always imported when +# Django starts so that shared_task will use this app. +from .celery import app as celery_app + +__all__ = ('celery_app',) diff --git a/Workshop4- Homework/myworld/myworld/__pycache__/__init__.cpython-310.pyc b/Workshop4- Homework/myworld/myworld/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..407b40a1ba6bcc0b8bb8d95c8cae7bfbd99e501c GIT binary patch literal 201 zcmd1j<>g`kf{sd|)OA4mF^GcDj69D28FNXjC literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/myworld/__pycache__/celery.cpython-310.pyc b/Workshop4- Homework/myworld/myworld/__pycache__/celery.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff056ff8ac3b4dc9b740d9fffab067c1855cedea GIT binary patch literal 694 zcmYjP&2G~`5Z+zeiR1iGLd1y!C!`#b+$)5N(x?KJRBFNjUo6M72~Hhv*j*PAaVsaJ zJ^>)LM;?He*(;~MLJx>pH=vHRGoIP;eBXRp(QF0;P5x^0uMQ!^@l z83}D<8C|iEQNqd6xpKh)_u6I*ybBt7+*?+l0#)!YZPmM~UK1OaKGYz%q)>;(7lNHN zXhI7fz#csO?xYkuf~XF3Lb~l6L?q)bHI*UHxZIe>hp%6bk4~b=XgYm0KAJ>tP7dE5 zkG6ZO%|{_K=qs*unlDsX-Bq?7SjPE6^b?WK_y1p4hNI)r={p=<%i|SS>p0<4%-mU; zLqaX?&g?hJLWX!$2c1RK`=%EsH;DgRJ#rT3q9neo;#&9$k@yPBP> zcsBn@WDQ5$J{w3O^Z+@ZmCyr~YChOe9wg@xxhP%q%~xX83|;`KUgTNTqqG?!u(iP@4TI&8;<7Lck$oO4-HRkDR+N|wg8 ye}v5$k9G79xzymEv+vLN&sW0IdSThBC+K|Ape@H|t%~miPC%K*N^@@;fBpjD*SSUj literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/myworld/__pycache__/settings.cpython-310.pyc b/Workshop4- Homework/myworld/myworld/__pycache__/settings.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4147a4b69fe8c6c830e5270e2ea2921264c89fc1 GIT binary patch literal 2390 zcma)7-Ba5}5SNT>3jzs&Kp-D&X_GW2gPa7KCYdHhwgvHETdpObxfhM>JDdZ3p_4-q z!&Co_JS2JOO#dal_Ng;{?n9;>x)O5YF_|gW=vKG8zumjv?w#FqAogvlzr>@OHFhk1)bvCLS!ok1C%BN;OCEB{t_$L(f!vnYp0P#z0N#Mv&7M!Ou& zz30&w$UMjkSVZGE)(SY*U3kw^9*@5fz;^;qpo{n-zJw?7Wjuwa@fAGtCP#U63D4rI z;5Uosl5sv6uTj1$phOzsF^v)s+q2AoNNs=< z2Qw)(RFZDgQ!_(TNo)KP7@qHTU{S8m3PN~yILuiu36plO8!n#1(Kg}3 z8aQV3Gm&Ga!{s68k1T!$(6<$YC|{Dx8%m=R36*L~L!#Vl8p&5)ZR%CEp@nmO!VXxM z#$5|6Cnb#XnCzH6D+q6YN@Km+P$Hor*A*meYDx=Qf!p~^YcckQ-|6;yGERD@ahx($MfP( z4_Px^)EZX)nQ0quEjQ9>U zj3^I{vEh{i{|7_{e{tQQe#W5Rl%sXv}mFxH`X`hb;T&F6$JuT>xzL?=x-7DGO7%Et!ek~N k&-;(?A<>-(0@(ZS-@>#2FnDr87DgVP%p^a_i@f;ne|y>*g#Z8m literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/myworld/__pycache__/urls.cpython-310.pyc b/Workshop4- Homework/myworld/myworld/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..03ba69e6e9963d43f23f8fbfcf29d9385049b59a GIT binary patch literal 1006 zcmb7DL2uJA7Mm!08B`|WNGZSF0mci4r4uV>9650 z<;sb_zya|&O;Lq}1eW4B(ewM>d!Mb2k3$4QUl;VOgU~nkaX13_cma=b6GbybJ?a;p z@Mpf~)}5jwf>|KCv#y6&mj*1L-L1FvVSU8>_0hVw^_TvvPkZlB+|R!F2!*$AU*lZK z1z%P=vs_8MP#TMed!-ACORd%{w@DbjUom`F>7vZ6Wm=j$TySHtR+VK21B<~{;ZL01 zn*?7u3Z)t564=C!w=7s@7&eSeLkweOZE2>2P?ej6t~0q*`*OJwgh}!&nGmZ=o*Ux8 z1j-u{zWSUA;4;(js*-slxhdO_K27jTN^vGJ7p2m6it$1#0fy47EZd(unGJr@;++F$ z;J_hl1+%MB6pdS7D<#+%%S^EI$gQI|yeu+fPUm2Z9qoS z;gigyj${=7q3A~DMMb$>LI_PgXU%nZpU+Jb3 zjrQ0ts^n`=`~oMuNs%&=XEYwYd2eQLcQ+-`-kfTAlMwRQB%9Wb$zgo%eRPtHh)g8a z$ta1jrD@d~wGsl!tbMyB+j8rU#;kQsM%$7ONq76|A^kDz^;v;tqDnSF%c|u9t(L5| zID^7xY1;P;e%I*0F+T;i1_-UiPYp~sCRl~?Qo}n9bI@!qtXh?fs6evuSk$#vh42c^ zcpUqEX;{z#QzjBts{%t4n=8jAO2b>`0Me=Vwfn@m#KL8ACQOO{H5FKKF#KcoflqPa zkxQsGE-NseFI=g3`X{b~47y2pRf5l(zkEYRczt|!H0Yh@!;_1P{-8I^znvd{|9Wz@ z_cVRxzqO`|x~&@t)Y` wkSq6hpIgMJ6zwlpivqY)9{3aWYJjX>hMmvrwI0N~6W5^IWarrn`jV#fAH5W%d;kCd literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/myworld/asgi.py b/Workshop4- Homework/myworld/myworld/asgi.py new file mode 100644 index 0000000..36404b3 --- /dev/null +++ b/Workshop4- Homework/myworld/myworld/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for myworld project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myworld.settings') + +application = get_asgi_application() diff --git a/Workshop4- Homework/myworld/myworld/celery.py b/Workshop4- Homework/myworld/myworld/celery.py new file mode 100644 index 0000000..b4eaa53 --- /dev/null +++ b/Workshop4- Homework/myworld/myworld/celery.py @@ -0,0 +1,33 @@ +import os +from celery import Celery + +# Set the default Django settings module for the 'celery' program. +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myworld.settings') + +app = Celery('myworld') + +# Using a string here means the worker doesn't have to serialize +# the configuration object to child processes. +# - namespace='CELERY' means all celery-related configuration keys +# should have a `CELERY_` prefix. +app.config_from_object('django.conf:settings', namespace='CELERY') + +# Load task modules from all registered Django apps. +app.autodiscover_tasks() + + +@app.task(bind=True) +def debug_task(self): + print(f'Request: {self.request!r}') + +app.conf.beat_schedule = { + #Scheduler Name + 'run-task-ten-seconds': { + # Task Name (Name Specified in Decorator) + 'task': 'extract', + # Schedule + 'schedule': 60.0, + # Function Arguments + 'args': (1,) + } +} diff --git a/Workshop4- Homework/myworld/myworld/settings.py b/Workshop4- Homework/myworld/myworld/settings.py new file mode 100644 index 0000000..5f09aba --- /dev/null +++ b/Workshop4- Homework/myworld/myworld/settings.py @@ -0,0 +1,126 @@ +import os + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-p(&-i=zw$r=bqzck3oi3y9%*4ps!a*ierb803y_jcpqd+!z_9@' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'members.apps.MembersConfig' +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'myworld.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'myworld.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/4.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'member_db', + 'USER': 'postgres', + 'PASSWORD': '123456', + 'HOST': 'psql-db', + 'PORT': 5432, + } +} + +# Password validation +# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/4.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/4.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +CELERY_TASK_SERIALIZER = 'json' +CELERY_RESULT_SERIALIZER = 'json' +CELERY_TIMEZONE = 'America/Los_Angeles' +# This configures rabbitmq as the datastore between Django + Celery +CELERY_BROKER_URL = 'amqp://{0}:{1}@{2}:{3}/{4}'.format( + os.environ["RABBITMQ_DEFAULT_USER"], os.environ["RABBITMQ_DEFAULT_PASS"], + os.environ["BROKER_HOST"], os.environ["BROKER_PORT"], + os.environ["RABBITMQ_DEFAULT_VHOST"]) diff --git a/Workshop4- Homework/myworld/myworld/urls.py b/Workshop4- Homework/myworld/myworld/urls.py new file mode 100644 index 0000000..921daef --- /dev/null +++ b/Workshop4- Homework/myworld/myworld/urls.py @@ -0,0 +1,23 @@ +""" +URL configuration for myworld project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import include, path + +urlpatterns = [ + path('members/', include('members.urls')), + path('admin/', admin.site.urls), +] diff --git a/Workshop4- Homework/myworld/myworld/wsgi.py b/Workshop4- Homework/myworld/myworld/wsgi.py new file mode 100644 index 0000000..cb3f79d --- /dev/null +++ b/Workshop4- Homework/myworld/myworld/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for myworld project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myworld.settings') + +application = get_wsgi_application() diff --git a/Workshop4- Homework/myworld/p_file.prof b/Workshop4- Homework/myworld/p_file.prof new file mode 100644 index 0000000000000000000000000000000000000000..ed2ed94f528ad2be8b5c2f3e2dcd2fbae8ebe872 GIT binary patch literal 13860 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 ZG))|QByaKTdo4gupKaBR+rX2Y{C~3SLk$1` literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/myworld/script.py b/Workshop4- Homework/myworld/script.py new file mode 100644 index 0000000..d2edb6f --- /dev/null +++ b/Workshop4- Homework/myworld/script.py @@ -0,0 +1,27 @@ +import random +from memory_profiler import profile +# Simple function to print messages +@profile +def print_msg(): + for i in range(10): + print("Program completed") + +# Generate random data +@profile +def generate(): + data = [random.randint(0, 99) for p in range(0, 1000)] + return data + +# Function to search +@profile +def search_function(data): + for i in data: + if i in [100,200,300,400,500]: + print("success") + +def main(): + data=generate() + search_function(data) + print_msg() + +main() diff --git a/Workshop4- Homework/myworld/web_scrapper.py b/Workshop4- Homework/myworld/web_scrapper.py new file mode 100644 index 0000000..fa44338 --- /dev/null +++ b/Workshop4- Homework/myworld/web_scrapper.py @@ -0,0 +1,86 @@ +import psycopg2 +import requests +import re +from bs4 import BeautifulSoup, element +from datetime import datetime + +# For the credentials mentioned below, you may refer the docker-compose.yml present in myworld . +db_name = 'member_db' +db_user = 'postgres' +db_pass = '123456' +db_host = 'psql-db' +db_port = '5432' + +# This will create the connection the to postgres database. +conn = psycopg2.connect(dbname=db_name, user=db_user, password=db_pass, host=db_host, port=db_port) + + +def add_row_to_blog(title, author, date, time): + # This function will add the entry to database + sql = """INSERT INTO members_blog (title, release_date, blog_time, author, created_date) VALUES (%s, %s::DATE, %s::TIME, %s, NOW())""" + + with conn: + with conn.cursor() as curs: + curs.execute(sql, (title, date, time, author)) + + +def truncate_table(): + # This function will delete the existing entries from the database. + with conn: + with conn.cursor() as curs: + curs.execute("TRUNCATE members_blog CASCADE;") + + +def convert_time_format(time_str): + # Convert time string to a valid format recognized by PostgreSQL + time_obj = datetime.strptime(time_str, "%I:%M %p") + return time_obj.strftime("%H:%M:%S") + + +def start_extraction(): + print("Extraction started") + url = "https://blog.python.org/" + + # Each time when we add a new entry, we delete the existing entries. + truncate_table() + data = requests.get(url) + page_soup = BeautifulSoup(data.text, 'html.parser') + + # Getting all the articles + blogs = page_soup.select('div.date-outer') + + for blog in blogs: + # loop through each article + date = blog.select('.date-header span')[0].get_text() + + post = blog.select('.post')[0] + + title = "" + title_bar = post.select('.post-title') + if len(title_bar) > 0: + title = title_bar[0].text + else: + title = post.select('.post-body')[0].contents[0].text + + # getting the author and blog time + post_footer = post.select('.post-footer')[0] + + author = post_footer.select('.post-author span')[0].text + + time = post_footer.select('abbr')[0].text + time = convert_time_format(time) # Convert time format + # Inserting data into the database + add_row_to_blog(title, author, date, time) + + print("\nTitle:", title.strip('\n')) + print("Date:", date) + print("Time:", time) + print("Author:", author) + + print( + "\n---------------------------------------------------------------------------------------------------------------\n") + + +if __name__ == "__main__": + start_extraction() + diff --git a/Workshop4- Homework/test_celery/__pycache__/celery.cpython-310.pyc b/Workshop4- Homework/test_celery/__pycache__/celery.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c744979a70295c8cc7d81ea8e33468de95e2e34 GIT binary patch literal 384 zcmYjLOHRWu6tv?sE&U<5MTDruXH_9ose3jEA!TEwv1vo>JYzdZ?HxD>SMrt>5+^`H z!bvtA$@6CXp2rVnvoQ*o7w6(9)UVbYBMD{|j$H)eh+~Nq&M13 z_%UNIjcbfx%tT>BpY;D5(i)O${fW#Z=#GAubO%aMZD1?v(t)8*b-9MdIQ9&tvOCb1 kxAbTW+Q%*Q-jD7S@J5Pz9OCRe&=gH^97Q<7F&_W@1N)qA)c^nh literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/test_celery/__pycache__/run_tasks.cpython-310.pyc b/Workshop4- Homework/test_celery/__pycache__/run_tasks.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f8c508df83502b8bf719cc6f1e1d1864e1be49b GIT binary patch literal 417 zcmZ`!Jx{|h5VhU7O{;z&1bf#GkOdaRm&DEj2&sz|;cFY}*pclF>B=8zM*fmlru+gV z#K0viES&V7{Lc5D?#yH|B3Q?(L-?kIe6-?kMJR3&P9sSosUkUDQc5I~J;jy`dNSHF zdk%CT;Xkk0l0#qif$s-3d1I8I8UTOg-J9)W8Q19le@6BmNQ=d=!Hvj*hOshw?Xw(2 zDrJK`avx$L@-)*zGz|4__L#cue3j|UZ9v}4cayGR!IjEi%$xSg#V~M>W6rjg5VeVI zj!rRI1TI0PRp|eE0xxW)ec%>SSq1JCK=DrO46Pk~T_qcnLsD3?2Az3hlP8_snbLak zZ0y!;OmT9ScyM04fC5`3w$!3q;Iybhe3=_rD!6WsbVo>I64RKC=@cUrN4mF&B*UG^t(UetCM0>HZWuQn^{!Y-sp zxDT}{YUcxN^r0=K)Cu$S#naUXF?g4+n{=TnnQEivvM!u5>0@0CRbyQKq|DMTl)k)9 zowP2W%2JwDiUZhzUilb_5jr0Wfuq<6OvKtOq7gMQ1j&(a=lQI0jgfh7aC_f902};b m8a#<vq!s literal 0 HcmV?d00001 diff --git a/Workshop4- Homework/test_celery/celery.py b/Workshop4- Homework/test_celery/celery.py new file mode 100644 index 0000000..f21799c --- /dev/null +++ b/Workshop4- Homework/test_celery/celery.py @@ -0,0 +1,7 @@ +from __future__ import absolute_import +from celery import Celery + +app = Celery('test_celery', + broker='amqp://jimmy:jimmy123@localhost/jimmy_vhost', + backend='rpc://', + include=['test_celery.tasks']) diff --git a/Workshop4- Homework/test_celery/run_tasks.py b/Workshop4- Homework/test_celery/run_tasks.py new file mode 100644 index 0000000..24a1442 --- /dev/null +++ b/Workshop4- Homework/test_celery/run_tasks.py @@ -0,0 +1,13 @@ +from .tasks import longtime_add +import time + +if __name__ == '__main__': + result = longtime_add.delay(1,2) + # at this time, our task is not finished, so it will return False + print ('Task finished? ', result.ready()) + print ('Task result: ', result.result) + # sleep 10 seconds to ensure the task has been finished + time.sleep(10) + # now the task should be finished and ready method will return True + print ('Task finished? ', result.ready()) + print ('Task result: ', result.result) diff --git a/Workshop4- Homework/test_celery/tasks.py b/Workshop4- Homework/test_celery/tasks.py new file mode 100644 index 0000000..88f2f1e --- /dev/null +++ b/Workshop4- Homework/test_celery/tasks.py @@ -0,0 +1,11 @@ +from __future__ import absolute_import +from test_celery.celery import app +import time + +@app.task +def longtime_add(x, y): + print ('long time task begins') + # sleep 5 seconds + time.sleep(5) + print ('long time task finished') + return x + y