protected override string BuildSearchUrl(string searchKey, YUEnums.PromotionType promotionType = YUEnums.PromotionType.ALL, YUEnums.AliveType aliveType = YUEnums.AliveType.ALL, YUEnums.FavType favType = YUEnums.FavType.ALL) { //https://totheglory.im/browse.php?search_field=北京 +halfdown +30down +freeleech +incdead +onlydead +excl +hr&c=M //TTG看起来只支持5种情况的过滤,其他都认为是全部过滤。 Dictionary <YUEnums.PromotionType, string> motionDict = new Dictionary <YUEnums.PromotionType, string>() { { YUEnums.PromotionType.FREE, " +freeleech" }, { YUEnums.PromotionType.THIRTYPERDOWN, " +30down" }, { YUEnums.PromotionType.HALFDOWN, " +halfdown" }, }; Dictionary <YUEnums.AliveType, string> aliveDict = new Dictionary <YUEnums.AliveType, string>() { { YUEnums.AliveType.ALL, " +incdead" }, { YUEnums.AliveType.Dead, " +onlydead" }, }; string queryString = string.Format("?search_field={0}", Uri.EscapeDataString(searchKey)); if (motionDict.ContainsKey(promotionType)) { queryString += Uri.EscapeDataString(motionDict[promotionType]); } if (aliveDict.ContainsKey(aliveType)) { queryString += Uri.EscapeDataString(aliveDict[aliveType]); } return(Site.SearchUrl + queryString); }
protected virtual string BuildSearchUrl(string searchKey, YUEnums.PromotionType promotionType = YUEnums.PromotionType.ALL, YUEnums.AliveType aliveType = YUEnums.AliveType.ALL, YUEnums.FavType favType = YUEnums.FavType.ALL) { //https://ourbits.club/torrents.php?incldead=2&spstate=2&inclbookmarked=1&search=&search_area=0&search_mode=0 //incldead->活种/断种 | spstate->促销 | inclbookmarked->收藏 | search->关键字 | search_area->范围 | search_mode->匹配模式 string queryString = string.Format("?incldead={0}&spstate={1}&inclbookmarked={2}&search={3}&search_area={4}&search_mode={5}", (int)aliveType, (int)promotionType, (int)favType, Uri.EscapeDataString(searchKey), 0, 0); return(Site.SearchUrl + queryString); }
public List <PTTorrent> SearchTorrent(string searchKey, YUEnums.PromotionType promotionType = YUEnums.PromotionType.ALL, YUEnums.AliveType aliveType = YUEnums.AliveType.ALL, YUEnums.FavType favType = YUEnums.FavType.ALL) { if (Site.SearchUrl.IsNullOrEmptyOrWhiteSpace()) { //站点还没有支持搜索 throw new Exception(string.Format("搜索种子错误,错误站点:{0},关键字:{1},错误原因:该站点尚未支持搜索。", Site.Name, searchKey)); } if (_cookie == null || _cookie.Count <= 0) { throw new Exception(string.Format("搜索种子错误,错误站点:{0},关键字:{1},错误原因:未登录,请先登录。", Site.Name, searchKey)); } string searchUrl = BuildSearchUrl(searchKey, promotionType, aliveType, favType); string htmlResult = HttpUtils.GetDataGetHtml(searchUrl, _cookie); HtmlDocument htmlDocument = new HtmlDocument(); htmlDocument.LoadHtml(htmlResult);//加载HTML字符串,如果是文件可以用htmlDocument.Load方法加载 var trNodes = GetTorrentNodes(htmlDocument); //如果只有一个节点,那么应该是Table的标题,这里忽略,从第二个节点开始算。 if (trNodes == null) { throw new Exception(string.Format("{0}无法搜索到对应结果,请尝试更换其他关键字。", SiteId)); } else { List <PTTorrent> torrents = new List <PTTorrent>(); for (int i = 1; i < trNodes.Count; i++) { var trNode = trNodes[i]; var tdNodes = GetTorrentNodes(trNode); //这里一般有10列,但是Frds为9列,所以这里以9列来处理 if (tdNodes == null || tdNodes.Count < 9) { continue; } else { PTTorrent torrent = new PTTorrent(); torrent.SiteId = SiteId; //tdNodes[1]为种子信息 //种子链接和标题是最重要的,如果这里拿不到,直接跳过了 if (!SetTorrentTitleAndLink(tdNodes[TorrentMaps[YUEnums.TorrentMap.Detail]], torrent)) { continue; } //这里的副标题如果没有的话,是否需要跳过?暂时先保留把。 SetTorrentSubTitle(tdNodes[TorrentMaps[YUEnums.TorrentMap.Detail]], torrent); SetTorrentPromotionType(tdNodes[TorrentMaps[YUEnums.TorrentMap.Detail]], torrent); SetTorrentHR(tdNodes[TorrentMaps[YUEnums.TorrentMap.Detail]], torrent); SetTorrentOtherInfo(tdNodes, torrent); torrents.Add(torrent); } } return(torrents); } }
private void SearchTorrent(List <PTSite> searchSites, string searchKey) { if (searchSites != null && searchSites.Count > 0) { bool isFill = false; List <PTTorrent> searchTorrents = new List <PTTorrent>(); StringBuilder sb = new StringBuilder(); var cts = new CancellationTokenSource(); YUEnums.PromotionType promotionType = (YUEnums.PromotionType)cmbPromotion.SelectedValue; YUEnums.AliveType aliveType = (YUEnums.AliveType)cmbAlive.SelectedValue; YUEnums.FavType favType = (YUEnums.FavType)cmbFav.SelectedValue; Task task = new Task(() => { Parallel.ForEach(searchSites.Distinct(), (site, state, i) => { //即便日后支持站点多用户,这里也只会取第一个用户。 AbstractPT pt = PTFactory.GetPT(site.Id, Global.Users.Where(x => x.Site.Id == site.Id).FirstOrDefault()) as AbstractPT; //假设4核Cpu,5个任务,因为是并行的原因,如果前4个在并行执行的过程任意一个发生了异常,那么此时前4个中其他3个还会继续执行到结束,但最后一个是不会执行的,所以这里需要做异常捕获处理。 try { List <PTTorrent> torrents = pt.SearchTorrent(searchKey, promotionType, aliveType, favType); lock (syncSearchObject) { if (torrents != null && torrents.Count > 0) { searchTorrents.AddRange(torrents); } } } catch (Exception ex) { lock (syncSearchObject) sb.AppendLine(ex.GetInnerExceptionMessage()); } }); }, cts.Token); progressPanel.BeginLoading(20000); task.Start(); cts.Token.Register(new Action(() => { if (!isFill) { FillTorrent(searchTorrents, ref isFill); bool isOpen = searchTorrents.Count <= 0; if (cts.Token.IsCancellationRequested) { LogMessage(null, "搜索过程出现错误,错误原因:超时。", isOpen); } } })); cts.CancelAfter(20000); task.ContinueWith(result => { if (!cts.Token.IsCancellationRequested && !isFill) { FillTorrent(searchTorrents, ref isFill); } string errMsg = sb.ToString(); if (!errMsg.IsNullOrEmptyOrWhiteSpace()) { bool isOpen = searchTorrents.Count <= 0; LogMessage(null, errMsg.TrimEnd(), isOpen); } }); } }