嗨,第八天了!昨天介紹了網頁
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
包覆在h3
且class
為r
的標籤裡面,程式碼:
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