iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 10
1
AI & Data

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

【Day 9】蒐集 iT 邦幫忙的技術文章 (2/6) - 使用好維護的選擇器

  • 分享至 

  • xImage
  •  

大家還記得昨天的落落長選擇器嗎?

html > body > div > div.row > div.col-md-12.clearfix > div.leftside > div.board.tabs-content > div.qa-list > div.qa-list__content > h3.qa-list__title > a.qa-list__title-link

這樣的選擇器會讓開發者(很有可能是正在看文章的你)在除錯的時候很難發現問題,而且一旦網站調整了中間某個地方的樣式,選擇器就會失效。所以我們今天就來練習怎麼樣使用比較友善的選擇器吧!

了解目標網站的結構

絕大多數的網站在設計 CSS 時都是有跡可循的,我們可以藉由觀察來了解每個選擇器對應的網站區塊。

  • div.leftside 對應到畫面中左邊的區塊

https://ithelp.ithome.com.tw/upload/images/20190924/20107875CBnf8XUM0p.png

  • div.board.tabs-content 對應到文章列表的區塊

https://ithelp.ithome.com.tw/upload/images/20190924/20107875roBeB91ed2.png

  • div.qa-list 對應到一列文章資訊的區塊

https://ithelp.ithome.com.tw/upload/images/20190924/20107875znDQISJj9i.png

  • div.qa-list__content 對應到文章主要資訊的區塊

https://ithelp.ithome.com.tw/upload/images/20190924/20107875PYRWqQIKEF.png

  • h3.qa-list__title 對應到文章標題的區塊

https://ithelp.ithome.com.tw/upload/images/20190924/20107875UohBBIVjd2.png

  • a.qa-list__title-link 對應到文章標題連結的區塊

https://ithelp.ithome.com.tw/upload/images/20190924/20107875SuAPs9dlcI.png

只要能找出爬取目標對應的選擇器,就可以直接以對應的選擇器來取得目標資料了。

使用不同的選擇器

了解網站結構後,可以試著調整原本那一長串選擇器。例如要找出全部文章標題,可以用這樣的選擇器:

div.qa-list > div.qa-list__content > h3.qa-list__title > a.qa-list__title-link

或者最短的,直接使用文章標題連結的選擇器:

a.qa-list__title-link

但如果使用到這麼簡短的選擇器,要確認一下網頁中有沒有其他「剛好」使用相同選擇器的區塊,最快能確認的方式當然是寫個程式來試試看囉!

import requests
from bs4 import BeautifulSoup

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

title_tags_1 = soup.select('html > body > div > div.row > div.col-md-12.clearfix > div.leftside > div.board.tabs-content > div.qa-list > div.qa-list__content > h3.qa-list__title > a.qa-list__title-link')
titles_1 = [tag.text for tag in title_tags_1]

title_tags_2 = soup.select('div.qa-list > div.qa-list__content > h3.qa-list__title > a.qa-list__title-link')
titles_2 = [tag.text for tag in title_tags_2]

title_tags_3 = soup.select('a.qa-list__title-link')
titles_3 = [tag.text for tag in title_tags_3]

print(titles_1 == titles_2 and titles_2 == titles_3)

https://ithelp.ithome.com.tw/upload/images/20190924/20107875QxYXvI2n63.png

還記得在 Day 5 學到的另一種搜尋 HTML 結構的方法嗎?其實我個人是比較常用那種方式,覺得閱讀起來比 CSS 選擇器還要容易。把前面的程式改成另一種方式的話是這樣:

import requests
from bs4 import BeautifulSoup

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

# 先找到文章區塊
article_tags = soup.find_all('div', class_='qa-list')

for article_tag in article_tags:
    # 再由每個區塊去找文章連結
    title_tag = article_tag.find('a', class_='qa-list__title-link')
    print(title_tag.text)

https://ithelp.ithome.com.tw/upload/images/20190924/201078754TMMHVnOQo.png

比較不一樣的地方是,這邊有先把文章區塊給抓出來,再跑一個迴圈從每個文章區塊往下找到文章標題連結。是因為過去常常需要這個區塊內的其他資訊(例如瀏覽數、發文時間),定位在外層的區塊可以方便從相同的位置往下找到其他資訊。

我們現在可以找出「第一頁」全部的文章標題了,但如果想要看到後面幾頁的文章怎麼辦?明天就會嘗試在程式裡換頁囉!


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

1 則留言

0
阿寶哥
iT邦新手 5 級 ‧ 2023-01-01 11:35:38

最後1支程式如下"直接定位到文章連結"不是更簡潔些嗎?

article_tags = soup.find_all('a', class_ = 'qa-list__title-link')

for article_tag in article_tags:
    print(article_tag.text)

Sorry!沒注意到"因為過去常常需要這個區塊內的其他資訊"這句話。

我要留言

立即登入留言