iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
自我挑戰組

從HTML到Python爬蟲的30天之旅系列 第 18

Day 18:專案03 - PTT 八卦版爬蟲03 | 文章標題、作者、時間

  • 分享至 

  • twitterImage
  •  

哎呀哎呀,開學後變得好忙阿,連一天寫一篇的時間都沒有,果然先預留點文章是對的。參賽前還以為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上,後續會持續的更新,如果喜歡也麻煩幫我按個星星吧~

有任何問題或建議,都歡迎在底下留言區提出,還請大家多多指教。


上一篇
Day 17:專案03 - PTT 八卦版爬蟲02 | session、post
下一篇
Day 19:專案03 - PTT 八卦版爬蟲04 | 留言、換頁、json
系列文
從HTML到Python爬蟲的30天之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言