2022年4月6日 星期三

Udemy - 100 Days of Code - The Complete Python Pro Bootcamp for 2021 - Intermediate+ - 2

 

Day 45~ Day 65

Introduction

課程接下來開始都圍繞在網頁爬蟲及開發的部分,如Requests, BeautifulSoup, Flask 以及SQLAlchemy…等

網址 :https://www.udemy.com/course/100-days-of-code/
程式碼:https://github.com/deathpc/python_100day/


Day 45

搭配前一個月的內容,這週開始介紹如何利用BeautifulSoup 這個套件來做網頁內容的擷取,常見起手式如下:
import requests
from bs4 import BeautifulSoup
response = requests.get("html")
soup = BeautifulSoup(response.text, "html.parser")
  • 挑選元素
    • find(), find_all()
      利用Tag的名稱及屬性去搜尋元素
    • select_one(), select()
      利用CSS選擇器搜尋元素

    • 例如搜尋所有 Class 為 card-title 的 H4 標籤
      soup.find_all('h4', 'card-title')
      soup.find_all('h4', {'class': 'card-title'})
      soup.find_all('h4', class_='card-title')
      soup.select('h4.card-title')
  • 取得元素內容
    • getText()
      取得標籤的文字
    • get("attribute_name")
      取得標籤的屬性值

Day 46-47

利用剛學到的bs去擷取某日 billboard 的 Top100 歌曲,再送到Spotify API 產生撥放清單以及在購物網站上擷取商品價格,但課程並沒有介紹 Spotify API 的使用方式,建議Google 一下它的認證機制怎麼做的,才不會卡住。


Day 48

介紹Selenium,一個自動化測試網站的模組,基本上BS能做的事Se都可以做,等於是軟體模擬使用者操作跟網站元素互動,因此一些互動渲染的部分也可以抓取到內容,以下為固定起手式
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.ui import WebDriverWait
driver_service = Service("chromedriver-97.exe")
driver_options = webdriver.ChromeOptions()
driver = webdriver.Chrome(service=driver_service, options=driver_options)
driver.get("url")


Day 49-50

這兩週要利用Selenium爬取LinkedIn跟Tinder,不過對這兩個網站沒什麼興趣,看完介紹沒問題就跳過了

Day 51-52

這兩週的課題是符合條件時自動發推特跟大量追蹤IG帳號,跟前兩週相比處理等待網頁載入時間這件事變得較為重要,除了單純的time.sleep之外,可透過expected_condition與WebDriverWait 兩個 sub-module 輔助,降低網頁載入受網速影響的問題。
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.ui import WebDriverWait
ec.invisibility_of_element_located((By.CSS_SELECTOR, "blabla"))(driver)
WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.CSS_SELECTOR, "blabla")))


Day 53

這週的內容是利用BS爬取符合條件的房價,並使用SE自動填入 Google 表單,完成後爬蟲的部分到這週就告一段落了

Day 54-55

這週開始介紹Python的網頁框架 - Flask,以及 Python 獨有的裝飾器語法
  • 在網址路由中傳遞變數
    # For security
    from markupsafe import escape

    @app.route('/user/<username>')
    def show_user_profile(username):
    return 'User %s' % escape(username)

    @app.route('/post/<int:post_id>')
    def show_post(post_id):
    return 'Post %d' % post_id
    • 可用的變數類型
      • string
      • int
      • float
      • path:跟 string 的差異在允許斜線作為輸入
      • uuid
  • Decorator
    decorator 可以讓程式碼更精簡,避免掉重複的程式碼,如以下區塊,上下兩段程式的作用是等價的
    def decorated():
    print("this function is decorated")

    def decorator(function):
    print('We will call "{}"'.format(function.__name__))
    return function

    decorated = decorator(decorated)
    decorated()

    --------------------------------------------------------------
    def decorator(function):
    print('We will call "{}"'.format(function.__name__))
    return function

    @decorator
    def decorated():
    print("this function is decorated")

    this_is_decorated()

Decorator 也可以透過 *args 及 **kwargs 傳遞被裝飾函式的 arguments,亦可傳遞參數給裝飾器本身,且裝飾器芝兼具有可堆疊的性質,詳細可參考以下區塊

def decorator(dec_arg):
def wrapper(func):
def internal_wrapper(*args):
print(f"Calling {func.__name__}, I'm decorator with {dec_arg}")
func(*args)
return internal_wrapper
return wrapper

@decorator('dec1')
def func1(*args):
print(f"Call from decorated1 with {args}")

@decorator('dec2')
@decorator('dec3')
def func2(*args):
print(f"Call from decorated2 with {args}")

func1('123', '321')
func2('456', '654')

Day 56

在Flask中載入網頁模板及靜態文件必須遵從框架的指示,將檔案放在 template 及 static 目錄,並輔以相應的函數:
  • render_template
    temp
    @app.route('/')
    def hello_world():
    return render_template("index.html")

  • load static file
    temp
    <link rel="stylesheet" href="static/styles.css">

  • Chrome hard fresh
    Chrome 會 cache 靜態文件,當更改文件後需要強制重新載入時,可按Shift+F5。

Day 57

Jinja 是 一種 Python 的模板語言,透過 Jinja 我們可以在 template 檔案中渲染 Python 傳遞過來的變數,也可以利用模板繼承的概念大幅簡化 html5 的撰寫

  • 傳遞參數或單行物件:
    • .py
      在 Route 的函式中回傳經過 render_template 渲染的 html,參數需以關鍵字參數傳入
      @app.route('/guess/<string:name>')
      def hello_world(name):
      gender = "male"
      age = 13
      return render_template("index1.html", name=name, gender=gender, age=age)
    • .html
      在HTML中使用{{}}包住 Python 語法,告知Jinja如何渲染
      <h1>Hey {{name.upper()}}</h1>
      <p>I think you are {{gender}},</p><br>
      <p>And maybe {{age}} years old</p><br>
  • 嵌入 Python 語法
    • If statement
      {% if True %}
      blabla
      {% endif %}
    • For loop
      {% for item in seq %}
      <li>{{ item }}</li>
      {% endfor %}
    • Comment
      {% raw %}
      <ul>
      {% for item in seq %}
      <li>{{ item }}</li>
      {% endfor %}
      </ul>
      {% endraw %}

  • 模板繼承:
    • base.html
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>{% block title %}{% endblock %}</title>
      </head>
      <body>
      {% block content %}{% endblock %}
      </body>
      </html>
    • child.html
      {% extends "base.html" %}

      {% block title %}
      Welocome
      {% endblock %}
      {% block content %}
      <div class="jumbotron">
      <div class="container">
      <h1>Welcome</h1>
      <p>Are you ready to discover my secret?</p>
      <a href="#"><button class="btn btn-primary btn-lg">Login</button></a>
      </div>
      </div>
      {% endblock %}

  • 網頁跳轉:
    • from_html
      使用 url_for 函式,輸入導向頁面的 Route Function 名稱與其他參數
      <a href={{url_for('post_page', post_id=i.id)}}>Read</a>
    • .py
      @app.route('/post/<int:post_id>')
      def post_page(post_id):
      post_item = [i for i in post_list if i.id == post_id][0]
      return render_template("post.html", post=post_item)


Day 58

Bootstrap
Bootstrap 是一個由 HTML、CSS 和 JavaScript 寫成的前端框架,可以讓你的網站排版自動適應螢幕大小,開法者只需要撰寫基本的 HTML 架構並加上 Bootstrap class 即可快速套用想要的格式設定。

  • CSS 與 JS 檔案載入
    <link rel="stylesheet" href="bootstrap-5.1.3-dist/bootstrap-5.1.3-dist/css/bootstrap.css">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" 後略
  • Grid 佈局 
    <div class="row">
    <div class=col-lg-6> #每列共劃分為12格,lg-6代表在電腦的尺寸上以6格顯示此標籤的內容
    </div>
    <div class=col-lg-6>
    </div>
    </div>
  • 常用組件
    • 導覽列
    • 按鈕
    • 輪播展示窗
    • 卡片組
    • ...

Day 59-62

修改現成的 Bootstrap 網頁範本,結合 Flask 建構一個簡易的 Blog 網站,簡而言之就是將之前 Day 56-58 學的東西結合在一起

  • Flask WTForm and Bootstrap
    利用這兩個套件,在.Py檔案中的路由函式傳入事先設定好的表單類別,在.html檔案中引用渲染表單的 marco ,即可快速在頁面上呈現表單。
    • .py
      from flask import Flask, render_template, request, redirect, url_for
      from flask_wtf import FlaskForm
      from wtforms import EmailField, PasswordField, SubmitField
      from wtforms.validators import DataRequired, Email, Length
      from flask_bootstrap import Bootstrap5


      class MyForm(FlaskForm):
      email = EmailField('User Email', validators=[DataRequired(), Email()])
      password = PasswordField('User password', validators=[DataRequired(), Length(min=9)])
      ok = SubmitField('submit-button')

      app = Flask(__name__)
      bootstrap = Bootstrap5(app)
      app.secret_key = "hello?"


      @app.route("/")
      def home():
      return render_template('index.html')


      @app.route("/login", methods=["GET", "POST"])
      def logina():
      form = MyForm()
      # 可替代驗證 request.method POST 的部份
      if form.validate_on_submit():
      print(form.email.data)
      print(form.password.data)
      if form.password.data =='zxczxczxc':
      return render_template('success.html')
      else:
      return render_template('denied.html')
      return render_template('login.html', form=form)

    • .html
      {% from 'bootstrap5/form.html' import render_form %}

      {% extends "bs5-base.html" %}

      {% block title %}
      Login
      {% endblock %}

      {% block content %}
      <div class="container">
      <h1>Login</h1>
      {{ render_form(form) }}
      </div>
      {% endblock %}


Day 63

SQLALchemy 是 Python 中的一款 ORM 框架,讓開發者可使用Python 的語法對資料庫進行操作,不需要直接寫 SQL 語法,可讀性較高,也可以防止 SQL injection,但因為多了一層 python 的包裝會犧牲掉部分的效能

  • Initialize DB and  table
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'blabla'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///book.db'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SQLALCHEMY_ECHO'] = True
    db = SQLAlchemy(app)

    class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(250), unique=True, nullable=False)
    author = db.Column(db.String(250), nullable=False)
    rating = db.Column(db.Float, nullable=False

    db.create_all()

  • Create new record
    new_book = Book(id=1, title="Harry Potter", author="J. K. Rowling", rating=9.3)
    db.session.add(new_book)
    db.session.commit()

  • Read record
    all_books = session.query(Book).all()
    book = Book.query.filter_by(title="Harry Potter").first()

  • Update record
    book_to_update = Book.query.filter_by(title="Harry Potter").first()
    book_to_update.title = "Harry Potter and the Chamber of Secrets"
    db.session.commit()

  • Delete record
    book_id = 1
    book_to_delete = Book.query.get(book_id)
    db.session.delete(book_to_delete)
    db.session.commit()

Day 65

  • Web Design
    • Colour Theory
      • 互補(對比)色:可用在Logo標誌或是想凸顯的事物上,但盡量避免大範圍使用或是用在跟文字有關的元素上
      • 近似色:常用在導航欄或是某元素及其背景色的搭配,創造出一種和諧、舒適的設計感
      • 三等份:在色環上間隔120度取色,以其中一種顏色當作主色調,另兩種顏色作為重點的標註
    • Typography
      • Serif:傳統、穩定
      • San-serif:簡單、直接、可讀性
      • 在一種設計中盡量只用兩種字型
      • 不要使用以下字型:Comic Sans, Kristen, Papyrus, Viner, curlz
    • User interfacer Design
      • Hierarchy
        用顏色與大小建立層次感
      • Layout
        文字的長度最好在40~60字元之間,太長的文字不利使用者閱讀,太短則會有很重的中斷感
      • Alignment
        盡量讓元素間的對齊點減少,呈現一致
      • White space
        在元素的四周適當地保留一些空間,簡約的設計也能提升質感(如蘋果)
      • Audience
    • User experience Design
      • Simplicity
        避免同時呈現太多不必要的的元素
      • Consistency
        不同頁面的功能呈現需一致 
      • Reading Patterns
        參考 F or Z-pattern 的閱讀模式擺放元素 
      • All Platform Design
        設計符合各式尺寸的呈現 

沒有留言:

張貼留言