python 爬蟲 爬取 learnku 精華文章

GA17發表於2020-04-17

繼上篇文章 使用 requests 登入 learnku 的基礎上,爬 learnku python 社群的精華文章。

python 社群精華文章列表連結為 https://learnku.com/python?filter=excellen...

老規矩,開啟連結後 F12 開啟開發者模式。點選開發者模式選擇節點那個箭頭,隨便點選一個文章的標題。

可以看到文章的 url 在一個 class 為 topic-title-wrap rm-tdu 的 a 標籤裡面,標題在這個a 標籤的第一個子節點 span 標籤裡面, span 標籤的 class 為 topic-title

接上上篇文章的程式碼

from lxml import etree
import requests


# 定義一個會話, 維持cookie
s = requests.Session()

headers = {
    'Host': 'learnku.com',
    'User-Agent': '你的UA'
}
# 更新會話的請求頭
s.headers.update(headers)

# 請求 learnku,拿 token。這裡其實還得到了首頁的 cookie。
response = s.get('https://learnku.com/')
html = etree.HTML(response.text)
# 解析 learnku 首頁拿到 token
token = html.xpath('//meta[@name="csrf-token"]/@content')

# 定義登入要提交的資料
payload = {
    '_token': token,
    'remember': 'yes',
    'return_back': 'yes',
    'username': '賬號',
    'password': '密碼'
}
# 請求登入
s.post('https://learnku.com/auth/login', data=payload)

# 請求精華文章
url = 'https://learnku.com/python?filter=excellent'
response = s.get(url)
html = etree.HTML(response.text)

# 定位頁面裡面包含標題的 a 標籤
lis = html.xpath('//a[@class="topic-title-wrap rm-tdu"]')

# 遍歷這些 a 標籤
for li in lis:
    essay_url = li.xpath('./@href')[0]
    title = li.xpath('./span[@class="topic-title"]/text()')[0]

這樣就可以獲取文章的連結和標題啦。但是,我發現了文章裡面的文字被標籤分隔開,這樣提取比較麻煩,而且如果有圖片的話很難弄出來,就算弄出來文章整體也不好看。這個時候我突然想到,可以點那個改進的功能,裡面的文章是 Markdown 格式的。

原本文章連結為 部落格:python 爬蟲 爬取酷狗音樂
改進文章連結為 https://learnku.com/topics/42536/patches/c...
可以發現,數字那個為文章的ID。

所以我們要把文章連結的 ID 提取出來變為改進文章的連結
然後請求改進文章的連結

from lxml import etree
import requests

# 中間部分程式碼省略
for li in lis:
    essay_url = li.xpath('./@href')[0]
    ID = essay_url[essay_url.rfind('/')+1:]
    modify_url = 'https://learnku.com/topics/{}/patches/create'.format(ID)
    title = li.xpath('./span[@class="topic-title"]/text()')[0]
    # 請求改進文章
    response = s.get(modify_url)

在改進文章的頁面如果繼續使用開發者模式定位的話,就會發現,請求到的 html 裡面沒有這個元素,我猜測開發者模式看到的是由 JS 渲染出來的。於是我儲存下請求的資料為 html 檔案,搜尋文章的部分詞語,發現文章是在一個 name 為 body 的 textarea 標籤下。

拿到文章內容就可以存起來啦。

from lxml import etree
import requests

# 中間部分程式碼省略
for li in lis:
    essay_url = li.xpath('./@href')[0]
    ID = essay_url[essay_url.rfind('/')+1:]
    modify_url = 'https://learnku.com/topics/{}/patches/create'.format(ID)
    title = li.xpath('./span[@class="topic-title"]/text()')[0]
    # 請求改進文章
    response = s.get(modify_url)
    # 儲存文章
    with open('{}.html'.format(title), 'wb') as f:
        f.write(response.content)
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章