Skip to content

sueshow/Python_Crawl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 

Repository files navigation

Crawl

環境及套件版本

  • Python 3.6.6
  • pip 10.0.0:為Python內建的套件管理
  • jupyter notebook 4.4.0

剖析網頁原始內容

  • 常見剖析 HTML 原始碼的方式有三種
    • 正則表示式(Regular Expression):容易被網站的小改動影響
    • 當成 HTML 處理
      • Beautiful Soup(簡稱 bs4)是最常看到用來操作 HTML 的套件
        • html.parser 來剖析 HTML
        • 搜尋方法
          • . 直接取到節點
          • 字串:指定要搜尋的標籤名稱
            # 搜尋標籤 "b"
            soup.find_all('b')
            # [<b>The Dormouse's story</b>]
            
          • 正規表示式:利用 Python re 物件的 search() 方法來搜尋符合的標籤名稱
            # 搜尋以 "b" 開頭的標籤
            import re
            for tag in soup.find_all(re.compile("^b")):
                print(tag.name)
            # body
            # b
            
          • 清單:指定多個要搜尋的標籤名稱
            • 指令:find_all(name, attrs, recursive, string, limit, **kwargs)
              • 範例
                # 搜尋標籤 "a" 和 "b"
                soup.find_all(["a", "b"])
                
              • 參數說明
                • name:帶入前面介紹的「過濾器」
                • attrs:傳入 dict 物件,用屬性來過濾
                • recursive:使用布林值(預設是 True),用來設定是否要遞迴往下找
                • string:帶入「過濾器」,用標籤的文字內容來過濾
                • limit:指定要回傳幾個結果
                • keyword arguments:跟 attrs 參數一樣是用屬性來過濾,絕大多數的情況下用 kwargs 就可以,只有一些特殊狀況(保留字、屬性名稱與方法參數名稱相同、kebab-case)會需要用 attrs 參數來處理
          • 方法:定義一個會回傳布林的方法物件來判斷是否要傳回標籤
            # 判斷標籤是否定義 class 屬性且無定義 id 屬性
            tag.has_attr('class') and not tag.has_attr('id')
            
        • 支援 lxmlhtml5lib
          • 一般建議使用比較快的 lxml,使用 XPath 定位資料
          • 安裝套件
            pip install lxml
            
          • 方法:用 lxml 的 etree.HTML() 方法載入 HTML 原始資料後,可以用 .xpath() 方法來執行 XPath 查詢
          • XPath 常用語法
            • 選擇節點
              語法 說明 語法 說明
              node-name 選擇名稱等於 node-name 的節點 / 選擇直屬於當前節點的所有節點(子節點)
              // 選擇當前節點下所有節點(子孫節點) . 選擇當前節點
              .. 選擇上一層節點(父節點) @ 選擇屬性
            • 範例說明:HTML 原始內容
              • 基本
                • /html:取得 html 標籤(以 / 開頭代表從根節點開始找)
                • /html/body/a:取得 body 下所有 a 標籤
                • //a:取得所有 a 標籤
                • /html/body//a:取得 body 下所有 a 標籤
                • //a/@href:取得所有 a 標籤的 href 屬性
              • 進階判斷式(predicates)
                • /html/body//a[1]:取得 body 下第一個 a 標籤
                • /html/body//a[last() - 1]:取得 body 下最後一個 a 標籤
                • /html/body//a[position() < 3]:取得 body 下前兩個 a 標籤
                • //p[@class]:取得有定義 class 屬性的 p 標籤
                • //p[@class='title']:取得 class 屬性值為 title 的 p 標籤
              • 選取任意節點:
                • *:任意標籤
                • @*:任意屬性
                • :一次查詢多組路徑
                • 範例
                  • /html/body/*:取得 body 標籤的全部子節點
                  • /html/body//*:取得 body 下全部標籤
                  • //p[@*]:取得至少有定義一個屬性的 p 標籤
                  • //p | //a:一次取得全部 p 標籤和 a 標籤
      • 載入 HTML 字串
        • prettify():回傳剖析器處理完後格式化的字串
        • 注意同樣的原始碼在不同剖析器可能會有不同的結果
    • 當成 XML 處理

爬蟲

  • 說明:可「自動」瀏覽全球資訊網的網路機器人,許多的搜尋入口網站(如 Google),都會透過網路爬蟲收集網路上的各種資訊,進一步分析後成為使用者搜尋的資料,許多開發者也會自行開發不同的爬蟲程式,進行大數據收集與分析
  • 類型
    • 靜態爬蟲:網站完成一個請求(request)與回應(response) 後,用戶端即不再與伺服器有任何的交流,所有的互動都只與瀏覽器的網頁互動,資訊不會傳遞到後端伺服器
    • 動態爬蟲:網站會依照使用者的行為不斷的與伺服器進行交流,必須要知道網站需要什麼「資訊」,提供正確的資訊,才能取得所需要的資料
  • 使用爬蟲的禮儀
    • 不造成網站伺服器的負擔:每次爬取資料時,設定適當的等待延遲
    • 確認網站是否有提供 API:節省讀取與分析網站 HTML 的時間
    • 注意 robots.txt:規範一個網站允許什麼樣的 User-Agent 訪問,也會規範 Crawl-delay 訪問間隔時間,如果 Crawl-delay 設定 1,表示這個網站期望每次訪問的時間間隔一秒鐘
  • 反爬蟲機制
    機制 說明 作法 破解難度
    判斷瀏覽器 headers 資訊 利用 headers 判斷來源是否合法,headers 通常會由瀏覽器自動產生,直接透過程式所發出的請求預設沒有 headers 只要能透過爬蟲程式,送出模擬瀏覽器的 headers 資訊,就能進行破解
    清空 window.navigator 有些反爬蟲的網頁,會檢測瀏覽器的 window.navigator 是否包含 webdriver 屬性,在正常使用瀏覽器的情況下,webdriver 屬性是 undefined,一旦使用了 selenium 函式庫,這個屬性就被初始化為 true 程式使用 selenium webdriver 的 execute_cdp_cmd 的方法,將 webdriver 設定為 undefined (詳如 selenium 說明)
    使用動態頁面 將網頁內容全部由動態產生,大幅增加爬蟲處理網頁結構的複雜度 只要確認動態頁面的架構,就能進行破解,如果打開的網頁是動態頁面,「檢視網頁原始碼」時看到的結構往往會很簡單,通常都只會是一些簡單的 HTML、CSS 和壓縮過的 js 文件 中低
    加入使用者行為判斷 在網頁的某些元素,加入使用者行為的判斷,例如滑鼠移動順序、滑鼠是否接觸...等,增加爬蟲處理的難度 確認頁面加入的使用者行為,就能模擬並進行破解,
    如:有些網頁會在按鈕加上「滑鼠碰觸」的保護,如果不是真的用滑鼠碰觸,只是用程式撰寫「點擊」指令,就會被當作爬蟲而被阻擋,模故擬出先碰觸元素,再進行點擊的動作,藉此突破這個反爬蟲的機制(詳如模擬點擊說明)
    如:有些網頁也會判斷使用者刷新網頁的時間(通常使用者不會在極短的時間內連續刷新),這時也可以使用 time 函式庫的 sleep 方法讓網頁有所等待,避開這個檢查機制
    提交使用者授權 在使用者登入時,會將使用者的授權(token)加入瀏覽器的 Cookie 當中,藉由判斷 Cookie 確認使用者是否合法 只要知道 request 與 response 的機制後,取得 Cookie 內的 token 就能破解
    破解驗證碼 相當常見的驗證機制,可相當程度的防堵惡意的干擾與攻擊,對於非人類操作與大量頻繁操作都有不錯的防範機制(如防堵高鐵搶票、演唱會搶票...等) 必須搭配一些 AI 來處理圖形、數字、文字的識別,通常只要能識別驗證碼就能破解,要破解一般驗證碼,需要先將網頁上的驗證碼圖片下載,再將圖片提交到 2Captcha 服務來幫我們進行辨識
    破解代理伺服器與第三方 IP 封鎖 針對惡意攻擊的 IP 進行封鎖 通常必須更換 IP 或更換代理伺服器才能破解,許多網站上也有提供免費的 Proxy IP,以 Free Proxy List 網站為例,就能取得許多免費的 Proxy IP

工具介紹

  • 搭配使用工具
    • Webdriver
      • WebDriver 是用來執行並操作瀏覽器的 API 介面,每一個瀏覽器都會有各自對應的驅動程式(driver),Selenium 會透過 WebDriver 來直接對瀏覽器進行操作,將所支援的瀏覽器進行自動化作業,就如同真的使用者在操作
      • 不同瀏覽器會有不同的 driver,如ChromeEdgeFirefoxSafari,需下載目前瀏覽器版本的 Webdriver
        • 下載版本查詢
        • Chromedriver:其他瀏覽器類似
          # 載入需要的套件
          from selenium import webdriver
          
          # 開啟瀏覽器視窗(Chrome)
          # 方法一:執行前需開啟 chromedriver.exe 且與執行檔在同一個工作目錄
          driver = webdriver.Chrome('./chromedriver')    # 指向 chromedriver 的位置
          # 方法二:或是直接指定 exe 檔案路徑
          driver = webdriver.Chrome('桌面\chromedriver')
          
          # get():輸入網址,即可前往特定網頁
          driver.get('https://www.google.com') # 更改網址以前往不同網頁
          # close():可關閉目前網頁視窗
          driver.close() # 關閉瀏覽器視窗
          
    • 額外工具
    • 網頁檢視器:網頁中看得到的內容一定抓得下來
      • Windows:請按 f12、ctrl+shift+i
      • macOS:請按 option+command+c
  • 套件
    • Selenium
      • 介紹:可模擬出使用者在瀏覽器的所有操作行為(點擊按鈕、輸入帳號密碼、捲動捲軸...等),因此除了爬蟲的應用,也常作為「自動化測試」使用的工具
      • 優點:可模擬使用者的動作,進行登入後爬取資料或滾動卷軸,並且能夠執行 JavaScript 程式碼
      • 指令
        from selenium import webdriver
        # 請求頭信息偽裝為瀏覽器,可以更好地請求數據信息
        user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15'
        opt = webdriver.ChromeOptions()
        # 加入 headers 資訊
        opt.add_argument('--user-agent=%s' % user_agent)
        driver = webdriver.Chrome('./chromedriver', options=opt)
        # 清空 window.navigator
        driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
            "source": """
              Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
              })
            """
        })
        driver.get('要爬的網址')
        
      • 使用規則
        • 取得網頁元素:兩種函數找出 WebElement
          • find_element:抓取符合條件的第一個項目,可搭配 By 方法
          • find_elements:抓取所有符合條件的項目,並回傳成 list
        • 八種方法
          • ID = id
          • CLASS_NAME = class_name
            • 透過標籤的 class 屬性搜尋
            • 字串內有空格的話要改為「.」
          • NAME = name
          • LINK_TEXT = link_text
            • 透過連結標籤的文字搜尋
          • PARTIAL_LINK_TEXT = partial_link_text
          • TAG_NAME = tag_name
            • 使用 TAG 選擇器特別要注意的是,HTML 標籤時常重複,因此 TAG 選擇器通常適用於抓取大框架的網頁元素再做細部搜尋
          • XPATH = xpath
            • 用於在 XML 文檔中定位節點的語言(想像網頁是圖書館,而各個網頁元素是書籍,XPath 就有點類似於目錄編號,可以直接查找)
            • 原因:當想要查找的元素沒有合適的 id 或 name 屬性時,可以使用 XPath 以絕對路徑(不建議使用)定位元素,也可以利用已知特殊 id 或 name 屬性的元素的相對路徑定位
            • XPath 包含來自 HTML 所有元素的位置(絕對路徑),因此,僅對網頁進行一點點調整就可能導致失敗(超級容易失敗,要不斷維護)
            • 步驟
              • 打開網頁檢視器,找到目標網頁元素的內容
              • 在內容上點擊右鍵 → Copy→Copy (full) XPath,獲取絕對或相對 XPath
              • 將複製下來的 XPath 貼上
            • 範例:
          • CSS_SELECTOR = css_selector
            • 重要
              • 「/」改寫成「>」
              • 「//」改寫成「 (空格)」
              • 用 id 查找「#」
              • 用 classname 查找「.」
            • 參考網頁:CSS Selectors
        • 取得標籤的資訊
          • 取得標籤的內部文字
            element = driver.find_element(搜尋欄位, '搜尋條件')
            element.text
            
          • 取得標籤的某個屬性
            element = driver.find_element(搜尋欄位, '搜尋條件')
            element.get_attribute('屬性名稱')
            
          • 模擬使用者點擊標籤
            element = driver.find_element(搜尋欄位, '搜尋條件')
            element.click()
            
        • 操作網頁元素
          • 方法
            方法 ActionChains 參數 說明 方法 ActionChains 參數 說明
            click() element 按下滑鼠左鍵 click_and_hold() element 滑鼠左鍵按著不放
            double_click() element 連續按兩下滑鼠左鍵 context_click() element 按下滑鼠右鍵 (需搭配指定元素定位)
            drag_and_drop() source, target 點擊 source 元素後,移動到 target 元素放開 drag_and_drop_by_offset() source, x, y 點擊 source 元素後,移動到指定的座標位置放開
            release() element 放開滑鼠 move_by_offset() x, y 移動滑鼠座標到指定位置
            move_to_element() element 移動滑鼠到某個元素上 move_to_element_with_offset() element, x, y 移動滑鼠到某個元素的相對座標位置
            send_keys() values 送出某個鍵盤按鍵值 send_keys_to_element() element, values 向某個元素發送鍵盤按鍵值
            key_down() value 按著鍵盤某個鍵 key_up() value 放開鍵盤某個鍵
            reset_actions() 清除儲存的動作 (實測沒有作用,查訊後是 Bug) pause() seconds 暫停動作
            perform() 執行儲存的動作
          • 要使用這些方法的方式有兩種
            • 第一種「針對指定元素呼叫方法」:只要針對指定的元素,呼叫指定的方法,就會執行對應的動作,只能使用 click、send_keys等
              from selenium import webdriver
              from time import sleep
              
              driver = webdriver.Chrome('./chromedriver')
              driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')
              a = driver.find_element_by_id('a')
              add = driver.find_element_by_id('add')
              a.click()     # 點擊按鈕 A,出現 a 文字
              sleep(1)
              add.click()   # 點擊 add 按鈕,出現 數字 1
              add.click()   # 點擊 add 按鈕,出現 數字 2
              sleep(1)
              add.click()   # 點擊 add 按鈕,出現 數字 3
              sleep(1)
              add.click()   # 點擊 add 按鈕,出現 數字 4
              
            • 第二種「使用ActionChains」:將所有需要執行的方法串成「鏈」,全部完成後執行 perform() 執行所有的過程
              from selenium import webdriver
              from selenium.webdriver.common.action_chains import ActionChains
              
              driver = webdriver.Chrome('./chromedriver')
              driver.get('https://example.oxxostudio.tw/python/selenium/demo.html')
              a = driver.find_element_by_id('a')
              add = driver.find_element_by_id('add')
              actions = ActionChains(driver)                                        # 使用 ActionChains 的方式
              actions.click(a).pause(1)                                             # 點擊按鈕 A,出現 a 文字後,暫停一秒
              actions.double_click(add).pause(1).click(add).pause(1).click(add)     # 連點 add 按鈕,等待一秒後再次點擊,等待一秒後再次點擊
              actions.perform()  # 執行儲存的動作
              
          • 取得網頁元素的內容
            • text:元素的內容文字
            • get_attribute:元素的某個 HTML 屬性值
            • id:元素的 id
            • tag_name:元素的 tag 名稱
            • size:元素的長寬尺寸
            • screenshot:將某個元素截圖並儲存為 png
            • is_displayed():元素是否顯示在網頁上
            • is_enabled():元素是否可用
            • is_selected():元素是否被選取
            • parent:元素的父元素。
    • Requests
      • 介紹:對網路發動請求的套件,可實作對網頁做 get、post 等 HTTP 協定的行為,請求網站獲取網頁數據
      • 指令
        import requests
        url = '要爬的網址'
        res = requests.get(url)
        # 返回 200:請求成功
        
        # 請求頭信息偽裝為瀏覽器,可以更好地請求數據信息
        headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'}
        res = requests.get(url, headers=headers)
        res.encoding = 'utf8'
        print(res.text)
        
      • 類型
        HTTP 方法 requests 方法 說明 備註
        GET requests.get(url) 向指定資源提交請求,可額外設定 params 參數字典 就像明信片,需要撰寫目的地的地址及內容,其中的地址就像是請求的網址,而內容就像是接在網址後面的參數(querystring),提交的參數會放在標頭中傳送(公開)
        POST requests.post(url) 向指定資源提交請求,可額外設定 data 參數字典 就像一般的信件,需撰寫目的地的地址,而信件內容會在信封中,提交的參數會放在內容中傳送(隱密)
        PUT requests.put(url) 向指定資源提供最新內容,可額外設定 data 參數字典
        DELETE requests.delete(url) 請求刪除指定的資源
        HEAD requests.head(url) 請求提供資源的回應標頭(不含內容)
        OPTIONS requests.options(url) 請求伺服器提供資源可用的功能選項
      • Response 物件的屬性與方法
        • 說明:當伺服器收到 requests HTTP 方法所發出的請求後,會傳回一個 Response 物件,物件裡包含伺服器回應的訊息資訊,可以透過下列的屬性與方法,查詢相關內容(bytes 表示資料以 bytes 表示,str 以字串表示,dict 以字典表示)
          Response 物件 說明 Response 物件 說明
          url 資源的 URL 位址 content 回應訊息的內容(bytes)
          text 回應訊息的內容字串(str) raw 原始回應訊息串流(bytes)
          status_code 回應的狀態(int) encoding 回應訊息的編碼
          headers 回應訊息的標頭(dict) cookies 回應訊息的 cookies(dict)
          history 請求歷史(list) json() 將回應訊息進行 JSON 解碼後回傳(dict)
          rasise_for_status() 檢查是否有例外發生,如果有就拋出例外
      • 傳遞參數
        • headers
          • 用途:讓瀏覽器向伺服器表明自己的身分,有些 HTTP 伺服器僅允許來自普通瀏覽器的請求,而不接受來自程式腳本的請求
          • 經常用於「偽裝」User-Agent
          • Mozilla Firefox 的 header 的值為 'Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11'
          • urllib 的 header 的值為 'Python-urllib/2.6'
          • 執行方式:Mozilla、AppleWebKit、Chrome,解析網頁:用 text/html 的方式,以 UTF-8 的格式去做解析
            headers = {
               'content-type': 'text/html; charset=UTF-8',
               'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
            }
            
        • cookies:設定 Request 中的 cookie(dict)
        • auth:支持 HTTP 認證功能(tuple)
        • json: JSON 格式的數據,作為 Request 的內容
        • files:傳輸文件(dict)
        • timeout:設定超時時間,以「秒」為單位
        • proxies:設定訪問代理伺服器,可以增加認證(dict)
        • allow_redirects:True/False,預設 True,意即重新定向
        • stream:True/False,預設 True,意即獲取內容立即下載
        • verify:True/False,預設 True,意即認證 SSL
        • cert:本機 SSL 路徑
    • BeautifulSoup
      • 介紹
        • 借助網頁的結構特性來解析網頁的工具
        • 分析網頁的 HTML 與 XML 文件,並將分析的結果轉換成「網頁標籤樹」(tag) 的型態,讓資料讀取方式更接近網頁的操作語法,處理起來也更為便利
        • 通常會搭配 requests 爬取網頁內容一併使用
      • 指令
        import requests
        from bs4 import BeautifulSoup
        
        url = 'https://water.taiwanstat.com/'
        web = requests.get(url)                        # 取得網頁內容
        soup = BeautifulSoup(web.text, 'html.parser')  # 轉換成標籤樹
        
        title = soup.title                             # 取得 title
        
        print(soup.find_all('a'))                      # 等同於下方的 soup('a')
        print(soup('a'))                               # 等同於上方的 find_all('a')
        infos = soup.select('路徑')                     # 路徑提取方式:在固定位置右鍵->copy->copy selector
        
      • 說明
        • 網頁是由「標籤」的語法所構成,標籤 (tag) 指的是由「<」和「>」包覆的代碼
        • 解析器:html5lib 的容錯率比 html.parser 高,但解析速度比較慢
          • Python 本身內建「html.parser」的解析器
          • 另外安裝「html5lib」解析器不需要 import,安裝後就可以使用
            pip install html5lib
            
      • Beautiful Soup 的方法
        方法 說明 方法 說明
        select() 以 CSS 選擇器的方式尋找指定的 tag
        find_all()、find() 以所在的 tag 位置,尋找內容裡所有的 tag 或第一個指定的 tag find_parents()、find_parent() 以所在的 tag 位置,尋找父層所有指定的 tag 或第一個找到的 tag
        find_next_siblings()、find_next_sibling() 以所在的 tag 位置,尋找同一層後方所有指定的 tag 或第一個找到的 tag find_previous_siblings()、find_previous_sibling() 以所在的 tag 位置,尋找同一層前方所有指定的 tag 或第一個找到的 tag
        find_all_next()、find_next() 以所在的 tag 位置,尋找後方內容裡所有指定的 tag 或第一個找到的 tag find_all_previous()、find_previous() 所在的 tag 位置,尋找前方內容裡所有指定的 tag 或第一個找到的 tag
      • Beautiful Soup 方法的參數
        • string:搜尋 tag 包含的文字
        • limit:搜尋 tag 後只回傳多少個結果
        • recursive:預設 True,會搜尋內容所有層,設定 False 只會搜尋下一層
        • id:搜尋 tag 的 id
        • class_:搜尋 tag class,因為 class 為 Python 保留字,所以後方要加上底線
        • href:搜尋 tag href
        • attrs:搜尋 tag attribute 屬性
      • 取得並輸出內容
        • .get_text():輸出 tag 的內容
        • [屬性]:輸出 tag 裡某個屬性的內容
          url = 'https://www.iana.org/domains/'
          web = requests.get(url)
          soup = BeautifulSoup(web.text, 'html.parser')
          print(soup.find('a').get_text())   # 輸出第一個 a tag 的內容
          print(soup.find('a')['href'])      # 輸出第一個 a tag 的 href 屬性內容
          
    • Lxml
      • 指令:
        From lxml import etree
        Html = etree.HTML(text)
        infos = Html.xpath('路徑')  #路徑提取方式:在固定位置右鍵->copy->copy xpath
        
      • 介紹:Lxml 為 XML 解析庫,可修正 HTML 代碼,形成結構化的 HTML 結構
      • 範例:詳如「爬蟲_股票資料_xpath.ipynb」之 HTML
    • 下載特定網址資料
      • 一般格式
        import urllib.request as req
        
        url = 網址
        with req.urlopen(url) as response:
            data = response.read().decode('utf-8')  # 取得網址的原始碼(HTML、CSS、JS)
        print(data)
        
      • JSON
        import urllib.request as req
        import json
        
        url = 'https://data.taipei/api/v1/dataset/296acfa2-5d93-4706-ad58-e83cc951863c?scope=resourceAquire'
        with req.urlopen(url) as response:
            data = json.load(response)  # 利用 json 模組處理 json 資料格式
        print(data)
        
      • 範例:詳如「爬蟲_簡易說明」之範例四~六

範例

  • requests:
    • 範例一 :【PTT 資訊版】爬取文章標題
      • import Python套件
        import requests   
        from bs4 import BeautifulSoup 
        
      • 將網頁 Get 下來
        r = requests.get('https://www.ptt.cc/bbs/MobileComm/index.html') #將此頁面的HTML GET下來
        print(r.text) #印出HTML
        
      • 將抓下來的資料用 Beautifulsoup4 轉為 HTML 的 parser,想選取的網頁裡的文章標題,故 soup.select 中放的是 div.title a
        soup = BeautifulSoup(r.text, 'html.parser') #將網頁資料以html.parser
        sel = soup.select('div.title a') #取HTML標中的 <div class="title"></div> 中的<a>標籤存入sel
        
      • 最後寫一個迴圈將爬下來的文章標題印出來
        for s in sel:
          print(s['href'], s.text) 
        
      • 範例:詳如「爬蟲_簡易說明.ipynb」之範例一
    • 範例二:【PTT Joke版】爬取多頁資料
      • 觀察下一頁按鈕的HTML標籤內容,發現上一頁按鈕的 a 標籤中有上一頁的網址為「/bbs/joke/index8140.html」
        r = requests.get('https://www.ptt.cc/bbs/joke/index.html')
        soup = BeautifulSoup(r.text, 'html.parser')
        u = soup.select('div.btn-group.btn-group-paging a')#上一頁按鈕的a標籤
        url = 'https://www.ptt.cc'+ u[1]['href'] #組合出上一頁的網址
        
      • 藉由迴圈來重複GET網頁
        url = 'https://www.ptt.cc/bbs/joke/index.html'
        for i in range(3): #往上爬3頁
          r = requests.get(url)
          soup = BeautifulSoup(r.text, 'html.parser')
          sel = soup.select('div.title a') #標題
          u = soup.select('div.btn-group.btn-group-paging a') #a標籤
          print ('本頁的URL為'+url)
          url = 'https://www.ptt.cc' + u[1]['href'] #上一頁的網址
        
        for s in sel: #印出網址跟標題
          print(s['href'], s.text)
        
      • 範例:詳如「爬蟲_簡易說明.ipynb」之範例二
    • 範例三:【PTT 八卦版】遇到按鈕
      • 進入網站後會看到讓使用者點選「是否已滿18歲」按鈕
      • 說明:
        • Cookie:網站存放在瀏覽器的一小段內容
        • 與伺服器互動:連線時,Cookie 放在 Request Headers 中送出
        • 先開啟瀏覽器開發者模式(F12),並點選至network(網路),觀察點選「已滿18歲」後,會送給伺服器之封包內容,意即透過「檢視原始碼」→「Application」→「Cookies」觀察重要的 Cookie
      • 範例:詳如「爬蟲_簡易說明.ipynb」之範例三
      • 參考網頁
  • selenium
    • 範例:模擬點擊
      from selenium import webdriver
      
      driver = webdriver.Chrome()
      driver.get('http://www.google.com') # 更改網址以前往不同網頁
      
      • 情境一:搜尋輸入
        # 定位搜尋框
        element = driver.find_element(by=By.CLASS_NAME, value='gLFyf.gsfi')
        
        # 傳入字串
        element.send_keys('Selenium Python')
        
        # 點擊搜尋按鈕
        button = driver.find_element(by=By.CLASS_NAME, value='gNO89b')
          # 點擊搜尋按鈕
        button.click()
        
          # 反爬蟲:點擊搜尋按鈕
        from selenium.webdriver.common.action_chains import ActionChains
        actions = ActionChains(element)
        actions.move_to_element(button).click(button)   # 滑鼠先移到 button 上,然後再點擊 button
        actions.perform()
        
      • 情境二:刪除輸入
        # 定位搜尋框
        element = driver.find_element(by=By.CLASS_NAME, value='gLFyf.gsfi')
        
        # 傳入字串
        element.send_keys('Selenium Python')
        
        # 刪除原本已輸入的文字
        element.clear()
        
      • 滾動網頁捲軸
        driver.execute_script('window.scrollTo(0, 500)')   # 捲動到 500px 位置
        sleep(1)
        
        h1 = driver.find_element_by_tag_name('h1')
        h3 = driver.find_element_by_tag_name('h3')
        script = '''
          let h1 = arguments[0];
          let h3 = arguments[1];
          alert(h1, h3)
        '''
        driver.execute_script(script, h1, h3)   # 執行 JavaScript,印出元素
        sleep(2)
        Alert(driver).accept()    # 點擊提示視窗的確認按鈕,關閉提示視窗
        
      • 瀏覽網頁的瀏覽紀錄
        # 前往下一項
        driver.forward()
        # 前往上一項
        driver.back()
        

查詢

  • Python 查詢
    • 查詢設定:conda config --show
    • 查詢 proxy
      import urllib
      urllib.request.getproxies()
      
  • 網路狀況
    • Windows
      • 檢視 IP Address
        • 指令:ipconfig
        • 結果:如果 IP Address 顯示為 0.0.0.0 或 169.x.x.x 則無法上網
      • 測試網站是否活著
        • 指令:ping 目的地網站名稱或IP Address
        • 結果:如果出現 Request timed out. 就表示該網站和我們電腦間的網路連線無法建立
      • 追蹤網路路徑
        • 指令:tracert 目的地網站名稱或IP Address
      • 測試網頁服務(HTTP)
        • 指令:
          • telnet 目的地網站名稱或IP Address 80
          • telnet 目的地網站名稱或IP Address 443
    • Linux
      • 測試網站是否活著
        • 指令:ping 目的地網站名稱或IP Address
        • 停止輸出:ctrl+c
      • 追蹤網路路徑
        • 指令:traceroute 目的地網站名稱或IP Address
  • HTTP 狀態代碼
    狀態代碼 說明 狀態代碼 說明 狀態代碼 說明
    200 網頁正常 301 網頁搬家,重新導向到新的網址 400 錯誤的要求
    401 未授權,需要憑證 403 沒有權限 404 找不到網頁
    500 伺服器錯誤 503 伺服器暫時無法處理請求 (附載過大) 504 伺服器沒有回應

查詢網站 TLS 資訊的方法


參考資料

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published