# 2022-12-11 第五天 Python網路爬蟲應用實務班上課記錄
###### tags: `python` `爬蟲` `crawler`
## CSS選擇器
#### HTML
```html=
<!DOCTYPE html>
<html>
<head>
<title>這是我的網頁</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<link href="main.css" rel="stylesheet" />
</head>
<body>
<header>
<h1>個人部落格</h1>
<nav>
<ul>
<li>首頁</li>
<li>關於我</li>
</ul>
</nav>
</header>
<article>
<img src="https://www.taiwan.net.tw/pic.ashx?qp=1/big_scenic_spots/pic_2187_5.jpg&sizetype=3" />
<h3>風景</h3>
<p>風景介紹風景介紹風景介紹風景介紹風景介紹風景介紹風景介紹風景介紹</p>
</article>
<article>
<h3>好用工具收集</h3>
<a href="http://www.aaronlife.com">教學講義</a>
<a href="https://www.google.com">谷哥搜尋</a>
<a href="https://www.yahoo.com.tw">雅虎奇摩</a>
</article>
<!-- 側邊選單 -->
<aside>
<h3 id="menu">內容快選</h3>
<ul>
<li class="menu-item">2022年12月</li>
<li class="menu-item">2022年11月</li>
<li class="menu-item">2022年10月</li>
<li class="menu-item">2022年09月</li>
</ul>
</aside>
</body>
</html>
```
#### CSS
```css=
/* CSS Selector(CSS選擇器) */
body {
background-color: #B4CEB3;
}
h1 {
font-size: 5em;
text-align: center;
}
li {
font-size: 2em;
}
img {
width: 50%;
}
h3 {
font-size: 2.5em;
color: blueviolet;
}
/* id名字不可重複 */
#menu {
font-size: 3em;
color: coral;
}
/* .menu-item {
color: chocolate;
} */
/* a標籤如果有href屬性 */
a[href] {
color:darkblue;
font-size: 1.5em;
}
a[href="http://www.aaronlife.com"] {
color:cornflowerblue;
font-size: 1.5em;
}
/* nav標籤內的url標籤內的li標籤 */
nav ul li {
color:darkgreen;
}
```
#### Python
```python=
from bs4 import BeautifulSoup
# 原始HTML原始碼
html_doc = '''
<html>
<head>
<title>這是HTML文件標題</title>
</head>
<body>
<h1 id="article" class="banner">網頁標題1</h1>
<p data-author='aaron' class="reqular text-normal">文章段落1</p>
<a class="link no btn" href="https://www.aaronlife.com/ref1">參考<b>資料</b>連結1</a>
<a class="link btn" href="http://www.aaronlife.org/ref2">參考<b>資料</b>連結2</a>
<a class="link btn" href="http://www.aaronlife.edu/ref2">參考資料連結3</a>
<a class="link btn" href="https://www.aaronlife.com/ref2">參考資料連結4</a>
<p>這是一份<b class="boldtext">HTML文件</b>。</p>
<h2 id="article1" class="banner">網頁標題2</h2>
<p data-author='andy' class="reqular text-normal">文章段落2</p>
<h2 id="article2" class="title normal">網頁標題3</h2>
<p data-author='william' class="reqular text-normal">文章段落3</p>
</body>
</html>
'''
soup = BeautifulSoup(html_doc, 'html.parser')
print(soup.prettify())
# 定位a標籤
result = soup.select('a')
print(result)
# 定位body裡面的p裡面的b標籤
result = soup.select('body p b')
print(result)
# 定位id=article標籤(只會有一個)
result = soup.select('#article')
print(result)
# 定位class屬性有link的標籤(可能多個)
result = soup.select('.link')
print(result)
# 定位class屬性有link或是有text-normal屬性值的標籤
result = soup.select('.link, .text-normal')
print(result)
# 定位class屬性同時有link和no和btn三個屬性值的標籤
result = soup.select('.link.no.btn')
print(result)
# 定位有href屬性的所有a標籤
result = soup.select('a[href]')
print(result)
# 定位有href屬性的所有a標籤第一筆符合條件的標籤
result = soup.select_one('a[href]')
print(result)
# 定位a標籤的href屬性值為https://www.aaronlife.com/ref1的標籤
result = soup.select('a[href="https://www.aaronlife.com/ref1"]')
print(result)
# 定位a標籤的href屬性值開頭為https的標籤
result = soup.select('a[href^="https"]')
print(result)
# 定位a標籤的href屬性值結尾為ref1的標籤
result = soup.select('a[href$="ref1"]')
print(result)
# 定位a標籤的href屬性值包含為.com的標籤
result = soup.select('a[href*=".com"]')
print(result)
```
#### 使用CSS選擇器爬取台灣銀行網頁資訊
```python=
from bs4 import BeautifulSoup
import requests # 下載網頁用的模組
import csv
import time
url = 'https://rate.bot.com.tw/xrt?Lang=zh-TW' # 匯率網址
# 下載台灣銀行匯率網頁原始碼
response = requests.get(url)
html_doc = response.text
# 寫入本地端確認有下載完整
# with open('rate.html', 'w', encoding='utf-8') as rate:
# rate.write(html_doc)
soup = BeautifulSoup(html_doc, 'html.parser')
# print(soup.prettify()) # 格式化下載後的網頁
tbody = soup.find('tbody')
all_rates_rows = tbody.find_all('tr')
all_rate_data = []
for row in all_rates_rows:
# 存放匯率資訊
rate_data = []
# 取得幣別
money_type = row.select_one('.hidden-phone.print_show').string.strip()
rate_data.append(money_type)
# 取得匯率資訊
rate_data.append(row.select_one('td[data-table="本行現金買入"].print_width').string.strip())
rate_data.append(row.select_one('td[data-table="本行現金賣出"].print_width').string.strip())
rate_data.append(row.select_one('td[data-table="本行即期買入"].print_width').string.strip())
rate_data.append(row.select_one('td[data-table="本行即期賣出"].print_width').string.strip())
all_rate_data.append(rate_data)
# 全部資料
print(all_rate_data)
# 以目前時間產生檔名
now = time.localtime()
file_name = time.strftime('%Y%m%d_%H%M%S.csv', now)
print('輸出的檔案名稱:', file_name)
with open(file_name, 'w', encoding='utf-8', newline='') as csvfile:
csvfile.write('\ufeff') # UTF-8 BOM
writer = csv.writer(csvfile) # 建立CSV寫入器
writer.writerow(['幣別', '現金買入', '現金賣出', '即期買入', '即期賣出'])
writer.writerows(all_rate_data)
```
## 練習
#### 爬取PTT Python版最新文章標題
```python=
# 請開發一個靜態網頁爬蟲,到https://www.ptt.cc/bbs/Python/index.html裡面爬出每個討論題目並險是在終端機畫面上:
# 例如:
# ------------------------------------------------------------------------------
# [問題] 優化程式碼,轉成 dict
# Re: [問題] 優化程式碼,轉成 dict
# Re: [問題] multiprocessing.pool能不用name==main嗎
# Re: [問題] 列出一個列表中所有子集合
# Re: [問題] 優化程式碼,轉成 dict
# Re: [問題] 列出一個列表中所有子集合
# [問題] 如何在sklearn中的分詞加入自己的辭典?
# ....
import requests
from bs4 import BeautifulSoup
url = 'https://www.ptt.cc/bbs/Python/index.html' # 目標網址
response = requests.get(url) # 取得ptt網頁原始碼
html_doc = response.text # 網頁原始碼
soup = BeautifulSoup(html_doc, 'html.parser')
a_tags = soup.find_all('a', class_=None, id=None) # 定位所有的a標籤
for i in a_tags:
if i.string.strip().find('搜尋') != 0:
print(i.string.strip())
```
## JSON
#### JSON解析
```python=
import json
my_json = '''
{
"name": "value",
"name2": "value2",
"name3": 999,
"name4": {
"sub": "value11",
"sub2": "value2"
},
"name5": [{
"obj": "hi"
}, 2, 3, 4, 5]
}
'''
# dumps() 將python物件轉成JSON字串
# loads() 將JSON字串轉成Python物件
json_obj = json.loads(my_json)
print(json_obj['name3'])
print(json_obj['name4']['sub2'])
print(json_obj['name5'][0]['obj'])
```
#### 爬Google Trend資料
```python=
import requests
url='https://trends.google.com.tw/trends/api/dailytrends?hl=zh-TW&tz=-480&geo=TW&ns=15&ed='
url += '20221112'
response = requests.get(url)
print(response.text)
```