iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
2
AI & Data

爬蟲在手、資料我有 - 30 天 Scrapy 爬蟲實戰系列 第 13

【Day 12】蒐集 iT 邦幫忙的技術文章 (5/6) - 文章資訊

  • 分享至 

  • xImage
  •  

通常蒐集的資料範圍不會只有文章標題和內文,還會有作者、發文時間、標籤,甚至瀏覽數、回文等等比較詳細的資訊。今天先來抓取比較簡單的幾個資訊吧。

區塊定位

昨天我們抓內文的時候,是直接使用 div.markdown__style 這個選擇器,在 Day 9 有提到我們可以先把元素定位在外層一點的地方,這樣後續比較好閱讀程式碼,執行起來也會比較快。

以 iT 邦幫忙來說,我會建議先把元素定位在 div.leftside,這樣不管是要抓原文或者下面的回文都可以從這邊開始。

https://ithelp.ithome.com.tw/upload/images/20190927/20107875jWLPAC5eMV.png

而要抓原文資訊時,就可以定位在 div.qa-panel,再根據要抓取的目標來往下找。

https://ithelp.ithome.com.tw/upload/images/20190927/20107875YTCJVWbiTT.png

import requests
from bs4 import BeautifulSoup

html_doc = requests.get('https://ithelp.ithome.com.tw/articles/10220022').text
soup = BeautifulSoup(html_doc, 'lxml')

leftside = soup.find('div', class_='leftside')
original_post = leftside.find('div', class_='qa-panel')

作者

雖然直接用 a.ir-article-info__name 就可以抓到作者名稱了,但這邊建議先定位在 div.qa-header,因為這個區塊包含了大部分我們要的資訊。

https://ithelp.ithome.com.tw/upload/images/20190927/20107875a8yE7k3Ruf.png

article_header = original_post.find('div', class_='qa-header')
article_info = article_header.find('div', class_='ir-article-info__content')

article_author = article_info.find('a', class_='ir-article-info__name')
print(article_author.get_text())

https://ithelp.ithome.com.tw/upload/images/20190927/20107875vwr8eo9WNp.png

這邊會發現作者名稱前後有一堆空白,可以用 article_author.get_text(strip=True)article_author.get_text().strip() 處理掉,通常取文字內容時也建議要這樣做。

發文時間

剛剛有先偷偷存一個 article_info 就是為了抓發文時間用的,因為 a.ir-article-info__time 元素就在裡面。

https://ithelp.ithome.com.tw/upload/images/20190927/20107875tCVw0kPCuX.png

from datetime import datetime

published_time_str = article_info.find('a', class_='ir-article-info__time').get_text(strip=True)
published_time = datetime.strptime(published_time_str, '%Y-%m-%d %H:%M:%S')

print(published_time)

因為每個網站的時間顯示格式都不太一樣,我個人習慣先轉換成 Python 的 datetime 物件,之後再視情況處理。

https://ithelp.ithome.com.tw/upload/images/20190927/20107875MmyP4E5JQn.png

文章標籤

元素位置在我們一開始存的 article_header 底下,要抓的是 div.qa-header__tagGroup 底下每一個 a.tag 的文字。

https://ithelp.ithome.com.tw/upload/images/20190927/20107875cGDVcLLBom.png

tag_group = article_header.find('div', class_='qa-header__tagGroup')
tags_element = tag_group.find_all('a', class_='tag')

tags = []
for tag_element in tags_element:
    tags.append(tag_element.get_text(strip=True))

print(tags)

或者用 pythonic 的寫法。

tags = [tag_element.get_text(strip=True) for tag_element in tags_element]
print(tags)

https://ithelp.ithome.com.tw/upload/images/20190927/20107875I3E7Exnju1.png

瀏覽數

元素位置在 article_info 底下,要抓的是 div.ir-article-info__view 標籤的文字內容。

https://ithelp.ithome.com.tw/upload/images/20190927/20107875Hj2k1EOVJI.png

view_count = article_info.find('div', class_='ir-article-info__view').get_text(strip=True)

print(view_count)

https://ithelp.ithome.com.tw/upload/images/20190927/20107875T5Ol4tneLJ.png

注意到我們取到的文字是47 瀏覽,如果只要數字的部份的話有兩個方式處理:

  1. 直接把「 瀏覽」字串移除(注意有個空白)
  2. 正規表示式把數字抓出來
view_count_str = article_info.find('div', class_='ir-article-info__view').get_text(strip=True)

# (1)
view_count = int(view_count_str.replace(' 瀏覽', ''))
print(view_count)

# (2)
import re
view_count = int(re.search('(\d+).*', view_count_str).group(1))
print(view_count)

https://ithelp.ithome.com.tw/upload/images/20190927/20107875Ytp6FI0X2X.png

程式碼整理

整理今天完整的原始碼如下:

import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re

html_doc = requests.get('https://ithelp.ithome.com.tw/articles/10220022').text
soup = BeautifulSoup(html_doc, 'lxml')

leftside = soup.find('div', class_='leftside')
original_post = leftside.find('div', class_='qa-panel')

article_header = original_post.find('div', class_='qa-header')
article_info = article_header.find('div', class_='ir-article-info__content')

# 作者
article_author = article_info.find('a', class_='ir-article-info__name').get_text(strip=True)

# 發文時間
published_time_str = article_info.find('a', class_='ir-article-info__time').get_text(strip=True)
published_time = datetime.strptime(published_time_str, '%Y-%m-%d %H:%M:%S')

# 文章標籤
tag_group = article_header.find('div', class_='qa-header__tagGroup')
tags_element = tag_group.find_all('a', class_='tag')
tags = [tag_element.get_text(strip=True) for tag_element in tags_element]

# 瀏覽數
view_count_str = article_info.find('div', class_='ir-article-info__view').get_text(strip=True)
view_count = int(re.search('(\d+).*', view_count_str).group(1))

上一篇
【Day 11】蒐集 iT 邦幫忙的技術文章 (4/6) - 內文
下一篇
【Day 13】蒐集 iT 邦幫忙的技術文章 (6/6) - 回文
系列文
爬蟲在手、資料我有 - 30 天 Scrapy 爬蟲實戰33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言