Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML

加入好友
加入社群
Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王
# -*- coding: utf-8 -*-
"""
Created on Sun Jan 21 23:00:08 2024

@author: SavingKing
"""

import requests
from bs4 import BeautifulSoup as bs

url = "https://www.104.com.tw/company/search?jobsource=index_cs"
response = requests.get(url)
#<Response [200]>

soup = bs(response.text)
"""
type(soup )
Out[77]: bs4.BeautifulSoup

type(response.text)
Out[78]: str
"""

code:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

soup:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

soup(由 BeautifulSoup 解析後的對象)和 response.text(從 requests 庫獲取的原始HTML文本)在本質上確實都與HTML格式相關,但它們之間存在幾個關鍵的區別:

response.text
這是通過HTTP請求(使用 requests 庫)從網頁URL獲取的原始HTML內容的字符串表示。
它是一個純文本字符串,包含了網頁的完整HTML代碼。
作為一個字符串,它不提供直接的方法來解析或操作HTML元素。
soup(BeautifulSoup 對象)
通過將 response.text 傳遞給 BeautifulSoup 構造函數,soup 變成了一個 BeautifulSoup 對象。
BeautifulSoup 對象表示的是一個解析後的文檔,它提供了許多方法和屬性來搜索和操作HTML文檔的結構。這意味著您可以方便地根據標簽名、屬性等來找到感興趣的HTML元素。
與 response.text 的純文本不同,soup 使得HTML內容變得像一個可遍歷和可操作的對象。您可以使用它的方法,如 find(), find_all(), select() 等,來提取或修改文檔的特定部分。
簡而言之,response.text 是從網頁獲取的未加工的HTML字符串,而 soup 是這個HTML字符串被 BeautifulSoup 解析後的對象,提供了豐富的API來使得HTML文檔的遍歷和操作更為簡單和直觀。這種轉換使得從HTML文檔中提取數據變得更加容易和高效。

推薦hahow線上學習python: https://igrape.net/30afN

Chrome瀏覽器
ctrl + shift +I
可以檢視網頁原始碼
做元素比對

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

放大HTML:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

注意一頁中的每一個職缺資料,
標籤開頭都是
article class="b-block--top-bord job-list-item b-clearfix js-job-item"
find_all() 中的參數
就是依據這個標籤
result_set = soup.find_all("article", class_="b-block--top-bord job-list-item b-clearfix js-job-item")
#class 是python的關鍵字
因此用class_與關鍵字區別
find_all() 中
class_是外露的參數名稱
所以需要多加一個底線,
避免跟python關鍵字衝突
select()中,
class被包在字串的單引號中
(雙引號被屬性值用掉)
所以不需要避免跟python關鍵字衝突
find_all() 中,
除了手動幫class多加一個底線
都是從HTML中複製貼上
會比select更直觀

code:

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 21 23:00:08 2024

@author: SavingKing
"""

import requests
from bs4 import BeautifulSoup as bs

headers = {
    'User-Agent': 
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}

url = "https://www.104.com.tw/jobs/search/?ro=0&keyword=Python&expansionType=area%2Cspec%2Ccom%2Cjob%2Cwf%2Cwktm&area=6001005000&order=15&asc=0&page=1&mode=s&jobsource=tab_cs_to_job&langFlag=0&langStatus=0&recommendJob=1&hotJob=1"
response = requests.get(url,headers=headers)
"""
#<Response [200]>
response.status_code
Out[30]: 200
"""

soup = bs(response.text,features="lxml")
"""
type(soup )
Out[77]: bs4.BeautifulSoup

type(response.text)
Out[78]: str
"""
result_set = soup.find_all("article",
class_="b-block--top-bord job-list-item b-clearfix js-job-item")
#bs4.element.ResultSet
print(result_set[0].prettify())
"""
type(result_set[0])
Out[118]: bs4.element.Tag
"""
tag0 = result_set[0]

result_set = soup.find_all(“article”,class_=”b-block–top-bord job-list-item b-clearfix js-job-item”)
#bs4.element.ResultSet
result_set是像list的BeautifulSoup實例

tag0 = result_set[0]
tag0的type為bs4.element.Tag
print(tag0.prettify()) #兩個t,不要拼錯
部分內容如下:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

分別使用find_all() 與 select
取出標記起來的bs4.element.Tag:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

.find_all() 與 .select()

soup.find_all("div",class_="job-list-tag b-content")
soup.select("div.job-list-tag.b-content")

.find_all() 與 .select()
使用不一樣的下參數方法
返回一樣的ResultSet:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

在使用BeautifulSoup的.select()方法時,它允許使用CSS選擇器來定位元素。當使用.來連接時,它特指元素的class屬性。這是因為在CSS中,.被用來選擇具有特定類名的元素。因此,當你使用.select(“div.job-list-tag.b-content”)時,它會查找所有div元素,這些元素同時擁有job-list-tag和b-content這兩個類名。

如果你想通過BeautifulSoup的.select()方法基於其他屬性來選擇元素,你需要使用不同的語法。例如,如果你想選擇具有特定id屬性的元素,你可以使用#符號,因為在CSS中,#符號用於選擇具有特定id的元素。

對於其他屬性,你可以使用方括號[]來指定。例如,如果你想選擇具有attribute屬性且屬性值為value的元素,可以這樣寫:

soup.select('[attribute="value"]')
#標籤名稱都要的話:
soup.select('div[class="job-list-tag b-content"]')

因為屬性名稱剛好是class,
使用select,參數可以使用.連接
等效於:

soup.select('div.job-list-tag.b-content')

總結一下:

使用.連接的是類名(class屬性)。
使用#連接的是ID(id屬性)。
使用[]可以指定其他屬性及其值

.find() 與.find_all() or.select()
內容幾乎一樣,
只差最外層少了一個中括號[]
因為.find()返回的是 bs4.element.Tag
.find_all() or.select()返回的是
bs4.element.ResultSet (像list)
取其中index 0的bs4.element.Tag
tag0.find_all(“div”,class_=”job-list-tag b-content”)[0] ==
tag0.find(“div”,class_=”job-list-tag b-content”)
會返回True

推薦hahow線上學習python: https://igrape.net/30afN

從tag0中撈出
職稱,網址,公司名,公司地址
再看一次tag0的html:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

code:

tag0 = result_set[0]

job = tag0.a.text 
#'Python 工程師'

job_href = tag0.a["href"]
#'//www.104.com.tw/job/7xykm?jobsource=tab_cs_to_job'

company,address=tag0.find_all("a")[1]["title"].split("\n")
#'公司名:旻新科技股份有限公司', '公司住址:桃園市中壢區新生路562-1號1樓'

輸出結果:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

目前已經可以抓下一整頁資料
輸出為excel
code:

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 21 23:00:08 2024

@author: SavingKing
"""

import requests
from bs4 import BeautifulSoup as bs
import time

headers = {
    'User-Agent': 
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
page=1
url = f"https://www.104.com.tw/jobs/search/?ro=0&keyword=Python&expansionType=area%2Cspec%2Ccom%2Cjob%2Cwf%2Cwktm&area=6001005000&order=15&asc=0&page={page}&mode=s&jobsource=tab_cs_to_job&langFlag=0&langStatus=0&recommendJob=1&hotJob=1"

response = requests.get(url,headers=headers)
"""
#<Response [200]>
response.status_code
Out[30]: 200
"""

soup = bs(response.text,features="lxml")
"""
type(soup )
Out[77]: bs4.BeautifulSoup

type(response.text)
Out[78]: str
"""
result_set = soup.find_all("article",class_="b-block--top-bord job-list-item b-clearfix js-job-item")
#bs4.element.ResultSet
print(result_set[0].prettify())
"""
type(result_set[0])
Out[118]: bs4.element.Tag
"""
tag0 = result_set[0]
tag1 = result_set[1]

def tag2tup_info(tag0):
    job = tag0.a.text 
    #'Python 工程師'
    
    job_href = tag0.a["href"]
    #'//www.104.com.tw/job/7xykm?jobsource=tab_cs_to_job'
    
    company,address=tag0.find_all("a")[1]["title"].split("\n")
    #'公司名:旻新科技股份有限公司', '公司住址:桃園市中壢區新生路562-1號1樓'
    tup=(job,job_href,company,address)
    return tup
tup = tag2tup_info(tag0)
print(tup)

def get_salary(tag1):
    if "待遇面議" in str(tag1):
        salary = "待遇面議"
    else:
        salary = tag1.find_all("a")[2].text
    return salary

import pandas as pd
def get_1page_info(result_set):
    lis_info = []
    for tag in result_set:
        tup = tag2tup_info(tag)
        salary = get_salary(tag)
        tup2 = tup + (salary,)
        lis_info.append(tup2)
    df_info = pd.DataFrame(lis_info,columns=["職缺","網址", "公司","地址","待遇"])
    return lis_info,df_info

pd.set_option('display.max_columns', None)
lis_info,df_info = get_1page_info(result_set)
#已經成功抓完一頁的資料了
timestamp = time.time()
localtime = time.localtime(timestamp)
strftime = time.strftime("%y%m%d_%H%M%S",localtime) 
#'240126_234705'
df_info_xlsx = "df_info_"+strftime+".xlsx"
df_info.to_excel(df_info_xlsx)

for tup in lis_info:
    print(tup)

輸出的df_info_240127_075351.xlsx:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

推薦hahow線上學習python: https://igrape.net/30afN

將程式放進去while迴圈中,
page+=1
直到網站沒有資料為止
function則移出迴圈之外,
以免每次迴圈都重新定義function

code:

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 21 23:00:08 2024

@author: SavingKing
"""

import requests
from bs4 import BeautifulSoup as bs
import time
import pandas as pd

# tag0 = result_set[0]
# tag1 = result_set[1]

def tag2tup_info(tag0):
    job = tag0.a.text 
    #'Python 工程師'
    
    job_href = tag0.a["href"]
    #'//www.104.com.tw/job/7xykm?jobsource=tab_cs_to_job'
    
    company,address=tag0.find_all("a")[1]["title"].split("\n")
    #'公司名:旻新科技股份有限公司', '公司住址:桃園市中壢區新生路562-1號1樓'
    tup=(job,job_href,company,address)
    return tup
# tup = tag2tup_info(tag0)
# print(tup)

def get_salary(tag1):
    if "待遇面議" in str(tag1):
        salary = "待遇面議"
    else:
        salary = tag1.find_all("a")[2].text
    return salary


def get_1page_info(result_set):
    lis_info = []
    for tag in result_set:
        tup = tag2tup_info(tag)
        salary = get_salary(tag)
        tup2 = tup + (salary,)
        lis_info.append(tup2)
    df_info = pd.DataFrame(lis_info,columns=["職缺","網址", "公司","地址","待遇"])
    return lis_info,df_info

headers = {
    'User-Agent': 
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}
    
lis_df = []
page=1

while True:
    url = f"https://www.104.com.tw/jobs/search/?ro=0&keyword=Python&expansionType=area%2Cspec%2Ccom%2Cjob%2Cwf%2Cwktm&area=6001005000&order=15&asc=0&page={page}&mode=s&jobsource=tab_cs_to_job&langFlag=0&langStatus=0&recommendJob=1&hotJob=1"
    print(f"目前正要抓取Page{page}資料")
    response = requests.get(url,headers=headers)
    """
    #<Response [200]>
    response.status_code
    Out[30]: 200
    """
    print("response.status_code:\t",response.status_code)
    
    soup = bs(response.text,features="lxml")
    """
    type(soup )
    Out[77]: bs4.BeautifulSoup
    
    type(response.text)
    Out[78]: str
    """
    result_set = soup.find_all("article",class_="b-block--top-bord job-list-item b-clearfix js-job-item")
    #bs4.element.ResultSet
    # print(result_set[0].prettify())
    """
    type(result_set[0])
    Out[118]: bs4.element.Tag
    """
    if result_set == []:
        break
    
    lis_info,df_info = get_1page_info(result_set)
    #已經成功抓完一頁的資料了
    lis_df.append(df_info)
    
    page+=1


pd.set_option('display.max_columns', None)
timestamp = time.time()
localtime = time.localtime(timestamp)
strftime = time.strftime("%y%m%d_%H%M%S",localtime) 
# #'240126_234705'
df_all = pd.concat(lis_df, axis="index").reset_index(drop=True)


xlsx = "df_all_"+strftime+".xlsx"
df_all.to_excel(xlsx)
print("資料已經輸出到:\n",xlsx)
# for tup in lis_info:
#     print(tup)

輸出的xlsx:

Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

推薦hahow線上學習python: https://igrape.net/30afN

加入好友
加入社群
Python爬蟲: 理解 response.text 與 BeautifulSoup 對象之間的關鍵區別 from bs4 import BeautifulSoup as bs ; response = requests.get(url) ; soup = bs(response.text) ; bs4.element.Tag .find_all() ; .select() ; .find() 差別為何?soup是大HTML, tag是小HTML - 儲蓄保險王

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡

You may also like...

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *