public async Task <JobListResultDto> SearchAsync(GetJobsInput input) { var cityCode = CityCodeDictionary.Get(JobSource.智联招聘, input.City); var request = new RestRequest(); request.AddParameter("kt", 3); request.AddParameter("kw", input.Keyword); request.AddParameter("cityId", cityCode); var pageSize = input.PageSize; request.AddParameter("start", (input.PageIndex - 1) * pageSize); request.AddParameter("pageSize", pageSize); try { var response = await _client.ExecuteGetTaskAsync <dynamic>(request); dynamic responseData = JObject.Parse(response.Content); var jobList = responseData.data.results; var jobs = new List <JobDto>(); foreach (var item in jobList) { var job = new JobDto { Position = item.jobName, Company = item.company.name, Salary = item.salary, Address = item.city.display, PublishedTime = item.updateDate, Education = item.eduLevel.name, Url = item.positionURL, WorkingYears = item.workingExp.name }; jobs.Add(job); } long totalCount = responseData.data.numTotal; return(new JobListResultDto(jobs, totalCount)); } catch (Exception e) { _logger.LogException(e); throw new BusinessException("Zhilian_001", e.Message, e.StackTrace, e.InnerException); } }
public async Task <JobListResultDto> GetJobsAsync(GetJobsInput input) { var cacheKey = $"Job@{input.Keyword?.Trim().ToLower()}@{input.City}@{input.JobSource}@{input.PageIndex}@{input.PageSize}"; var output = await JobListCache.GetOrAddAsync( cacheKey, factory : async() => { JobListResultDto jobList; switch (input.JobSource) { case JobSource.智联招聘: jobList = await _zhilianJobSearcher.SearchAsync(input); break; case JobSource.前程无忧: jobList = await _qianchengJobSearcher.SearchAsync(input); break; case JobSource.猎聘招聘: jobList = await _liepinJobSearcher.SearchAsync(input); break; case JobSource.Boss招聘: jobList = await _bossJobSearcher.SearchAsync(input); break; case JobSource.拉钩招聘: jobList = await _lagouJobSearcher.SearchAsync(input); break; default: throw new ArgumentOutOfRangeException(); } jobList.CacheKey = cacheKey; return(jobList); }, optionsFactory : () => new DistributedCacheEntryOptions { //TODO: 应该是可配置的 AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(2), SlidingExpiration = TimeSpan.FromMinutes(30) } ); return(output); }
public async Task <JobListResultDto> SearchAsync(GetJobsInput input) { var cityCode = CityCodeDictionary.Get(JobSource.Boss招聘, input.City); var request = new RestRequest(); //request.AddParameter("salary", "*"); //TODO: 实现自定义 request.AddParameter("query", input.Keyword); request.AddParameter("city", cityCode); request.AddParameter("page", input.PageIndex); request.AddParameter("pageSize", input.PageSize); input.PageSize = 30; //固定的 PageSize try { var response = await _client.ExecuteGetTaskAsync <dynamic>(request); var htmlString = response.Content; var htmlParser = new HtmlParser(); var document = htmlParser.ParseDocument(htmlString); var jobInfoElements = document.QuerySelectorAll(".job-list ul li"); var jobs = jobInfoElements.Select(t => { var dto = new JobDto { Position = t.QuerySelector(".job-title").TextContent.Trim(), Company = t.QuerySelector(".company-text a").TextContent, Salary = t.QuerySelector(".red").TextContent, Address = t.QuerySelector(".info-primary p").InnerHtml.Split("<em class=\"vline\"></em>")[0], PublishedTime = t.QuerySelector(".info-publis p").TextContent, Education = t.QuerySelector(".info-primary p").InnerHtml.Split("<em class=\"vline\"></em>")[2], Url = "http://www.zhipin.com" + t.QuerySelector(".company-text a").Attributes["href"]?.Value, WorkingYears = t.QuerySelector(".info-primary p").InnerHtml.Split("<em class=\"vline\"></em>")[1] }; return(dto); }).ToList(); long.TryParse(document.QuerySelector(".job-tab").Attributes["data-rescount"]?.Value, out var totalCount); return(new JobListResultDto(jobs, totalCount)); } catch (Exception e) { _logger.LogException(e); throw new BusinessException("Boss_001", e.Message, e.StackTrace, e.InnerException); } }
public async Task <JobListResultDto> SearchAsync(GetJobsInput input) { var cityCode = CityCodeDictionary.Get(JobSource.前程无忧, input.City); var request = new RestRequest(); //request.AddParameter("salary", "*"); //TODO: 实现自定义 request.AddParameter("keyword", input.Keyword); request.AddParameter("jobarea", cityCode); request.AddParameter("curr_page", input.PageIndex); request.AddParameter("pageSize", input.PageSize); input.PageSize = 50; // 前程无忧固定的 PageSize try { var response = await _client.ExecuteGetTaskAsync <dynamic>(request); var htmlString = Encoding.GetEncoding("GBK").GetString(response.RawBytes); var htmlParser = new HtmlParser(); var document = htmlParser.ParseDocument(htmlString); var jobInfoElements = document.QuerySelectorAll(".dw_table div.el") .Where(t => t.QuerySelector(".t1 span a") != null); var jobs = jobInfoElements.Select(t => new JobDto { Position = t.QuerySelector(".t1 span a").TextContent.Trim(), Company = t.QuerySelector(".t2 a").TextContent, Salary = t.QuerySelector(".t4").TextContent, Address = t.QuerySelector(".t3").TextContent, PublishedTime = t.QuerySelector(".t5").TextContent, //Education = t.QuerySelector(".edu").TextContent, Url = t.QuerySelector(".t1 span a").Attributes["href"]?.Value }).ToList(); long.TryParse(document.QuerySelector("input[name=jobid_count]").Attributes["value"]?.Value, out var totalCount); return(new JobListResultDto(jobs, totalCount)); } catch (Exception e) { _logger.LogException(e); throw new BusinessException("Qiancheng_001", e.Message, e.StackTrace, e.InnerException); } }
public async Task <JobListResultDto> SearchAsync(GetJobsInput input) { var cityCode = CityCodeDictionary.Get(JobSource.猎聘招聘, input.City); var request = new RestRequest(); request.AddParameter("salary", "*"); //TODO: 实现自定义 request.AddParameter("key", input.Keyword); request.AddParameter("dqs", cityCode); request.AddParameter("curPage", input.PageIndex - 1); //猎聘页索引从0开始 request.AddParameter("pageSize", input.PageSize); if (!input.ExtendedData.IsNullOrEmpty()) { try { var extendedData = _jsonSerializer.Deserialize <ExtendedParameters>(input.ExtendedData); request.AddObject(extendedData); } catch (Exception e) { _logger.LogWarning(e.Message, e.StackTrace, e.InnerException); } } try { var response = await _client.ExecuteGetTaskAsync <dynamic>(request); var htmlString = response.Content; var htmlParser = new HtmlParser(); var document = htmlParser.ParseDocument(htmlString); var jobInfoElements = document.QuerySelectorAll("ul.sojob-list li") .Where(t => t.QuerySelector(".job-info h3 a") != null); var jobs = jobInfoElements.Select(t => new JobDto { Position = t.QuerySelector("h3 a").TextContent.Trim(), Company = t.QuerySelector(".company-name a").TextContent, Salary = t.QuerySelector(".text-warning").TextContent, Address = t.QuerySelector(".area").TextContent, PublishedTime = t.QuerySelector("time").Attributes["title"].Value, Education = t.QuerySelector(".edu").TextContent, Url = t.QuerySelector(".job-info h3 a").GetAttribute("href"), WorkingYears = t.QuerySelector(".edu").NextElementSibling.TextContent }).ToList(); var dataInfoJson = document.Body.GetAttribute("data-info").UrlDecode(); dynamic dataInfo = JObject.Parse(dataInfoJson); //下次搜索携带的参数 var extendedParameters = new ExtendedParameters { init = dataInfo.init ?? -1, searchType = 1, headckid = dataInfo.headckid, fromSearchBtn = 2, sortFlag = 15, ckid = dataInfo.ckid, degradeFlag = 0, d_sfrom = dataInfo.as_from, d_ckId = dataInfo.ck_id, d_headId = dataInfo.head_id, d_curPage = input.PageIndex - 1, d_pageSize = input.PageSize }; var siTag = document.QuerySelector("input[name=siTag]").Attributes["value"]?.Value; extendedParameters.siTag = siTag; long totalCount = dataInfo.totalcnt; var extendedDataJson = _jsonSerializer.Serialize(extendedParameters); var resultDto = new JobListResultDto(jobs, totalCount) { NextRequestExtendedData = extendedDataJson }; return(resultDto); } catch (Exception e) { _logger.LogException(e); throw new BusinessException("Liepin_001", e.Message, e.StackTrace, e.InnerException); } }
public async Task <JobListResultDto> SearchAsync(GetJobsInput input) { var cityCode = CityCodeDictionary.Get(JobSource.拉钩招聘, input.City); var cookies = await GetRequestCookieAsync(cityCode); var url = $"https://www.lagou.com/jobs/positionAjax.json?px=new&city={cityCode.UrlEncode()}&needAddtionalResult=false"; var client = new RestClient(url) { UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36" }; var request = new RestRequest(); #region Heades & Cookie request.AddHeader("Accept", @"application/json, text/javascript, */*; q=0.01"); request.AddHeader("Accept-Encoding", "gzip, deflate, br"); request.AddHeader("Accept-Language", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"); request.AddHeader("Cache-Control", "max-age=0"); request.AddHeader("Connection", "keep-alive"); request.AddHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); request.AddHeader("Origin", "https://www.lagou.com"); request.AddHeader("X-Anit-Forge-Code", "0"); var refererUrl = $"https://www.lagou.com/jobs/list_{(input.Keyword.IsNullOrEmpty() ? "" : input.Keyword.UrlEncode())}?px=new&city={cityCode.UrlEncode()}&needAddtionalResult=false"; request.AddHeader("Referer", refererUrl); request.AddHeader("X-Anit-Forge-Code", "0"); request.AddHeader("X-Anit-Forge-Token", "None"); request.AddHeader("X-Requested-With", "XMLHttpRequest"); request.AddHeader("Cookie", $"JSESSIONID={cookies["JSESSIONID"]};SEARCH_ID={cookies["SEARCH_ID"]};LGRID={cookies["LGRID"]}"); foreach (var item in cookies) { request.AddCookie(item.Key, item.Value); } #endregion request.AddParameter("first", "true"); request.AddParameter("kd", input.Keyword); request.AddParameter("pn", input.PageIndex); request.AddParameter("pageSize", input.PageSize); input.PageSize = 15; //固定的 PageSize try { var response = await client.ExecutePostTaskAsync <dynamic>(request); dynamic responseData = JObject.Parse(response.Content); var jobList = responseData.content.positionResult.result; var jobs = new List <JobDto>(); foreach (var item in jobList) { var job = new JobDto { Position = item.positionName, Company = item.companyFullName, Salary = item.salary, Address = item.city + item.district + item.stationname, PublishedTime = item.formatCreateTime, Education = item.education, Url = $"https://www.lagou.com/jobs/{item.positionId}.html", WorkingYears = item.workYear }; jobs.Add(job); } long totalCount = responseData.content.positionResult.totalCount; return(new JobListResultDto(jobs, totalCount)); } catch (Exception e) { _logger.LogException(e); throw new BusinessException("Lagou_001", e.Message, e.StackTrace, e.InnerException); } }