python-爬取104人力銀行的職缺訊息

python-爬取104人力銀行的職缺訊息

(一).印出職缺內容

首先先以Google Chrome連到104人力銀行網站,隨意搜尋關鍵字,我先舉搜尋’Python’為例子。
接著網頁會加載搜尋到有關Python的職缺,按下F12進入開發者模式。

對著各個職缺名稱點選右鍵->檢查,會跳出該職缺內容的路徑。

我們知道,所有職缺的子標籤都是在<div id=”js-job-content”>的標籤裡,而每個子標籤都叫做<article class=”js-job-item”>,這些資訊即可爬取個職缺內容囉。

我只想要知道各個職缺名稱、公司名稱、地址、薪資、網址。
職缺名稱在data-job-name裡 ,也在<a>標籤的class”js-job-link”裡
公司名稱在data-cust-name裡
地址在<ul>標籤的class=”job-list-intro”的<li>標籤裡
薪資在<span>標籤的class=”b-tag–default:裡
網址在<a>標籤的href裡

程式碼如下:

#印出各個職缺內容
import requests
import bs4

url = 'https://www.104.com.tw/jobs/search/?keyword=python&order=1&jobsource=2018indexpoc&ro=0'
htmlFile = requests.get(url)
ObjSoup=bs4.BeautifulSoup(htmlFile.text,'lxml')
jobs = ObjSoup.find_all('article',class_='js-job-item')             #搜尋所有職缺

for job in jobs:
    print(job.find('a',class_="js-job-link").text)                  #職缺內容
    print(job.get('data-cust-name'))                                #公司名稱
    print(job.find('ul', class_='job-list-intro').find('li').text)  #地址
    print(job.find('span',class_='b-tag--default').text)            #薪資
    print(job.find('a').get('href'))                                #網址
    print('='*70)

執行結果:

(二)資料存取,將爬取資料存成csv檔

光是印出職缺內容還不夠,我希望能存成CSV格式,使用EXCEL來搜尋比較方便。
這裡我使用CSV方式來做資料存取的動作。
程式碼如下:

#將各個職缺內容存到csv檔
import requests
import bs4
import csv
url = 'https://www.104.com.tw/jobs/search/?keyword=python&order=1&jobsource=2018indexpoc&ro=0'
htmlFile = requests.get(url)
ObjSoup=bs4.BeautifulSoup(htmlFile.text,'lxml')
jobs = ObjSoup.find_all('article',class_='js-job-item')                     #搜尋所有職缺

fn='104人力銀行職缺內容.csv'                                                 #取CSV檔名
columns_name=['職缺內容','公司名稱','地址','薪資','網址']                     #第一欄的名稱
with open(fn,'w',newline='',) as csvFile:                                   #定義CSV的寫入檔,並且每次寫入完會換下一行
    dictWriter = csv.DictWriter(csvFile,fieldnames=columns_name)            #定義寫入器
    dictWriter.writeheader()
    
    for job in jobs:
        job_name=job.find('a',class_="js-job-link").text                    #職缺內容
        job_company=job.get('data-cust-name')                               #公司名稱
        job_loc=job.find('ul', class_='job-list-intro').find('li').text     #地址
        job_pay=job.find('span',class_='b-tag--default').text               #薪資
        job_url=job.find('a').get('href')                                   #網址
        
        dictWriter.writerow({'職缺內容':job_name,'公司名稱':job_company,
                            '地址':job_loc,'薪資':job_pay,'網址':job_url})

執行結果:
會跑出一個104人力銀行職缺內容.csv檔案

這樣子我們就完成資料的存取囉!

(三)連續爬取多頁,並存成CSV檔

讀者可能會發現,明明還有好幾頁,為什麼只存第一頁的職缺資料而已。
當你試著在網站上往下滾輪到底,網站會自動載入第二頁的職缺內容,這是使用了Ajax的加載技術。觀察網址發現,網址會自動變成含有page=2,所以我們知道,如果要爬取下一頁的資訊,只需要把這個跑出來的網址宣告給url參數就好了。
因為會大量搜尋網站上的資料,故每一次換頁時需加上等待時間time.sleep()較佳。
現在筆者試著把取前5頁的職缺資訊
程式碼如下:

#爬取5頁的職缺內容,將各個職缺內容存到csv檔
import requests
import bs4
import csv
import random,time
url_A ='https://www.104.com.tw/jobs/search/?ro=0&kwop=7&keyword=python&order=15&asc=0&page='
url_B = '&mode=s&jobsource=2018indexpoc'

all_job_datas=[]
for page in range(1,5+1):
    url = url_A+str(page)+url_B
    print(url)
    htmlFile = requests.get(url)
    ObjSoup=bs4.BeautifulSoup(htmlFile.text,'lxml')
    jobs = ObjSoup.find_all('article',class_='js-job-item')                 #搜尋所有職缺  
       
    for job in jobs:
        job_name=job.find('a',class_="js-job-link").text                    #職缺內容
        job_company=job.get('data-cust-name')                               #公司名稱
        job_loc=job.find('ul', class_='job-list-intro').find('li').text     #地址
        job_pay=job.find('span',class_='b-tag--default').text               #薪資
        job_url=job.find('a').get('href')                                   #網址
        job_data={'職缺內容':job_name,'公司名稱':job_company,
                         '地址':job_loc,'薪資':job_pay,'網址':job_url}
        all_job_datas.append(job_data)
    time.sleep(random.randint(1,3))


fn='104人力銀行職缺內容共5頁.csv'                                             #取CSV檔名
columns_name=['職缺內容','公司名稱','地址','薪資','網址']                     #第一欄的名稱
with open(fn,'w',newline='') as csvFile:               #定義CSV的寫入檔,並且每次寫入完會換下一行
    dictWriter = csv.DictWriter(csvFile,fieldnames=columns_name)            #定義寫入器
    dictWriter.writeheader()       
    for data in all_job_datas:
        dictWriter.writerow(data)
8 comments Add yours
  1. 落葉大你好,我想將職缺內容一起寫入csv中但卻遇到亂碼的問題
    —————————————————
    [加入職缺內容的選項,報錯UnicodeEncodeError: ‘cp950’ 然後csv中職缺內容空白]
    job_name=job.find(‘a’,class_=”js-job-link”).text #職缺內容
    job_company=job.get(‘data-cust-name’) #公司名稱
    job_loc=job.find(‘ul’, class_=’job-list-intro’).find(‘li’).text #地址
    job_pay=job.find(‘span’,class_=’b-tag–default’).text #薪資
    job_des=job.find(‘P’,class_=’job-list-item__info b-clearfix b-content’) #職缺內容 (新增)
    job_url=job.find(‘a’).get(‘href’) #網址
    job_data={‘職缺內容’:job_name,’公司名稱’:job_company,
    ‘地址’:job_loc,’薪資’:job_pay,’內容’:job_des,’網址’:job_url}
    all_job_datas.append(job_data)
    time.sleep(random.randint(1,3))

    [網路查到 加入指定編碼utf-8後,轉出的csv雖有讀到職缺內容,但都是亂碼]
    with open(fn,’w’,newline=”,encoding=’utf-8′) as csvFile:
    #定義CSV的寫入檔,並且每次寫入完會換下一行 (加入編碼成utf-8)

    [透過excel修正編碼導入本亂碼csv,資料正常顯示,但職缺內容卻全部消失(原本有…)]
    —————————————————
    實在不太懂為什麼,請問能否指點一下關於職缺內容的爬取我是否漏掉甚麼地方,或是可以指點關鍵字,謝謝!

    1. 仍在學習的大蟒蛇小白 您好:
      這個問題我也有碰過。
      似乎某些字是要存成csv時,編碼轉換的問題。

      我重新再run過一次程式,錯誤碼為
      UnicodeEncodeError: ‘cp950’ codec can’t encode character ‘\u5f63’ in position 48: illegal multibyte sequence
      其中這個\u5f63 轉譯成中文為” 彣 ”

      在寫成CSV時,請將with open 改成如下:
      with open(fn,’w’,newline=”,encoding=’utf_8_sig′) as csvFile:

      其中這個encoding=’utf_8_sig′ 可以把困難的中文字給顯示出來。
      其原理請看我找的網站
      https://www.itread01.com/content/1543553103.html
      希望能夠解決您的問題~!

    1. 感謝你的支持~~
      不過之後我可能比較不會再寫python相關文章囉……
      因為有其他想做的事情要做!!

      祝你學習順利!

  2. 落葉大您好 我在使用您的程式碼的時候發現錯誤
    AttributeError: ‘NoneType’ object has no attribute ‘text’
    薪資如果爬蟲爬下來 他只要是月薪30,000~40,000元 那他就會回傳NONE值
    但如果是待遇面議的話他就不會出現問題
    如果我想要讓他都正常跑出來的話我需要做什麼修改

    1. wu您好:
      job_pay的搜尋標籤似乎有變更,以前直接搜尋span下的class_=’b-tag–default 可以正常搜尋到。
      但是現在薪資那個語法位置有時候會變成在div底下。
      因此將job_pay那一段改成:
      job_pay=job.find(‘div’,class_=’job-list-tag b-content’).find(class_=’b-tag–default’).text
      這樣應該可以正常找到並且成功寫入job_data裡。

      另外執行程式、在存成csv時,你可能會發現UnicodeEncodeError: ‘big5’ codec can’t encode character ‘\u6ed9′ in position 10: illegal multibyte sequence 的錯誤
      只需要在with open(fn,’w’,newline=”) as csvFile: 這行程式碼改成如下:
      with open(fn,’w’,newline=”, encoding=’utf_8_sig’) as csvFile: 即可

發佈留言

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