顯示具有 python 標籤的文章。 顯示所有文章
顯示具有 python 標籤的文章。 顯示所有文章

2024年6月2日 星期日

[selenium] chrome driver issue: disconnected: not connected to DevTools

使用 chrome driver 第 6 個月後,第一次遇到這個問題,記錄一下處理過程,遇到問題如下圖


這是發生在不斷發出 request 後的 11 分鐘左右才遇到的,若是使用時間較短的,目前沒遇到此問題。

然後我又看到下面資訊,想說,該不會是 browser 和 chrome driver 的版本第四個數字不一樣造成的吧?
capabilities":{"acceptInsecureCerts":false,"browserName":"chrome-headless-shell","browserVersion":"125.0.6422.142","chrome":{"chromedriverVersion":"125.0.6422.141

但 chrome driver 目前能 download 到的只有 125.0.6422.141,該不會這個 .142 版的 browser 有什麼更新真的讓 .141 driver 產生問題了吧,google 了一下,目前沒發現什麼解法,

[後記][2024/07/06] 後來又有一天什麼都沒動,再重跑一次就可以用了,結論就是,不確定原因是什麼,但這個原因可能會消失,之後若再遇到的話,若 chrome driver 都更新好了,就只能改天再試試了


2024年2月25日 星期日

[scrapy] 實戰記錄 - 台北 101 網站

攝影師:Pixabay

為了增加百貨公司品牌爬蟲的內容, 近期開始研究台北 101 網站,找到這裡可以看到全部的品牌,把這些都爬出來就行了

先找出正確的 element

從下圖可看出,這些品牌存在於 "listarea logo" class 下面的 "cardobj lazyload show" class 中

問題:

準備好 request https://www.taipei-101.com.tw/tw/shopping/brandsearch 然後去拿 "cardobj lazyload show" class 裡的資料,但會發現抓不到資料,將 response.text 印出來後存成檔案才發現,"listarea logo" class 裡是沒有內容的

處理方式:

發現這些品牌資訊是另外 request 去拿到 json 檔案回來 parse 而成

這邊直接找出此 request,直接用 python 去抓回來 parse 完成





2023年6月3日 星期六

[scrapy] 使用 scrapy 爬不到資料

Photo by ThisIsEngineering

記錄一下使用 scrapy 遇到的一些問題

問題:
用 browser 打開這個網頁明明就能看到畫面,但使用下面方法後
scrapy shell https://info.sogo.com.tw/tp1/floors/B2 
view(response)
卻只能看到下面錯誤

後來發現,這是因為少設定了 USER_AGENT 的關係,user agent 通常是用來識別 request 這方的軟體、os、device 等資訊,有些 server 會檢查這個 http header 資訊,若沒有的話,就不會回傳正確 response

處理方式:
在 settings.py 裡找到 USER_AGENT 設定,將一個正確的 user agent 填入即可,這邊我是參考 chrome 的 user agent 填入(如下)

問題:
網頁能打開後,卻找不到品牌列表,用 browser 打開往下 scroll 後,會看到如下的畫面,品牌列表的部份看起來是被放在這樣的結構裡

<div class="tab-content">
...
<a href="xxxx" class="brandBox">...</a>

但是使用
scrapy shell https://info.sogo.com.tw/tp1/floors/B2 
view(response)
卻只能看到 <div class="tab-content"> 裡沒有 brandBox 的資料

分析:
用 chrome 的 inspect 可以找到品牌列表是用這個 request 來的

而這個 request 是由 jquery-3.2.0.min.js 裡呼叫的
由此就能確定,找不到品牌列表是因為他是 javascript 的 request 而來的,scrapy 預設是爬靜態網頁,所以我邊需要針對這個 javascript 的 request 多做處理才行

這邊分享兩個 debug 技巧,
1. 在 spider 程式內呼叫 scrapy shell 的功能,在 def parse() 裡寫到下面即可
from scrapy.shell import inspect_response
inspect_response(response, self)
2. 在 spider 程式內印出 response 網頁資料,做法如下
def write_to_file(self, words):
    with open("logging.log", "a") as f:
        f.write(words)

def parse():
    self.write_to_file("response text: %s" % response.text)

處理方式:
使用 selenium 幫忙處理 javascript 的 request,照下面方法將 selenium 安裝且設定好,使用 selenium 的 function 做同一個 url 的 request,response 的資料裡就有品牌列表了
安裝 selenium
pip install scrapy-selenium
安裝 chrome driver
這裡下載跟自己使用的 chrome driver 相近的版本
在 settings.py 裡做好設定
總共四個設定,SELENIUM_DRIVER_EXECUTABLE_PATH 就是填上面下載的 chrome driver 檔案的路徑
在 spider 中使用
這邊不使用原本的 start_urls,而是使用如下的做法
from scrapy_selenium import SeleniumRequest
def start_request(self):
    target_url = "xxx"
    yield SeleniumRequest(url=target_url, callback=self.parse)

原本使用下面兩行去看有多少品牌是 0,設定成功之後,就可以看到 60
brands_num = len(response.xpath('//a[@class="brandBox"]'))
print("brands_num: " + (str)(brands_num))

Reference

2020年12月19日 星期六

[程式][投資] 查看多隻美股有被哪些 ETF 持有

QuoteInspector.com

ETFDB 裡面的 ETF Stock Exposure Tool 很好用,可以查出單一隻美股有被哪些 ETF 持有,但卻無法一次查出多隻美股有被哪些 ETF 持有,雖然 ETF Channel 有這個功能,但還是比較喜歡 ETFDB 的介面,於是我用 Python 做出了讓 ETFDB 能夠查看多隻美股有被哪些 ETF 持有的功能。

這功能算是我練習用的,請勿使用在商業行為,一天也不能使用太多次,否則會被擋掉,請小心服用 github

作法如下:

先將最後輸入的美股代號從 ETF Stock Exposure Tool 找出所有買進的 ETF,送出正確的 URL 後再利用這篇的方法,找出中間使用到多頁查詢的 request,再將多個 request 抓回來,這些資料是透過 json 儲存的,拿到 response 後將 ETF 的名稱抓出來

找到這些 ETF 後再逐一送出 request 去看他的持有股票,再將這些股票逐一比對你輸入的美股代號,就可以找出哪些 ETF 有持有你想查的多隻美股

執行範例:找出同時擁有 AAPL TSLA COST 的 ETF 是 ONEQ

US_ETFs_Exposure.py AAPL TSLA COST



2020年1月30日 星期四

[程式][投資] 查看近 12 年 EPS 資訊及其年增率


這篇 有提到過,希望能讓投資更加穩健,在 理財達人秀 - 存股敵8個 看到了 EPS 的重要,想要可以在找新的股票或是在檢視手中股票時可以方便的查詢 EPS 和年增率,另外也想學習 Python,就寫了一個 script,同時也把程式放在 github 上讓大家方便存取。

透過下面網址連到公開資訊觀測站,輸入公司代號後,就會列出 "簡明綜合損益表(三年)",表格的最下方就有 "基本每股盈餘(元)" 資訊,我是以這個資訊當做例子來製作 script。
https://mops.twse.com.tw/mops/web/t163sb17

想要看三年以前的資料,可以選擇歷史資料和年度即可,但是 101 年以前的資料,網站會指引你去別的網頁查,使用方法跟上面的網頁完全一樣。

利用 Python 送出 4 次 request 取回這些資料後,利用 pandas 把網頁資訊分析後找出 EPS,再把這些 EPS 資料存到變數裡,最後再將每年的年增率算出,然後排成適合閱讀的列表,如上圖。

關於怎麼查看網頁 POST 資料,可以參考 這篇
這只是個開始,之後會看還需要什麼樣的資訊,繼續寫新的 script。

Reference:




2019年12月18日 星期三

[程式] 如何查看 POST 資料,以公開資訊觀測站為例


很想來玩玩爬財報,看到網路上這篇 Python 財報爬蟲 覺得很有趣,但總覺得有釣竿會比直接吃魚好一些,就開始研究他的程式到底怎麼做出來的,其中我搞不清楚的就是公開資訊站的財報資料是要用 POST 的方式送出資料的,Python 可以做到送出 POST 這個沒問題,但我怎麼知道 POST 要帶出哪些東西?(如下)

r = requests.post(url, {
        'encodeURIComponent':1,
        'step':1,
        'firstin':1,
        'off':1,
        'TYPEK':'sii',
        'year':str(year),
        'season':str(season),
    })

查了他網頁原始碼,再用了一些 web sniffer 工具,最後再 Google 一陣子後,發現原來 Chrome 就有非常好用的工具可以找出此次 POST 是帶什麼資料

打開 Chrome Menu -> 更多工具 -> 開發人員工具(Ctrl + Shift + I)

接著選到上方有一個 Network,然後按網頁上你想看的動作,目前的範例是 公開資訊觀測站 上的查詢,接著在 Network 左下方出現的 request 點一下,就可以看到下方的 Form Data,裡頭就是 POST 要帶出的資料

我用的 Chrome 版本是 79.0.3945.79,這個開發人員工具真的非常好用,希望大家都能學會。

Reference
Python 財報爬蟲

2018年2月25日 星期日

[程式] Pandas 初體驗:找出投資商品配息資料


因為想要用 Python 來協助我更快看股票配息資料,找到了 Pandas 和 [Python] 使用 Pandas 來撈資料,照著上面的做,很快的我可以抓到 stockq 的資料(程式如下)
import pandas as pd
url = 'http://www.stockq.org/market/asia.php'
table = pd.read_html(url)[4]
table = table.drop(table.columns[[0,1,2,3,4]],axis=0)
table = table.drop(table.columns[9:296],axis=1)
print table
我想抓我最常看殖利率的網站 Goodinfo! 台灣股市資訊網,卻得到 error 如下

ValueError: No tables found

用 WHATS MY INFO 確認一下 user-agent 是 Python-urllib/2.7,再用 User-Agent Switcher for Google Chrome 測試一下,果然會得到 "請勿透過網站內容下載軟體查詢本網站" 的回應。

試著把他換成一般 chrome browser 的 user-agent 再試試,果然讀的到東西(程式如下)
import pandas as pd 
import requests
url = 'https://goodinfo.tw/StockInfo/StockDividendPolicy.asp?STOCK_ID=1416'
table = pd.read_html(requests.get(url, headers={'User-agent': 'Mozilla/5.0 
(Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) 
Chrome/63.0.3239.132 Safari/537.36'}).text)
print table
後來發現 Yahoo Finance 是比較適合拿資料的地方,因為他可以拿到台港美股的資料,但改成用 Yahoo Finance 後又遇到下面這個錯誤
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U95') dtype('<U95') dtype('<U95')

這個錯誤是跟編碼有關的問題,看起來是 pands.read_html() 裡面產生的問題,之前用 Python 爬東西時,也常遇到這種編碼問題,為了避開這個問題,我們先將資料用 BeautifulSoup 做處理,拉出 table 後,再餵進 pandas,就可以抓出 Yahoo Finance 上面顯示的歷史配息資料了,執行後會看到 Quote:,輸入在 Yahoo Finance 上找的到的代號,就會顯示結果如下了,程式和執行結果如下:

程式:
import pandas as pd 
import requests
from bs4 import BeautifulSoup
x = raw_input("Quote: ")
url = 'https://finance.yahoo.com/quote/'+x+'/history?period1=946915200&period2=1519401600&interval=div%7Csplit&filter=div&frequency=1d'
r = requests.get(url)
soup = BeautifulSoup(r.content, 'lxml')
table = soup.find_all('table')[0];
dfs = pd.read_html(str(table))
for index, row in dfs[0].iterrows():
    print row[0], row[1]

執行結果:
Quote: 2330.tw
Jun 26, 2017 7 Dividend
Jun 27, 2016 6 Dividend
Jun 29, 2015 4.49988 Dividend
Jul 14, 2014 2.99991 Dividend
Jul 03, 2013 2.99955 Dividend
Jul 04, 2012 2.99948 Dividend
Jun 29, 2011 2.99951 Dividend
Jul 06, 2010 2.99973 Dividend
Jul 15, 2009 2.98497 Dividend
Jul 16, 2008 3.00989 Dividend
Jun 08, 2007 2.98459 Dividend
Jun 20, 2006 2.42631 Dividend
Jun 13, 2005 1.90457 Dividend
Jun 14, 2004 0.529159 Dividend

因為這是初體驗,所以沒有任何 error handle 的處理,請小心使用 :)

安裝 library 方法:
pip install pandas
pip install BeautifulSoup
pip install requests

Reference:
Pandas
[Python] 使用 Pandas 來撈資料
Goodinfo! 台灣股市資訊網
WHATS MY INFO
User-Agent Switcher for Google Chrome
BeautifulSoup