Day 18:专案03 - PTT 八卦版爬虫03 | 文章标题、作者、时间

哎呀哎呀,开学後变得好忙阿,连一天写一篇的时间都没有,果然先预留点文章是对的。参赛前还以为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上,後续会持续的更新,如果喜欢也麻烦帮我按个星星吧~

有任何问题或建议,都欢迎在底下留言区提出,还请大家多多指教。


<<:  Unity自主学习(九):创建新专案

>>:  Day 23 实作 user_bp (1)

DAY 25 制作表格-添加中文字体

添加中文字体 在安装matplotlib後,因为我们的资料内含有中文字,而matplotlib内建并...

Day28|将 GitHub 的档案抓取下来到自己的本地端 - git pull 指令与冲突时的解决方法

上篇介绍了如何将档案 Push 到 GitHub 後,今天就来练习如何从 GitHub 下载档案吧!...

Day17 简易资料库RealmSwift小实作4

昨天我们说到刷新tableview的部分,因为每一笔资料写入都要将资料写进realm里,再从中回传至...

mostly:functional 谢幕与片尾曲

The future is already here – it's just not evenly...

[Day11] - Django REST Framework 介绍

在前几篇我们介绍了 Docker 以及 Docker Compose,让开发时的环境设定不会再因为作...