網頁

2023年4月30日 星期日

使用 Python 製作台股代碼與股票名稱對應字典(二)

上一篇提到將台股上市上櫃公司名稱從證交所網頁抓下來,並存成 dataframe 的格式,如下:

如果要用 yfinance 來取得股價寫法是:

import yfinance as yf
hist = yf.Ticker('1101.TW') # 台泥
price_df = hist.history(period='1d', auto_adjust=False)

因此我們要有一個 '1101.TW' 可以對應到 '台泥' 的一個 table,我們可以這樣做,

將上一篇得到的 df 的有價證券代號及名稱欄位的值切開,例如上圖,索引0台泥的 '有價證券代號及名稱' 欄位的值是 '1101  台泥',我們要切開成為 '1101.TW' 和 '台泥'

code, name = df['有價證券代號及名稱'][0].split()
print(code, name)

結果:1101 台泥 
將變數code+'.TW',就是股票代碼,股票名稱就是'台泥',然後使用 code 當作字典的key,
name當作字典的value,我們可以用一個迴圈跑完整個 df,順便將產業別也放上去
stock_dict = {}
for index, item in enumerate(df['有價證券代號及名稱']):
name_list = item.split()
code = name_list[0] + '.TW'
name = name_list[1]
key = code
value = [name, df['產業別'][index]]
stock_dict[key] = value
print(index, code, value)

 
 
 
 
 
然後將上面的程式寫成 function: 
# 製作股票代碼與股票名稱dict
def make_stock_dict(df):
stock_dict = {}
for index, item in enumerate(df['有價證券代號及名稱']):
name_list = item.split()
code = name_list[0] + '.TW'
name = name_list[1]
key = code
value = [name, df['產業別'][index]]
stock_dict[key] = value
return stock_dict
要呼叫的時候就這樣寫:
stock_dict = make_stock_dict(df)

返回的變數 stock_dict 是字典型態,
鍵(key)是股票代碼;值(value)是一個list,包含公司名稱和產業別。
這樣就製作了一個台股代碼和公司,名產業別的一個對照清單。

 
你可以參考上一篇:
1. 用 Python 取得台股上市上櫃清單(一)
 
 



2023年4月29日 星期六

用 Python 取得台股上市上櫃清單(一)

各位知道目前台股上市上櫃的公司有多少嗎?
今天用 Python 來抓取台灣證券交易所上市上櫃的公司清單。

台灣證券交易所公佈的上市證券國際證券辨識號碼一覽表網頁在:
https://isin.twse.com.tw/isin/C_public.jsp?strMode=2

 Mode=2是上市資料,Mode=4是上櫃資料,現在先用上市資料來說明。

1.首先先載入相關套件:

import requests
import pandas as pd

2. 將html 網頁資料抓下來存成 dataframe資料格式:

res = requests.get("http://isin.twse.com.tw/isin/C_public.jsp?strMode=2")
df = pd.read_html(res.text)[0]
df

3. 接著設定欄位(column)名稱:

df.columns = df.iloc[0]
df


4.  刪除第一行(Row):

df = df.iloc[2:]
df 


5. 接著要找出CFI code 是 ESVUFR 的資料,其中CFI代碼CBCIXU是不動產投資信託,CEOGEU是ETF . . .

df = df[df['CFICode'] == 'ESVUFR']
df

6. 現在資料有977筆,就是上市公司資料,接著我們要將索引序號重新編排一下:

df = df.reset_index(drop=True)
df

7. 最後我們把這寫成一個 function:

def crawler_stock_name(req_code):
# req_code:2 上市,
# req_code:4 上櫃
res = requests.get("http://isin.twse.com.tw/isin/C_public.jsp?strMode=" + str(req_code))
df = pd.read_html(res.text)[0]
# 設定column名稱
df.columns = df.iloc[0]
# 刪除第一行
df = df.iloc[2:]
# 篩選資料
df = df[df['CFICode'] == 'ESVUFR']
# index 序號重新編號
df = df.reset_index(drop=True)
return df

要取得上市公司的資料就執行:

df = crawler_stock_name(2)
df

要取得上櫃公司的資料就執行:

df = crawler_stock_name(4)
df
上櫃公司809家

下篇再來講一下如何將股票代碼和公司名稱做一個索引。

你可以參考:

1.  使用 Python 製作台股代碼與股票名稱對應字典(二)





2023年3月26日 星期日

解決osx samba網路瀏覽主機圖像變成問號的問題

安裝Debian 11 samba 分享後在osx 網路瀏覽這台主機會變成?問號,如下:

可以修改 /etc/smb.confGlobal 區段加上 fruit:model = model_name
model_name 可以有 iMac, MacPro, Macmini, iPhone . . .
例如,加上 fruit:model = iPhone
重啟 samba service :service smbd restart

sudo avahi-daemon -k

畫面上看到的主機會是這樣

如果加上 fruit:model = iMac
重啟 samba service :service smbd restart

畫面上看到的主機會是這樣

網路上有人寫了一隻python script 可以列出fruit:model的清單有興趣的人可以試一試,列出的 model有:

ADP2,1,
ADP3,2,
AirPort, AirPort4, AirPort4,102, AirPort4,107, AirPort5, AirPort5,104, AirPort5,105, AirPort5,108, AirPort5,114, AirPort5,117, AirPort6, AirPort6,106, AirPort7,120,
AppleTV, AppleTV1,1,
D201AP, D201AP, D201AP,
D20AP, D20AP, D20AP,
D211AP, D211AP, D211AP,
D21AP, D21AP, D21AP,
D221AP, D221AP,
D22AP, D22AP,
K48AP,
Laptop,
M68AP,
MacBook, MacBook1,1, MacBook1,1,Black, MacBook1,1,White,  MacBook2,1, MacBook2,1,Black, MacBook2,1,White, MacBook3,1, MacBook3,1,Black, MacBook3,1,White, MacBook4,1, MacBook4,1,Black, MacBook4,1,White, MacBook5,1, MacBook5,2, MacBook6,1, MacBook7,1, MacBook8,1, MacBookAir, MacBookAir1,1, MacBookAir10,1,  MacBookPro, MacBookPro1,1, MacBookPro1,2, MacBookPro10,1, MacBookPro10,2, MacBookPro11,1, MacBookPro11,2, MacBookPro11,3, MacBookPro11,4, MacBookPro11,5, MacBookPro12,1, MacBookPro13,1, MacBookPro2,1, MacBookPro2,2, MacBookPro3,1, MacBookPro4,1, MacBookPro5,1, MacBookPro5,2, MacBookPro5,3, MacBookPro5,4, MacBookPro5,5, MacBookPro6,1, MacBookPro6,2, MacBookPro7,1, MacBookPro8,1, MacBookPro8,2, MacBookPro8,3, MacBookPro9,1, MacBookPro9,2,
MacPro, MacPro1,1, MacPro2,1, MacPro3,1, MacPro4,1, MacPro5,1, MacPro6,1, MacPro7,1,
Macintosh,
Macmini, Macmini1,1, Macmini2,1, Macmini3,1, Macmini4,1, Macmini5, Macmini6, Macmini7, Macmini8,1, Macmini9,1,
N18AP,
N45AP,
N72AP,
N81AP,
N82AP,
N88AP,
N90AP,
PowerBook, PowerBook3,2, PowerBook3,3, PowerBook3,4, PowerBook3,5, PowerBook5,1, PowerBook5,2, PowerBook5,3, PowerBook5,4, PowerBook5,5, PowerBook5,6, PowerBook5,7, PowerBook5,8, PowerBook5,9, PowerBook6,1, PowerBook6,2, PowerBook6,3, PowerBook6,4, PowerBook6,5, PowerBook6,7, PowerBook6,8, PowerMac, PowerMac10,1, PowerMac10,2, PowerMac11,2, PowerMac11,2,Quad, PowerMac12,1, PowerMac3,5, PowerMac3,6, PowerMac4,2, PowerMac4,4, PowerMac4,5, PowerMac6,1, PowerMac6,3, PowerMac6,4, PowerMac7,2, PowerMac7,3, PowerMac8,1, PowerMac8,2, PowerMac9,1,
RackMac, RackMac1,1, RackMac1,2, RackMac3,1, RackMount,
TimeCapsule, TimeCapsule6, TimeCapsule6,106, TimeCapsule6,109, TimeCapsule6,113, TimeCapsule6,116, TimeCapsule8,119,
Tower,
Watch,
Windows, Windows2000, Windows2003, Windows2008, Windows7, WindowsVista, WindowsXP,
Xserve, Xserve1,1, Xserve2,1, Xserve3,1,
iMac, iMac10,1, iMac11,1, iMac11,2, iMac11,3, iMac12,1, iMac12,2, iMac13,1, iMac13,2, iMac13,3, iMac14,1, iMac14,2, iMac14,3, iMac14,4, iMac15,1, iMac16,1, iMac16,2, iMac17,1, iMac18,1, iMac18,2, iMac18,3, iMac19,1, iMac19,2, iMac20,1, iMac20,2, iMac21,1, iMac4,1, iMac4,2, iMac5,1, iMac5,2, iMac6,1, iMac7,1, iMac8,1, iMac9,1, iMacPro1,1,
iPad, iPad1,1,
iPhone, iPhone, iPhone, iPhone, iPhone, iPhone, iPhone, iPhone, iPhone, iPhone1,1, iPhone1,2, iPhone10,1, iPhone10,1, iPhone10,1, iPhone10,2, iPhone10,2, iPhone10,2, iPhone10,3, iPhone10,3, iPhone10,4, iPhone10,4, iPhone10,4, iPhone10,5, iPhone10,5, iPhone10,5, iPhone10,6, iPhone10,6, iPhone2,1, iPhone3,1,
iPod, iPod1,1, iPod2,1, iPod3,1, iPod4,1

解決 ssh 免密碼登入的異常

按此篇 SSH 登入免密碼 設定後發現還是要密碼才能登入ssh server,可以查看 /var/log/auth.log,輸入 grep 'sshd' /var/log/auth.log

 
Mar 26 10:36:44 wattOS sshd[13705]: Authentication refused: bad ownership or mod
es for directory /home/jkchang
 
才知道 /home/jkchang 我的家目錄權限異常,修改後就正常了。

另外,ssh 可以取消密碼登入,修改 /etc/ssh/sshd_config 將
PasswordAuthentication no
然後重啟 ssh service:
sudo service ssh restart
or
sudo /etc/init.d/ssh restart
 
您可以參考:
1. ssh登入免密碼 
 

2023年3月19日 星期日

簡單的 html 表單及 php 接收表單

首先做一個簡單的學生資料表單:

 
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<form method="post" action="demo.php">
學生資料建立 <br><br>
學號: <input type="text" name="id" value="">
<span class="error"> <?php echo $nameErr;?> </span>
<br><br>
姓名: <input type="text" name="name" value="">
<span class="error"> <?php echo $nameErr;?> </span>
<br><br>
性别:
<input type="radio" name="sex" value="male">男
<input type="radio" name="sex" value="female">女
<span class="error"> <?php echo $genderErr;?> </span>
<br><br>
手機: <input type="text" name="phone" value="">
<span class="error"> <?php echo $emailErr;?> </span>
<br><br>
郵件: <input type="text" name="email" >
<span class="error"><?php echo $websiteErr;?> </span>
<br><br>
擅長運動:
<input type="checkbox" name="sport[]" value="羽球">羽球
<input type="checkbox" name="sport[]" value="籃球">籃球
<input type="checkbox" name="sport[]" value="桌球">桌球
<input type="checkbox" name="sport[]" value="直排輪">直排輪
<span class="error"> <?php echo $sportErr;?> </span>
<br><br>
<input type="submit" name="submit" value="送出">
<input type="reset" value="清除">
</form>

將此檔案存檔為 demo.html,並在瀏覽器輸入 127.0.0.1/demo.html


 

接著寫一個可以接收 html 表單資料的 php 程式:


<?php
$id = $_POST['id'];
$name = $_POST['name'];
$sex = $_POST['sex'];
$phone = $_POST['phone'];
$email = $_POST['email'];
echo "學號: ".$id;
echo "<br>姓名: ".$name;
echo "<br>性别: ".$sex;
echo "<br>手機: ".$phone;
echo "<br>郵件: ".$email;
echo "<br>擅長運動: ";
$q = isset($_POST['sport'])? $_POST['sport'] : '';
if(isset($q)) {
foreach($q as $val) {
echo $val.', ';
}
}
?>

我們將檔案存成 demo.php ,記得要和 html 表單程式裡呼叫的檔名相同就好。

現在在表單輸入一些資料:

按下送出後會出現:



OSX 設定 Apache、PHP

Mac OSX 已經內建了 Apache 與 PHP,只要幾個動作就可以設定完成。

1.啟動 Apache:
OSX已經安裝好 Apache Server,啟動 Apache 只要輸入:


sudo apachectl start

在瀏覽器網址列輸入http://127.0.0.1,如果畫面上出現 It Works! 就代表啟動 Apache 了!
 

2.編輯Apache設定檔:
由於 Mac 已經內建 PHP 模組,我們只要在 Apache 中將他啟用就可以了
使用編輯器編輯 Apache 設定檔 /etc/apache2/httpd.conf,找到:


LoadModule php7_module libexec/apache2/libphp7.so

將前面 # 號刪除即可。

3.重新啟動 Apache:


sudo apachectl restart

步驟做完了, 當然要驗證一下 PHP 是否有如期運作, 透過下面指令建立一個測試用的 php 檔案

echo "<?php phpinfo();" | sudo tee /Library/WebServer/Documents/info.php

意思是在 /Library/WebServer/Documents/ 目錄下建立一個 info.php 檔案,內容是:

<?php phpinfo();

接著我們就可以在瀏覽器位址欄輸入 http://127.0.0.1/info.php 來檢查一下結果:
 

如果出現如上圖的畫面就代表 PHP 已經正常啟動了!
(PHP Info 可能會因為版本不同而有差異)

 4.設定目錄權限:
OSX 的 Apache 預設工作目錄為 /Library/WebServer/Documents/

由於預設的擁有者是 root,這會導致我們無法直接寫入檔案,可以透過下面指令將所有權限改成使用者的:


sudo chown -R 使用者名稱 /Library/WebServer/Documents/



2023年3月9日 星期四

TORRE ORIA 西班牙小紅帽半甜紅葡萄酒

 

晚餐老婆準備了一些菜,今晚就開這瓶 西班牙小紅帽半甜紅酒  吧。
 
 
這支一樣是來自西班牙的紅酒,葡萄品種是博巴爾(Bobal),第一次喝這品種的紅酒,看介紹才知博巴爾是西班牙僅次於田帕尼優Tempranillo的葡萄品種,也是西班牙的特有品種。
 
Bobal 與其他品種葡萄色澤比較
 
酒精濃度12%,葡萄品種博巴爾(Bobal),酒體呈現寶石紅色,色澤深厚,喝起來如名稱"半甜",實際上我覺得根本是甜酒,蠻適合當餐酒或是女生喝。
 
瓶塞的狼人標誌: 
 
 
紅酒呈寶石紅色,色澤深厚,有著豐富水果香氣:
 
 
全聯價格$399,不喜歡紅酒的酸澀口感不妨試試這瓶半甜紅酒。
 
 

2023年3月6日 星期一

使用Python 做 Yahoo電影爬蟲

最近在寫LINE-bot聊天機器人,有個功能是查詢Yahoo電影的本週新片功能,有參考了網路上的一些方法,不過有些項目爬不下來有可能是Yahoo電影的網頁格式有改過,我把我修改的版本分享給大家順便可以練習爬蟲。


1.首先載入相關的套件:

 
import requests
from bs4 import BeautifulSoup
import pyshorteners as ps
 

說明:

requests:requests套件支援了HTTP的各種請求方法,其中GET與POST是最常使用到方式。
BeautifulSoup:BeautifulSoup是一個用來解析HTML結構的套件,將取回的網頁HTML結構,透過其提供的方法(Method),能夠輕鬆的搜尋及擷取網頁上所需的資料。
pyshorteners:縮短網址的套件。

2.將網頁爬取下來:

 
url = "https://movies.yahoo.com.tw/movie_thisweek.html"
# 使用 http GET 請求 url 的內容
response = requests.get(url)
# 擷取 request 回傳的文字部分
web_content = response.text
# 使用 BeautifulSoup 來 parse 網頁的內容
soup = BeautifulSoup(web_content,'lxml')
soup_items = soup.find_all("div", {"class":"release_info"})
 

3.現在網頁資訊都在soup_items變數內,內容大概是這樣:
 

4.現在要將本週新片的中文電影名稱取出,我們到Yahoo電影的本週新片頁面用F12來看網頁內容:

4.用迴圈將資訊取出,使用 find 方法找出字串中是否包含子字符串"release_movie_name",就是電影新片中文名稱 (strip()是將取出的字串前後空白刪除)。   

 
for index, item in enumerate(soup_items):
# 中文片名
name = item.find("div", {"class":"release_movie_name"}).a.text.strip()
 

5.用這方法可以依序找出英文片名,上映時間的資訊:

    
    # 英文片名
en = item.find("div", {"class":"en"}).a.text.strip()
# 上映時間
release_time = item.find("div",
{"class":"release_movie_time"}).\
text.split(':')[-1].strip()
 

6.接下來是"期待度"資訊,網路上大多用 div 標籤裡面的 span 標籤,不過這方式試過不行,直接用 "leveltext" 標籤就好。

 

為了不要因為抓到 None值會出現錯誤,還是給個條件測試一下比較保險:   

     
    # 期待度
    level = 'No Data' if item.find("div", {"class":"leveltext"}) is None \
else item.find("div", {"class":"leveltext"}).span.text
 

7.接著是取出預告片網址連結,在"btn_s_vedio"標籤內。
   

取出"btn_s_vedio"標籤的 href 值(就是預告片網址):

    
    # 預告片連結
tag1 = item.find('a', class_="btn_s_vedio")
trailer = tag1.get("href")
trailer = '-無預告片-' if trailer is None else trailer    
 

或是:

 
    trailer if not trailer is None else '-無預告片-'
 

tag1 和 trailer 也可以合併寫成:  

    
    trailer = item.find('a',class_="btn_s_vedio gabtn")['href']
 

不過當沒有預告片連結的時候會出錯,因為 href 的值會是 None,所以不建議這樣寫。

trailer 的值如下:


8.利用 pyshorteners 將新片連結的長網址改成短網址,如果沒有預告片網址就將直改為'-無預告片-':   
     
    # 縮網址
short_url = ps.Shortener().tinyurl.short(trailer) \
if not trailer is None else '-無預告片-'
 

9.印出結果:   
     
    print(f'{index + 1:>2d}.電影名稱:{name}')
print(f' 英文片名:{en}')
print(f' 上映時間:{release_time}')
print(f' 期待度:{level}')
print(f' 預告片:{trailer}')
print(f' 短連結:{short_url}')
print('-' * 50)
 


10.原始碼如下:

 
import requests
from bs4 import BeautifulSoup
import pyshorteners as ps

url = "https://movies.yahoo.com.tw/movie_thisweek.html"
# 使用 http GET 請求 url 的內容
response = requests.get(url)
# 擷取 request 回傳的文字部分
web_content = response.text
# 使用 BeautifulSoup 來 parse 網頁的內容
soup = BeautifulSoup(web_content,'lxml')
soup_items = soup.find_all("div", {"class":"release_info"})
for index, item in enumerate(soup_items):
# 中文片名
name = item.find("div", {"class":"release_movie_name"}).a.text.strip()
# 英文片名
en = item.find("div", {"class":"en"}).a.text.strip()
# 上映時間
release_time = item.find("div",
{"class":"release_movie_time"}).\
text.split(':')[-1].strip()
# 期待度
level = item.find("div", {"class":"leveltext"}).span.text
# 預告片連結
tag1 = item.find('a', class_="btn_s_vedio")
trailer = tag1.get("href")
#trailer = item.find('a',class_="btn_s_vedio gabtn")['href']
#trailer = '-無預告片-' if trailer is None else trailer
trailer if not trailer is None else '-無預告片-'
# 縮網址
short_url = ps.Shortener().tinyurl.short(trailer) \
if not trailer is None else '-無預告片-'
print(f'{index + 1:>2d}.電影名稱:{name}')
print(f' 英文片名:{en}')
print(f' 上映時間:{release_time}')
print(f' 期待度:{level}')
print(f' 預告片:{trailer}')
print(f' 短連結:{short_url}')
print('-' * 50)
 

執行結果: