嗨,第八天了!昨天介紹了網頁 HTML 的架構,今天就要來說明如何用 BeautifulSoup 去解析裡面的內容。 BeautifulSoup 在上一年的鐵人賽我有簡單的說明過了。

:: [Day23]Beautiful Soup網頁解析

那今天要說什麼呢?我們就來解析昨天Google搜尋畫面的內容吧!

import requests
from bs4 import BeautifulSoup
r = requests.get('https://www.google.com/search?q=python3')
soup = BeautifulSoup(r.text, 'lxml')
  • 先引入requests, BeautifulSoup https://www.google.com/search?q=python3為我們要請求的網址,這個頁面為我們在Google搜尋python3出來的頁面(可以看昨天的文章)
  • 把回傳內容裡的文字也就是html內容傳入BeautifulSoup
  • 在昨天的文章中,我們關閉了JS,關閉之後會看到這個畫面:

    現在來看看裡面的元素吧,先從標題點右鍵檢查:

    可以看出它在a標籤裡面,但若我們直接抓取所有a標籤,會把葉庫存檔,類似內容等內容也抓到,所以我們往上一層看,會發現a包覆在h3classr的標籤裡面,程式碼:

    a_tags = soup.select('h3.r a')
    for t in a_tags:
        print(t.text)
    

    可以看出我們找到所有的標題了:

    來說明一下select()也就是css 選擇器,若有寫過css就能夠理解怎麼去解析它,.&#的用法就是css在用的寫法。其實select()就跟find_all()是一樣的,只是內容的寫法不同,find_all()在上一年文章已經說明過了,這裡就不贅述了,.select('h3.r a')中的h3為標籤名稱.class屬性,所以.後面接class名稱也就是r#id屬性。

  • 注意:select()所得到的內容為一list,跟find_all()一樣,所以若確定只有一個內容可以用select_one()
  • title = soup.select_one('h3.r a')
    print(title.text)
    

    上面程式碼,只會得到Python 3.0 Release | Python.org

  • 注意:因為只會抓一筆,所以它並不是存在list內,不需要用迴圈去取出全部內容,可以直接使用title.text
  • 這樣有理解兩個的差別了嗎?
    接下來我們來取得href吧!先來看看a_tag這個變數是什麼內容:

    a_tag = soup.select_one('h3.r a')
    print(a_tag)
    # <a href="/url?q=https://www.python.org/download/releases/3.0/&sa=U&ved=0ahUKEwigs7is6PvdAhXB2LwKHSUqCWoQFggTMAA&usg=AOvVaw0PrtXxN9eChI2u0SKQ7wuS">Python 3.0 Release | Python.org</a>
    

    可以看出來它抓到整個a元素的內容,那href要怎麼得到呢?

    print(a_tag['href'])
    # /url?q=https://www.python.org/download/releases/3.0/&sa=U&ved=0ahUKEwjo9qPw6PvdAhVV6bwKHQVBDrAQFggTMAA&usg=AOvVaw1-sMTCID-cyLCuxL9Q4fIU
    

    好的,現在得到了這串不知名的href要做什麼呢?

    a_tag = soup.select_one('h3.r a')
    href = a_tag['href']
    googleUrl = 'https://www.google.com'
    print(googleUrl + href)
    # https://www.google.com/url?q=https://www.python.org/download/releases/3.0/&sa=U&ved=0ahUKEwiBkavx6fvdAhXIvLwKHVstDacQFggTMAA&usg=AOvVaw0qRzzs3ItQQZszDNvtFiet
    

    所得到的內容就是搜尋結果的第一個網頁連結了!不信的話點進去看看?

    最後,我們寫一個小小的範例,抓到href後重新更換url重新requests,並將頁面存到html檔案內:

    r = requests.get('https://www.google.com/search?q=python3')
    soup = BeautifulSoup(r.text, 'lxml')
    googleUrl = 'https://www.google.com'
    a_list = soup.select('h3.r a')
    for a in a_list:
        print('title', a.text)
        print('href', a['href'])
        contentUrl = googleUrl + a['href']
        r = requests.get(contentUrl)
        with open ( a.text + '.html', 'w+') as f:
            f.write(r.text)
            print('saved')
    

    這樣我們就得到每個連結裡的網頁內容了!
    透過這個方式我們可以再分別解析網頁內容!
    因此,明天我們來試試看如何透過requests&BeautifalSoup爬PTT!

  • 是不是很好理解呢?若要知道更多語法的話可以直接看文件:
    Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation

    我文章會再修正一下,感謝你。
    或是header設定像是:headers={'Content-type': 'text/plain; charset=utf-8'}

    關於你提到如果javascript沒有關掉的話,抓到的網頁會是長的如何?的問題,
    應該要這樣解釋:
    我之所以要示範關閉javascript(第7天),
    是因為爬蟲抓到的就是沒有js的內容,除非用工具渲染js(後面文章有提到)不是說因為我們關閉了所以才只會抓到沒有js的內容(有點饒舌)

    你上面網址的內容,我在第7天有說明哦https://ithelp.ithome.com.tw/articles/10204082

    或是`header`設定像是:`headers={'Content-type': 'text/plain; charset=utf-8'}` 關於你提到`如果javascript沒有關掉的話,抓到的網頁會是長的如何?`的問題, 應該要這樣解釋: 我之所以要示範關閉`javascript`(第7天), 是因為爬蟲抓到的就是`沒有js`的內容,除非用工具渲染js(後面文章有提到)不是說因為我們關閉了所以才只會抓到沒有js的內容(有點饒舌) 你上面網址的內容,我在第7天有說明哦https://ithelp.ithome.com.tw/articles/10204082
  •