【GitHub】實做 硬塞網 InsideJob 篩選器

【小工具】實做 硬塞網 InsideJob 篩選器

年關將近,不少人興起了找工作的念頭。

我個人愛看硬塞網的一些資訊,硬塞網也提供了一個找工作的平台Inside Job Board

 

但是,這年頭沒有個可以下條件的地方,感覺有點遜色了。

朋友也提出一樣的問題,所以,這篇文章誕生了。

 

雖然我昨天釋放出exe檔和上傳到GitHub中,但,猶豫了很久也研讀了一下關於法律問題的方面。

最終決定,完全撤離。依照Robots.txt,硬塞網並無不允許網路爬蟲,但,凡事說不定。

今日已經有寄信詢問硬塞網是否可以進行爬蟲行為了,若得到同意我還是會發佈。

 

在此之前,僅針對這樣的案例,來教學一下我怎麼達到我想要的目的。

需求:

  • 沒有任何主機存放資料
  • 抓取Inside Job的資料
  • 可以下條件判斷資料是否符合

想法:

  • 寫成Winform
  • 每次使用者可以設定要抓幾頁的資訊(畢竟太多也只是舊資料)
  • 有連結可以直接開瀏覽器到該職缺的網頁

準備技術:

  • 網頁爬蟲,這次用Html Agility Pack來實做。
  • Winform 技術,我非常少接觸Winform,大多還是用寫Webform的觀念下去寫。
  • DataTable.Filter

主要分成四個區塊:

  • 步驟一:資料建立:第一次使用者決定頁數後,讓爬蟲程式去撈資料回來,建立DataTable。
  • 步驟二:工作清單:在爬蟲抓完資料後,會自己跳到這裡,列出抓到的清單。點選連結可以直接開啟該職缺網頁。
  • 步驟三:資料篩選:可以做職缺、公司名稱、工作內容、工作地點、薪水範圍的篩選。
  • 步驟四:詳細資料:在工作清單列表中,點選工作名稱可以列出詳細資訊。

做完的成品圖:

1

2

3

4

 

======================以下切回技術面======================

第一個動作了解你要爬的網頁,網頁動向等。

已InsideJob為例,下方式他們的網址,多翻幾頁你會發現,最後的數字根本就是PageNum的參數。

http://jobs.inside.com.tw/jobs/page/2

所以,我們可以透過迴圈去抓取一頁又一頁的資料。

 

第二個動作,他們的資訊排列整齊,列表式,這種網頁也蠻好分析的。

第三就只差你要會用Html Agility Pack啦!這邊推薦一個MSDN教學文:簡單好用快速的HTML Parser

以下列出,我開始抓取網頁資料的程式碼:

int JobCount = 0; 
pgb1.Maximum = Convert.ToInt16(tbxCrawPage.Text.Trim()); 
DataTable oJobList = EmptyDataTable(); 
WebClient client = new WebClient(); 
string TargetUrl = oUrl + "/jobs/page/";


//這邊跑回圈看要抓幾頁 
for (int i = 1; i <= Convert.ToInt16(tbxCrawPage.Text.Trim()); i++) 
{ 
	//整段包Try其實不太好,包起來主要原因是client.DownloadData時,若Server回應500錯誤,就掛了。 
	try 
	{ 
		using (MemoryStream ms = new MemoryStream(client.DownloadData(TargetUrl + i.ToString()))) 
		{ 
			// 讀取 所有HTML HtmlAgilityPack.HtmlDocument 
			oHtml = new HtmlAgilityPack.HtmlDocument(); 
			oHtml.Load(ms, Encoding.UTF8); 
			
			// 載取 目標Table Html HtmlAgilityPack.HtmlDocument 
			HtmlContext = new HtmlAgilityPack.HtmlDocument(); 
			string oTargetHtml = oHtml.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/div[1]/div[1]/div[2]/div[1]/ul[1]").InnerHtml; 
			HtmlContext.LoadHtml(oTargetHtml); 
			
			//寫入每筆資料至Datatable 
			for (int j = 1; j <= HtmlContext.DocumentNode.SelectNodes("/li").Count; j++) 
			{ 
				Entity.JobEntity oJob = new Entity.JobEntity(); 
				
				//這樣寫可以直接抓到連結 
				oJob.Joblink = HtmlContext.DocumentNode.SelectSingleNode("/li[" + j + "]/a[1]").Attributes["href"].Value; 
				//這樣寫可以抓到裡面的文字 
				oJob.JobTitle = HtmlContext.DocumentNode.SelectSingleNode("/li[" + j + "]/a[1]/div[1]/h3[1]").InnerText; 
				
				DataRow oRow = oJobList.NewRow(); 
				oRow["SerNo"] = JobCount + 1; 
				oRow["JobTitle"] = oJob.JobTitle; 
				oRow["Joblink"] = oUrl + oJob.Joblink; 
				oJobList.Rows.Add(oRow); 
			} 
		} 
	} 
	catch 
	{ 
		continue; 
	} 
}


public static DataTable EmptyDataTable() 
{ 
	DataTable workTable = new DataTable("InsideJobDT"); 
	workTable.Columns.Add("SerNo", typeof(int)); 
	workTable.Columns.Add("JobTitle", typeof(String)); 
	
	//職缺名稱 
	workTable.Columns.Add("Joblink", typeof(String)); 
	
	//Inside連結            
	return workTable; 
}

其實抓網頁資料最麻煩的是剖析XPath,之前我用FireFox中的FireBug就可以直接指定元素,可以得到XPath。

1

但是,這次在抓的過程中,得到的XPath就是錯的(Div少一層),原因不明。

最後也是靠Html Agility Pack提供的軟體完成,軟體:HAP Explorer

程式碼中,我扣除了很多的欄位,畢竟這只是教學文。

解決上述,基本上工作清單的資料來源就有了。

我們看看資料設定這一段怎麼搞得吧!

DataView oDV = oJobList.DefaultView; 
string Filter = ""; 
if (!string.IsNullOrEmpty(tbxJobTitle.Text.Trim())) 
	Filter += " JobTitle like '%" + tbxJobTitle.Text.Trim() + "%' | "; 
	
if (!string.IsNullOrEmpty(tbxCompanyName.Text.Trim())) 
	Filter += " JobCompanyName like '%" + tbxCompanyName.Text.Trim() + "%' | "; 

if (!string.IsNullOrEmpty(tbxJobInfo.Text.Trim())) 
	Filter += " JobInfo like '%" + tbxJobInfo.Text.Trim() + "%' | "; 

if (!string.IsNullOrEmpty(tbxPayMin.Text.Trim())) 
	Filter += " JobPayMin >= " + tbxPayMin.Text.Trim() + " | "; 

oDV.RowFilter = Filter.Trim().TrimEnd('|').Replace("|", "and"); 

lblJobCount.Text = "共有" + oDV.Count.ToString() + "職缺"; 
gvResult.AutoGenerateColumns = false; 
gvResult.DataSource = oDV;

因為不知道會有幾個條件,所以用了一個小小技巧,透過TrimEnd把最後一個特殊符號去掉,再把特殊符號換成and。

取出詳細資料也是透過RowFilter來做,就不另外說明了。

最後,Winform 的DataGridView裡面,按下連結要開啟瀏覽器也是需要額外處裡。

類似webform 的 GridView 有RomCommand事件。

if (e.ColumnIndex == 8 && e.RowIndex >= 0) 
{ 
	string Link = Convert.ToString(gvResult.Rows[e.RowIndex].Cells[e.ColumnIndex].Value); 
	System.Diagnostics.Process.Start(Link); 
}

以上這些事情,應該已經足以打造這樣一隻程式了。

希望有一天,可以發佈完整程式供給有需要的大家使用。

謝謝!

20151129更新:

把程式放上GitHub,有興趣的人可以自行使用,網站資料為該網站所有,請勿用無惡意途徑上。

純屬交流&學習用,若有任何責任本人不予負責。

目前該網站版頁面有異動過,所以,XPath已經變更,若有需求請自行修改程式。

https://github.com/kkman021/InsideJobCrawlerAP