哎呀哎呀,開學後變得好忙阿,連一天寫一篇的時間都沒有,果然先預留點文章是對的。參賽前還以為30天很短,實際參賽後才覺得真的是很漫長的過程,離結束還剩12天,好久阿~ (茶
好啦,發牢騷就到這邊,昨天我們已經用session抓到PTT八卦板的文章清單了,今天就接續來說怎麼抓到每一篇文的作者等詳細資訊吧!
我們延續昨天的進度,已經可以抓到首頁的文章列表了,但問題是,首頁能得到的資訊最多就這樣了,如果還想要進一步抓到文章中作者、時間等資訊該怎麼辦呢?
因此我們要另外想辦法,一樣 右鍵>>檢查,會觀察到標題其實就是個連結<a>
,而連結中的屬性href
正是文章內頁的網址。
既然這樣,就只需要我們之前學過BeautifulSoup的find_all()
就OK了。
import requests
from bs4 import BeautifulSoup
# post要傳的資料
payload = {
'from': '/bbs/Gossiping/index.html',
'yes': 'yes'
}
# 用session紀錄此次使用的cookie
rs = requests.session()
# post傳遞資料
response = rs.post("https://www.ptt.cc/ask/over18", data=payload)
# 再get一次PTT八卦板首頁
response = rs.get("https://www.ptt.cc/bbs/Gossiping/index.html")
print(response.status_code)
root = BeautifulSoup(response.text, "html.parser")
links = root.find_all("div", class_="title") # 文章標題
for link in links:
print(link.a["href"])
執行的結果:
但抓到的網址並不是完整的網址,我們要在前面加上PTT的網域才行。
for link in links:
page_url = "https://www.ptt.cc"+link.a["href"]
print(page_url)
這樣就可以順利取得文章內文的連結了!
那麼,取得這些連結後又要幹嘛呢? 當然就是利用這些網址,去取得每篇文章內文的原始碼阿! 取得方法更前面取得首頁文章列表類似,方法同樣是用GET。
用先前建立好的session物件,就不需要再帶cookie囉! 原因請見Day17。
response = rs.get(page_url)
result = BeautifulSoup(response.text, "html.parser")
隨便打開一篇文章,檢查作者、標題、時間這些欄位是放在哪裡。
發現都在 class="main-content"
的div底下 class="article-meta-value"
的span中。
所以程式碼就:
main_content = result.find("div", id="main-content")
article_info = main_content.find_all("span", class_="article-meta-value")
if len(article_info) != 0:
author = article_info[0].string # 作者
title = article_info[2].string # 標題
time = article_info[3].string # 時間
else: # 避免有沒有資訊的狀況
author = "無" # 作者
title = "無" # 標題
time = "無" # 時間
因為class="article-meta-value"
的span有4個,但,第一個是作者,第二個是我們不想要的,第三個的是標題,第四個是時間,所以索引值就是0、2、3。
老樣子,文章內容>>右鍵>>檢查,但這次有點麻煩,內容不存在特定的容器中。只是單純的丟到 "main-content" 而已。
即使如此也難不倒我們! 多檢查幾篇不同文章後,就會發現文章都是以 "- -" 來做結尾的,我們就來利用這個特性。
把先前抓的 "main_content" 文字的部分(text),使用split("- -")
以 "- -" 符號分割字串,並把最後一段給捨棄(通常是其他不相關的內容)。
但因為原本文章可能也含有 "- -" 符號而不小心被切割,再用 join()
函數將字串恢復原樣。
# 將整段文字內容抓出來
all_text = main_content.text
# 以--切割,抓最後一個--前的所有內容
pre_texts = all_text.split("--")[:-1]
# 將前面的所有內容合併成一個
one_text = "--".join(pre_texts)
試著把目前的文章內容print出來檢查。
發現文章是從第一個換行後開始(第一行是作者資訊那些的),所以就用 "\n" 來做分割,更上面一樣,用 join()
函數將字串恢復原樣。
# 以\n切割,第一行標題不要
texts = one_text.split("\n")[1:]
# 將每一行合併
content = "\n".join(texts)
結果,非常完美www (燦笑
今天教到怎麼抓取PTT八卦板文章的作者資訊和內容,明天接續來處理留言串的部分,還有最後把爬到的資料整理匯出成JSON檔,就這樣吧!
今天的文章好像有點划水,但最近真的比較忙,接下來會盡量每天多空出時間來寫文章的。
寫文章的此刻,網路上正好流行肥宅對話的話題,所以PTT上面出現很多相關的討論串,為了讓文章有趣一點,我也在文章裡加了一點肥宅用語(沒有很多啦),希望讀者看了之後沒有感到很不舒服www (摸頭
如果喜歡這系列文章麻煩幫我按Like加訂閱,你的支持是我創作最大的動力~
本系列文章以及範例程式碼都同步更新在GitHub上,後續會持續的更新,如果喜歡也麻煩幫我按個星星吧~
有任何問題或建議,都歡迎在底下留言區提出,還請大家多多指教。