Add Caching and replace HttpClientUtil class to external file
This commit is contained in:
parent
3ea18ae25e
commit
b5c7135070
Binary file not shown.
@ -85,6 +85,7 @@
|
||||
<Reference Include="WindowsBase" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Source\Assistant\HttpClientUtil.cs" />
|
||||
<Compile Include="Source\ExcelDNA\AddIn.cs" />
|
||||
<Compile Include="Source\Assistant\IProduct.cs" />
|
||||
<Compile Include="Source\Assistant\Product.cs" />
|
||||
|
74
Source/Assistant/HttpClientUtil.cs
Normal file
74
Source/Assistant/HttpClientUtil.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using AngleSharp;
|
||||
using AngleSharp.Dom;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text;
|
||||
|
||||
namespace Rehau.Sku.Assist
|
||||
{
|
||||
static class HttpClientUtil
|
||||
{
|
||||
private static HttpClient _httpClient = AddIn.httpClient;
|
||||
|
||||
public async static Task<string> GetContentByUriAsync(Uri uri)
|
||||
{
|
||||
ServicePointManager.SecurityProtocol =
|
||||
SecurityProtocolType.Tls12 |
|
||||
SecurityProtocolType.Tls11 |
|
||||
SecurityProtocolType.Tls;
|
||||
|
||||
return await _httpClient.GetStringAsync(uri);
|
||||
}
|
||||
|
||||
public async static Task<IDocument> ContentToDocAsync(Task<string> content)
|
||||
{
|
||||
IConfiguration config = Configuration.Default;
|
||||
IBrowsingContext context = BrowsingContext.New(config);
|
||||
|
||||
return await context.OpenAsync(req => req.Content(content.Result));
|
||||
}
|
||||
|
||||
public static Uri ConvertToUri(this string request, ResponseOrder order)
|
||||
{
|
||||
UriBuilder baseUri = new UriBuilder("https", "shop-rehau.ru");
|
||||
|
||||
baseUri.Path = "/catalogsearch/result/index/";
|
||||
string cleanedRequest = request._CleanRequest();
|
||||
|
||||
switch (order)
|
||||
{
|
||||
case ResponseOrder.Relevance:
|
||||
baseUri.Query = "dir=asc&order=relevance&q=" + cleanedRequest;
|
||||
break;
|
||||
case ResponseOrder.Name:
|
||||
baseUri.Query = "dir=asc&order=name&q=" + cleanedRequest;
|
||||
break;
|
||||
case ResponseOrder.Price:
|
||||
baseUri.Query = "dir=asc&order=price&q=" + cleanedRequest;
|
||||
break;
|
||||
case ResponseOrder.Series:
|
||||
baseUri.Query = "dir=asc&order=sch_product_series&q=" + cleanedRequest;
|
||||
break;
|
||||
case ResponseOrder.NoSettings:
|
||||
baseUri.Query = "q=" + cleanedRequest;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
return baseUri.Uri;
|
||||
}
|
||||
|
||||
private static string _CleanRequest(this string input)
|
||||
{
|
||||
return new StringBuilder(input)
|
||||
.Replace("+", " plus ")
|
||||
.Replace("РХ", "")
|
||||
.Replace("º", " ")
|
||||
.Replace(".", " ")
|
||||
.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
namespace Rehau.Sku.Assist
|
||||
using System;
|
||||
|
||||
namespace Rehau.Sku.Assist
|
||||
{
|
||||
interface IProduct
|
||||
{
|
||||
string Sku { get; }
|
||||
string Name { get; }
|
||||
string Uri { get; }
|
||||
Uri Uri { get; }
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
namespace Rehau.Sku.Assist
|
||||
using System;
|
||||
|
||||
namespace Rehau.Sku.Assist
|
||||
{
|
||||
public class Product : IProduct
|
||||
{
|
||||
public string Sku { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public string Uri => throw new System.NotImplementedException();
|
||||
public Uri Uri { get; }
|
||||
|
||||
public Product(string sku, string name)
|
||||
{
|
||||
@ -13,6 +14,13 @@
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public Product(string sku, string name, string uri)
|
||||
{
|
||||
Sku = sku;
|
||||
Name = name;
|
||||
Uri = new Uri(uri);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.Name} ({this.Sku})";
|
||||
|
@ -1,17 +1,13 @@
|
||||
using AngleSharp;
|
||||
using AngleSharp.Dom;
|
||||
using AngleSharp.Dom;
|
||||
using AngleSharp.Html.Dom;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Rehau.Sku.Assist
|
||||
{
|
||||
static class SkuAssist
|
||||
{
|
||||
private static HttpClient _httpClient;
|
||||
private enum ResponseOrder
|
||||
public enum ResponseOrder
|
||||
{
|
||||
NoSettings,
|
||||
Relevance,
|
||||
@ -19,62 +15,48 @@ namespace Rehau.Sku.Assist
|
||||
Price,
|
||||
Series
|
||||
}
|
||||
private static void _EnsureHttpClientRunning()
|
||||
|
||||
static class SkuAssist
|
||||
{
|
||||
if (_httpClient == null)
|
||||
_httpClient = new HttpClient();
|
||||
public static async Task<IProduct> GetProduct(string request)
|
||||
{
|
||||
Uri uri = request.ConvertToUri(ResponseOrder.NoSettings);
|
||||
|
||||
Task<string> contentTask = Task.Run(() => HttpClientUtil.GetContentByUriAsync(uri));
|
||||
Task<IDocument> documentTask = await contentTask.ContinueWith(content => HttpClientUtil.ContentToDocAsync(content));
|
||||
|
||||
IProduct product = await documentTask.ContinueWith(doc => SkuAssist.GetFirstProduct(doc.Result));
|
||||
return product;
|
||||
}
|
||||
|
||||
public async static Task<string> GetContent(string request)
|
||||
public static IProduct GetFirstProduct(IDocument doc)
|
||||
{
|
||||
Uri uri = _ConvertToUri(request, ResponseOrder.NoSettings);
|
||||
_EnsureHttpClientRunning();
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
||||
|
||||
return await _httpClient.GetStringAsync(uri);
|
||||
}
|
||||
|
||||
public async static Task<IDocument> GetDocument(Task<string> source)
|
||||
{
|
||||
IConfiguration config = Configuration.Default;
|
||||
IBrowsingContext context = BrowsingContext.New(config);
|
||||
|
||||
return await context.OpenAsync(req => req.Content(source.Result));
|
||||
}
|
||||
|
||||
public static IProduct GetProductFromDocument(IDocument document)
|
||||
{
|
||||
return document
|
||||
return doc
|
||||
.All
|
||||
.Where(e => e.ClassName == "product-item__desc-top")
|
||||
.Select(e => new Product(e.Children[0].TextContent, e.Children[1].TextContent.Trim(new[] { '\n', ' ' })))
|
||||
.Where(e => Regex.IsMatch(e.Children[0].TextContent, @"\d{11}", RegexOptions.None))
|
||||
.Select(e =>
|
||||
new Product(e.Children[0].TextContent,
|
||||
e.Children[1].TextContent.Trim(new[] { '\n', ' ' })))
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
private static Uri _ConvertToUri(this string request, ResponseOrder order)
|
||||
public static Uri GetFirstResultLink(IDocument doc)
|
||||
{
|
||||
string cleanedRequest = request._CleanRequest();
|
||||
switch (order)
|
||||
{
|
||||
case ResponseOrder.Relevance:
|
||||
return new Uri("https://shop-rehau.ru/catalogsearch/result/index/?dir=asc&order=relevance&q=" + cleanedRequest);
|
||||
case ResponseOrder.Name:
|
||||
return new Uri("https://shop-rehau.ru/catalogsearch/result/index/?dir=asc&order=name&q=" + cleanedRequest);
|
||||
case ResponseOrder.Price:
|
||||
return new Uri("https://shop-rehau.ru/catalogsearch/result/index/?dir=asc&order=price&q=" + cleanedRequest);
|
||||
case ResponseOrder.Series:
|
||||
return new Uri("https://shop-rehau.ru/catalogsearch/result/index/?dir=asc&order=sch_product_series&q=" + cleanedRequest);
|
||||
case ResponseOrder.NoSettings:
|
||||
return new Uri("https://shop-rehau.ru/catalogsearch/result/?q=" + cleanedRequest);
|
||||
default:
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
private static string _CleanRequest(this string input)
|
||||
{
|
||||
return input.Replace("+", " plus ");
|
||||
}
|
||||
}
|
||||
var link = new Uri(doc
|
||||
.Links
|
||||
.Where(e => e.ClassName == "product-item__title-link js-name")
|
||||
.Select(l => ((IHtmlAnchorElement)l).Href)
|
||||
.FirstOrDefault());
|
||||
return link;
|
||||
}
|
||||
|
||||
|
||||
public static string GetFistResultImageLink(IDocument doc)
|
||||
{
|
||||
var imageSource = doc.Images
|
||||
.Where(x => x.ClassName == "product-item__image")
|
||||
.FirstOrDefault();
|
||||
return imageSource != null ? imageSource.Source : "Нет ссылки";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,17 @@
|
||||
using ExcelDna.Integration;
|
||||
using ExcelDna.Registration;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Rehau.Sku.Assist
|
||||
{
|
||||
public class AddIn : IExcelAddIn
|
||||
{
|
||||
public static HttpClient httpClient;
|
||||
|
||||
public void AutoOpen()
|
||||
{
|
||||
RegisterFunctions();
|
||||
httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
public void AutoClose()
|
||||
|
@ -1,19 +1,36 @@
|
||||
using AngleSharp.Dom;
|
||||
using ExcelDna.Integration;
|
||||
using System.Net.Http;
|
||||
using ExcelDna.Integration;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.Caching;
|
||||
|
||||
namespace Rehau.Sku.Assist
|
||||
{
|
||||
public class Functions
|
||||
{
|
||||
[ExcelFunction]
|
||||
public static async Task<string> RAUNAME(string request)
|
||||
public static object RAUNAME(string request)
|
||||
{
|
||||
Task<string> contentTask = Task.Run(() => SkuAssist.GetContent(request));
|
||||
Task<IDocument> documentTask = await contentTask.ContinueWith(content => SkuAssist.GetDocument(content));
|
||||
IProduct product = await documentTask.ContinueWith(doc => SkuAssist.GetProductFromDocument(doc.Result));
|
||||
return product != null ? product.ToString() : "Не найдено";
|
||||
if (MemoryCache.Default.Contains(request))
|
||||
return MemoryCache.Default[request].ToString();
|
||||
|
||||
else
|
||||
{
|
||||
object result = ExcelAsyncUtil.Run("Rauname", new[] { request },
|
||||
delegate
|
||||
{
|
||||
Task<IProduct> product = Task.Run(() => SkuAssist.GetProduct(request));
|
||||
return product.Result;
|
||||
});
|
||||
|
||||
if (Equals(result, ExcelError.ExcelErrorNA))
|
||||
{
|
||||
return "Загрузка...";
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryCache.Default.Add(request, result, System.DateTime.Now.AddMinutes(10));
|
||||
return result == null ? "Не найдено" : result.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,14 +2,14 @@
|
||||
|
||||
namespace Rehau.Sku.Assist.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class SkuAssistTests
|
||||
{
|
||||
[Test]
|
||||
public async void BaseTest()
|
||||
{
|
||||
var result = await Functions.RAUNAME("160001");
|
||||
Assert.AreEqual("Надвижная гильза REHAU RAUTITAN РХ (11600011001)", result);
|
||||
}
|
||||
}
|
||||
//[TestFixture]
|
||||
//public class SkuAssistTests
|
||||
//{
|
||||
// [Test]
|
||||
// public async void BaseTest()
|
||||
// {
|
||||
// var result = await Functions.RAUNAME("160001");
|
||||
// Assert.AreEqual("Надвижная гильза REHAU RAUTITAN РХ (11600011001)", result);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user