Web Crawler (Dcard)#

# 載入使用的套件
import pandas as pd
import requests

import re
# 檢視資料結構
ID = '235442609'
url = 'https://www.dcard.tw/_api/posts/' + ID
# 透過request套件抓下這個網址的資料
requ = requests.get(url)
# 初步檢視抓到的資料結構
requ.json()
{'id': 235442609,
 'title': '超狂學經歷!195公分帥家教徵學生',
 'content': 'https://i.imgur.com/REIEzSd.jpg\n\n身高195公分的男大生楊承翰在家教社團PO文徵學生的文章被網友推爆了,網友們看到他的學經歷及成績不禁大讚根本就是學霸王,而他不只擁有高顏質,還是籃球系隊成員,超乎常人的學經歷及證書考試成績,瞬間讓網友都跪著朝聖,直呼「天哪好厲害的帥哥」、「這個當家教太可惜了」。\n\n21歲台大學生楊承翰日前在臉書社團「家教補教學校兼全職、打工、師訓交流」發文,想以時薪1千5百元找家教學生,授課內容為英文、數學、理化、程式語言、留學申請,及SAT/ACT/TOFEL/AP等,希望能在台北範圍教學,也可接受線上教學,貼文下方也附註他的學經歷。\n\n學歷:\n就讀美國杜克大學(Duke University)大三,雙主修資工,數學\n畢業於新竹科學園區實驗中學(National Experimental High School)\n美國哈佛大學(Harvard University)暑期醫學研究生\n國立台灣大學(National Taiwan University) 新冠專案訪問生\n\n相關經歷:\n從小在美國及台灣長大,精通中英文。\n擁有三年以上的教學經驗,1對1家教經驗豐富(7+學生,科目分別為代數、微積分、化學、Python程式設計及英文寫作)。\n曾任教於台北市美西留學教育顧問公司,擔任數學專科及SAT衝刺班教師。\n多次擔任私人留學顧問,幫助學生錄取杜克大學(Duke University),加州理工學院(California Institute of Technology)及密西根大學(University of Michigan)等。\n協助杜克大學校方開發資工系大一必修的課程網頁及作業内容。\n\n考試分數:\nSAT: 1540/1600(Essay 24/24)\nACT: 34/36\nTOEFL: 119/120\nSAT Chinese, Biology, Chemistry, Math Level 2: 800/800\nAP English Language, English Literature, Chinese, World History, US Government, Biology, Chemistry, Physics 1, Physics C: Mechanics, Physics C: E&M, Calculus AB, Calculus BC: 5/5 (Advanced Placement (AP) = 美國大學先修課)\nUSA Biology Olympiad(USABO)Semifinalist(美國生物奧林匹亞準決賽入選者)\n\n文章吸引4千多位網友按讚,超狂的學經歷背景讓網友全看傻眼了,紛紛留言「這經歷是鬼吧,好猛」、「這個當家教太可惜了」、「哇賽我還不推爆」、「來看神仙」、「這是學霸王吧」、「怎麼不去打NCAA?」\n\n對此,楊承翰向《ETtoday新聞雲》表示,「我真的沒有想到徵學生的貼文會被受到那麼多關注。很謝謝大家給我的支持、鼓勵及建議,我也成功的找到好幾個合適的家教案件了。」\nhttps://i.imgur.com/xWRCeuo.jpg\nhttps://i.imgur.com/5An71PS.jpg\n\nhttps://www.ettoday.net/news/20210226/1926628.htm\n\n\n他會這麼高是遺傳+後天愛運動\n他爸183\n媽媽172\n基因強大👀\n\n另外這個學經歷收1500也很佛心\n台大的家教一小時大概800up\n醫學可以到1200~1500\n\n這樣應該算很勝利了?',
 'excerpt': '身高195公分的男大生楊承翰在家教社團PO文徵學生的文章被網友推爆了,網友們看到他的學經歷及成績不禁大讚根本就是學霸王,而他不只擁有高顏質,還是籃球系隊成員,超乎常人的學經歷及證書考試成績,瞬間讓網友',
 'anonymousSchool': False,
 'anonymousDepartment': True,
 'pinned': False,
 'forumId': 'd43f33f9-873f-46b3-9f24-38c90056b96c',
 'replyId': None,
 'createdAt': '2021-02-27T14:33:42.684Z',
 'updatedAt': '2021-02-27T19:20:43.811Z',
 'commentCount': 519,
 'likeCount': 5372,
 'tags': [],
 'topics': ['帥哥', 'SAT', 'Duke', '家教'],
 'supportedReactions': None,
 'withNickname': False,
 'reportReason': '',
 'hiddenByAuthor': False,
 'meta': {'layout': 'classic'},
 'forumName': '考試',
 'forumAlias': 'exam',
 'nsfw': False,
 'school': '國立臺灣大學',
 'replyTitle': None,
 'gender': 'F',
 'personaSubscriptable': True,
 'reactions': [{'id': '286f599c-f86a-4932-82f0-f5a06f1eca03', 'count': 5179},
  {'id': '011ead16-9b83-4729-9fde-c588920c6c2d', 'count': 94},
  {'id': '4b018f48-e184-445f-adf1-fc8e04ba09b9', 'count': 76},
  {'id': 'e8e6bc5d-41b0-4129-b134-97507523d7ff', 'count': 18},
  {'id': 'aa0d425f-d530-4478-9a77-fe3aedc79eea', 'count': 3},
  {'id': '514c2569-fd53-4d9d-a415-bf0f88e7329f', 'count': 2}],
 'hidden': False,
 'customStyle': None,
 'isSuspiciousAccount': False,
 'isModerator': False,
 'layout': 'classic',
 'spoilerAlert': False,
 'withImages': True,
 'withVideos': False,
 'media': [{'url': 'https://i.imgur.com/REIEzSd.jpg'},
  {'url': 'https://i.imgur.com/xWRCeuo.jpg'},
  {'url': 'https://i.imgur.com/5An71PS.jpg'}],
 'reportReasonText': '',
 'mediaMeta': [{'id': 'c4276c8c-f4b5-4c1d-82e8-56b1c26a4fd5',
   'url': 'https://i.imgur.com/REIEzSdl.jpg',
   'normalizedUrl': 'https://i.imgur.com/REIEzSdl.jpg',
   'thumbnail': 'https://i.imgur.com/REIEzSdl.jpg',
   'type': 'image/thumbnail',
   'tags': ['ANNOTATED'],
   'createdAt': '2021-02-27T14:34:57.354Z',
   'updatedAt': '2021-02-27T19:20:43.811Z',
   'width': 795,
   'height': 796},
  {'id': 'c4276c8c-f4b5-4c1d-82e8-56b1c26a4fd5',
   'url': 'https://i.imgur.com/REIEzSd.jpg',
   'normalizedUrl': 'https://imgur.com/REIEzSd',
   'thumbnail': 'https://i.imgur.com/REIEzSdl.jpg',
   'type': 'image/imgur',
   'tags': ['ANNOTATED'],
   'createdAt': '2021-02-27T14:34:57.354Z',
   'updatedAt': '2021-02-27T19:20:43.811Z',
   'width': 795,
   'height': 796},
  {'id': 'df8d763d-91c8-4384-a405-161bc606248a',
   'url': 'https://i.imgur.com/xWRCeuo.jpg',
   'normalizedUrl': 'https://imgur.com/xWRCeuo',
   'thumbnail': 'https://i.imgur.com/xWRCeuol.jpg',
   'type': 'image/imgur',
   'tags': ['ANNOTATED', 'POSSIBLY_UNSAFE', 'GOOGLE_VISION_ADULT_LIKELY'],
   'createdAt': '2021-02-27T14:34:57.354Z',
   'updatedAt': '2021-02-27T19:20:43.811Z',
   'width': 738,
   'height': 483},
  {'id': '72775c40-c99a-49f3-a7ac-a907484aa2fd',
   'url': 'https://i.imgur.com/5An71PS.jpg',
   'normalizedUrl': 'https://imgur.com/5An71PS',
   'thumbnail': 'https://i.imgur.com/5An71PSl.jpg',
   'type': 'image/imgur',
   'tags': ['ANNOTATED'],
   'createdAt': '2021-02-27T14:34:57.354Z',
   'updatedAt': '2021-02-27T19:20:43.811Z',
   'width': 451,
   'height': 791}],
 'excerptComments': [],
 'postAvatar': '',
 'verifiedBadge': False}
# 將抓下來的資料轉為DataFrame
ID = '235442609'
url = url = 'https://www.dcard.tw/_api/posts/' + ID
requ = requests.get(url)
rejs = requ.json()
pd.DataFrame(
    data=
    [{'ID':rejs['id'],
      'title':rejs['title'],
      'content':rejs['content'],
      'excerpt':rejs['excerpt'],
      'createdAt':rejs['createdAt'],
      'updatedAt':rejs['updatedAt'],
      'commentCount':rejs['commentCount'],
      'forumName':rejs['forumName'],
      'forumAlias':rejs['forumAlias'],
      'gender':rejs['gender'],
      'likeCount':rejs['likeCount'],
      'reactions':rejs['reactions'],
      'topics':rejs['topics']}],
    columns=['ID','title','content','excerpt','createdAt','updatedAt','commentCount','forumName','forumAlias','gender','likeCount','reactions','topics'])
ID title content excerpt createdAt updatedAt commentCount forumName forumAlias gender likeCount reactions topics
0 235442609 超狂學經歷!195公分帥家教徵學生 https://i.imgur.com/REIEzSd.jpg\n\n身高195公分的男大生... 身高195公分的男大生楊承翰在家教社團PO文徵學生的文章被網友推爆了,網友們看到他的學經歷及... 2021-02-27T14:33:42.684Z 2021-02-27T19:20:43.811Z 519 考試 exam F 5372 [{'id': '286f599c-f86a-4932-82f0-f5a06f1eca03'... [帥哥, SAT, Duke, 家教]
# 撰寫簡單的函數,透過輸入文章ID,就輸出文章的資料
def Crawl(ID):
    link = 'https://www.dcard.tw/_api/posts/' + str(ID)
    requ = requests.get(link)
    rejs = requ.json()
    return(pd.DataFrame(
        data=
        [{'ID':rejs['id'],
          'title':rejs['title'],
          'content':rejs['content'],
          'excerpt':rejs['excerpt'],
          'createdAt':rejs['createdAt'],
          'updatedAt':rejs['updatedAt'],
          'commentCount':rejs['commentCount'],
          'forumName':rejs['forumName'],
          'forumAlias':rejs['forumAlias'],
          'gender':rejs['gender'],
          'likeCount':rejs['likeCount'],
          'reactions':rejs['reactions'],
          'topics':rejs['topics']}],
        columns=['ID','title','content','excerpt','createdAt','updatedAt','commentCount','forumName','forumAlias','gender','likeCount','reactions','topics']))
# 嘗試使用撰寫出的函數,抓取編號231030181的文章
Crawl(235442609)
ID title content excerpt createdAt updatedAt commentCount forumName forumAlias gender likeCount reactions topics
0 235442609 超狂學經歷!195公分帥家教徵學生 https://i.imgur.com/REIEzSd.jpg\n\n身高195公分的男大生... 身高195公分的男大生楊承翰在家教社團PO文徵學生的文章被網友推爆了,網友們看到他的學經歷及... 2021-02-27T14:33:42.684Z 2021-02-27T19:20:43.811Z 519 考試 exam F 5372 [{'id': '286f599c-f86a-4932-82f0-f5a06f1eca03'... [帥哥, SAT, Duke, 家教]
import random, time
# 一次讀取100篇最熱門的文章
url = 'https://www.dcard.tw/_api/posts?popular=true&limit=100'
resq = requests.get(url)
rejs = resq.json()
df = pd.DataFrame()
for i in range(len(rejs)):
    wait_time = random.randint(3,10)
    time.sleep(wait_time)
    df = df.append(Crawl(rejs[i]['id']),ignore_index=True)
print(df.shape)
df
# 將資料存到桌面
df.to_excel('dcard.xlsx')
(100, 13)
# # 透過迴圈讀取10*100篇文章,若需讀取更多資料,可以將range(10)中的數值提升
# for j in range(2):
#     last = str(int(df.tail(1).ID)) # 找出爬出資料的最後一筆ID
#     url = 'https://www.dcard.tw/_api/posts?popular=true&limit=100&before=' + last
#     resq = requests.get(url)
#     rejs = resq.json()
#     for i in range(len(rejs)):
#         wait_time = random.randomint(3,10)
#         time.sleep(wait_time)
#         df = df.append(Crawl(rejs[i]['id']), ignore_index=True)
# print(df.shape)
# df
# 將資料存到桌面
# df.to_excel('dcard.xlsx')