Browse Source

添加项目文件。

master
Nice 3 years ago
parent
commit
ec0e040509
  1. 25
      ReptileCaptures.sln
  2. 11
      ReptileCaptures/DTO/ImagesInfo.cs
  3. 15
      ReptileCaptures/DTO/Page.cs
  4. 19
      ReptileCaptures/DTO/SearchRegionTree.cs
  5. 38
      ReptileCaptures/Entites/Entity.cs
  6. 48
      ReptileCaptures/Entites/ODbContext.cs
  7. 33
      ReptileCaptures/Entites/ReptileCapture.cs
  8. 31
      ReptileCaptures/Entites/ReptileRegion.cs
  9. 52
      ReptileCaptures/Manage.cs
  10. 142
      ReptileCaptures/Program.cs
  11. 23
      ReptileCaptures/Repositories/IReptileCaptureRespository.cs
  12. 20
      ReptileCaptures/Repositories/IReptileRegionRespository.cs
  13. 35
      ReptileCaptures/Repositories/ReptileCaptureRespository.cs
  14. 47
      ReptileCaptures/Repositories/ReptileRegionRespository.cs
  15. 27
      ReptileCaptures/ReptileCaptures.csproj
  16. 4
      ReptileCaptures/appsettings.json

25
ReptileCaptures.sln

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReptileCaptures", "ReptileCaptures\ReptileCaptures.csproj", "{6C8B6841-164D-4E1C-96E2-112A8EB3209A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6C8B6841-164D-4E1C-96E2-112A8EB3209A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C8B6841-164D-4E1C-96E2-112A8EB3209A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C8B6841-164D-4E1C-96E2-112A8EB3209A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6C8B6841-164D-4E1C-96E2-112A8EB3209A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3C52CE1A-23FF-4447-B7B0-26C6704DC9F9}
EndGlobalSection
EndGlobal

11
ReptileCaptures/DTO/ImagesInfo.cs

@ -0,0 +1,11 @@
namespace PC
{
internal class ImagesInfo
{
public string CaptureUrl { get; set; }
public string CamName { get; set; }
public string CamIndexCode { get; set; }
public string CaptureId { get; set; }
public DateTime CaptureTime { get; set; }
}
}

15
ReptileCaptures/DTO/Page.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PC
{
internal class Page<PageSource>
{
public string Code { get; set; }
public PageSource Data { get; set; }
public string Msg { get; set; }
}
}

19
ReptileCaptures/DTO/SearchRegionTree.cs

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PC
{
public class SearchRegionTree
{
public List<SearchRegion> Rows { get; set; }
}
public class SearchRegion
{
public string Id { get; set; }
public string PId { get; set; }
public string Name { get; set; }
}
}

38
ReptileCaptures/Entites/Entity.cs

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace PC.Entites
{
internal class Entity
{
private static readonly RandomNumberGenerator RandomNumberGenerator = RandomNumberGenerator.Create();
/// <summary>
/// 主键Id
/// </summary>
public Guid Id { get; private set; }
protected Guid NewId()
{
var randomBytes = new byte[10];
RandomNumberGenerator.GetBytes(randomBytes);
long timestamp = DateTime.UtcNow.Ticks / 10000L;
byte[] timestampBytes = BitConverter.GetBytes(timestamp);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(timestampBytes);
}
byte[] guidBytes = new byte[16];
Buffer.BlockCopy(randomBytes, 0, guidBytes, 0, 10);
Buffer.BlockCopy(timestampBytes, 2, guidBytes, 10, 6);
Id = new Guid(guidBytes);
return Id;
}
}
}

48
ReptileCaptures/Entites/ODbContext.cs

@ -0,0 +1,48 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PC.Entites
{
internal class ODbContext : DbContext
{
private readonly IConfiguration Configuration;
public ODbContext(IConfiguration configuration)
{
Configuration = configuration;
}
public DbSet<ReptileCapture> ReptileCaptures { get; set; }
public DbSet<ReptileRegion> ReptileRegions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(Configuration["SqlConnection"]);
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ReptileCapture>(o =>
{
o.ToTable(nameof(ReptileCapture));
o.HasKey(o => o.Id);
o.Property(o => o.RegionId).HasColumnType("nvarchar(50)").HasColumnName("RegionId");
o.Property(o => o.CaptureTime).HasColumnType("datetime").HasColumnName("CaptureTime");
o.Property(o => o.CaptureUrl).HasColumnType("nvarchar(100)").HasColumnName("CaptureUrl");
o.Property(o => o.CaptureId).HasColumnType("nvarchar(50)").HasColumnName("CaptureId");
});
modelBuilder.Entity<ReptileRegion>(o =>
{
o.ToTable(nameof(ReptileRegion));
o.HasKey(o => o.Id);
o.Property(o => o.RegionId).HasColumnType("nvarchar(50)").HasColumnName("RegionId");
o.Property(o => o.RegionPId).HasColumnType("nvarchar(50)").HasColumnName("RegionPId");
o.Property(o => o.RegionName).HasColumnType("nvarchar(50)").HasColumnName("RegionName");
});
base.OnModelCreating(modelBuilder);
}
}
}

33
ReptileCaptures/Entites/ReptileCapture.cs

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PC.Entites
{
internal class ReptileCapture : Entity
{
/// <summary>
/// 图片地址
/// </summary>
public string CaptureUrl { get; set; }
/// <summary>
/// 区域Id
/// </summary>
public string RegionId { get; set; }
/// <summary>
/// 图片时间
/// </summary>
public DateTime CaptureTime { get; set; }
/// <summary>
/// 图片Id
/// </summary>
public string CaptureId { get; set; }
public ReptileCapture Create()
{
NewId();
return this;
}
}
}

31
ReptileCaptures/Entites/ReptileRegion.cs

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PC.Entites
{
internal class ReptileRegion : Entity
{
/// <summary>
/// 区域父Id
/// </summary>
public string RegionPId { get; set; }
/// <summary>
/// 区域名称
/// </summary>
public string RegionName { get; set; }
/// <summary>
/// 区域Id
/// </summary>
public string RegionId { get; set; }
public ReptileRegion Create()
{
NewId();
return this;
}
}
}

52
ReptileCaptures/Manage.cs

@ -0,0 +1,52 @@
using Microsoft.Extensions.Configuration;
using OpenQA.Selenium;
namespace PC
{
public class Manage
{
/// 登录
public static void Login(IWebDriver driver)
{
Thread.Sleep(3000);
driver.FindElement(By.CssSelector("#app > div > div > div.container.login-page > div.container.fullscreen-layout > div.m-main-content > div > div > form > div:nth-child(1) > div > div.login-input.has-prepend.el-input.el-input--prefix > input")).
SendKeys("admin");
driver.FindElement(By.CssSelector("#app > div > div > div.container.login-page > div.container.fullscreen-layout > div.m-main-content > div > div > form > div:nth-child(2) > div > div.login-input.has-prepend.el-input.el-input--prefix > input")).
SendKeys("hik12345+");
driver.FindElement(By.CssSelector("#app > div > div > div.container.login-page > div.container.fullscreen-layout > div.m-main-content > div > div > form > div:nth-child(5) > div > button")).
Click();
Thread.Sleep(5000);
}
//查询
public static void Query(IWebDriver driver)
{
Thread.Sleep(3000);
driver.FindElement(By.XPath(@"//*[@id=""app""]/div/section/aside/div/div/div/div/div[2]/button")).Click();
Thread.Sleep(3000);
}
//点击城市复选框
public static void ClickCity(IWebDriver driver)
{
Thread.Sleep(3000);
////*[@id="app"]/div/section/aside/div/div/div/div/div[1]/div[3]/div[1]/div[1]/div/div/div/div[1]/label
driver.FindElement(By.XPath(@"//*[@id=""app""]/div/section/aside/div/div/div/div/div[1]/div[3]/div[1]/div[1]/div/div/div/div[1]/label")).Click();
Thread.Sleep(3000);
}
public static async Task<string> DownImageNameAsync(IConfiguration configuration, string url)
{
using HttpClient httpClient = new();
var imageResponse = await httpClient.GetAsync(url);
imageResponse.EnsureSuccessStatusCode();
using Stream stream = imageResponse.Content.ReadAsStream();
string imageName = @$"{Guid.NewGuid()}.jpg";
string path = configuration["Path"];
using Stream saveStream = File.Create($"{path}\\{imageName}");
stream.CopyTo(saveStream);
return imageName;
}
}
}

142
ReptileCaptures/Program.cs

@ -0,0 +1,142 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools.V95;
using OpenQA.Selenium.DevTools.V95.Network;
using PC;
using PC.Entites;
using PC.Repositories;
using System.Collections.ObjectModel;
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddTransient<IConfiguration>(o => new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build()
);
serviceCollection.AddDbContext<ODbContext>();
serviceCollection.AddTransient<IReptileCaptureRespository, ReptileCaptureRespository>();
serviceCollection.AddTransient<IReptileRegionRespository, ReptileRegionRespository>();
IServiceProvider service = serviceCollection.BuildServiceProvider();
IReptileCaptureRespository reptileCaptureRespository = service.GetService<IReptileCaptureRespository>();
IReptileRegionRespository reptileRegionRespository = service.GetService<IReptileRegionRespository>();
ChromeOptions options = new();
options.AddArgument("--auto-open-devtools-for-tabs");
options.AddArgument("log-level=3");
int successCount = 1;
int errorCount = 1;
Console.WriteLine($"项目运行");
while (true)
{
try
{
Console.WriteLine($"爬虫启动运行{successCount}次");
using (ChromeDriver driver = new(options))
{
driver.Manage().Window.Maximize();
driver.Navigate().GoToUrl("http://39.98.181.39/portal/ui/login?service=http%3A%2F%2F39.98.181.39%3A80%2Fportal%2F");
var domain = driver.GetDevToolsSession().GetVersionSpecificDomains<DevToolsSessionDomains>();
await domain.Network.Enable(new EnableCommandSettings());
await domain.Network.EnableReportingApi(new EnableReportingApiCommandSettings());
//登录
Manage.Login(driver);
List<RequestWillBeSentEventArgs> requestWillBeSentEventArgs = new();
domain.Network.RequestWillBeSent += (se, e) =>
{
if (e.Type == OpenQA.Selenium.DevTools.V95.Network.ResourceType.XHR)
{
if (e.Request.Method == "GET")
{
if (e.Request.Url.Contains("vms/ui/unit/fetchUnitNodesByParent") ||
e.Request.Url.Contains("vms/ui/camera/fetchCaptureCamsPageQuery"))
{
requestWillBeSentEventArgs.Add(e);
}
}
else if (e.Request.Method == "POST")
{
if (e.Request.Url.Contains("vms/ui/captureInfo/fetchCaptureInfoByCam"))
{
requestWillBeSentEventArgs.Add(e);
}
}
}
};
//图片查询
driver.FindElement(By.CssSelector("#bottomWrapper > div.page.sub-page-container.page-show > div.container.home-page.is-overdue > div > div > div > div.list-content > div.list-nav.el-scrollbar.has-gutter > div.el-nav-scrollbar__wrap.el-scrollbar__wrap > div > div > div.m-list-ctn > div:nth-child(3) > div.content.cf > div:nth-child(3) > img")).
Click();
//进入
IWebElement iframe = driver.FindElement(By.CssSelector("#iframe000026"));
driver.SwitchTo().Frame(iframe);
//点击城市复选框
Manage.ClickCity(driver);
//查询
Manage.Query(driver);
ReadOnlyCollection<IWebElement> selectRegionTrees = driver.FindElements(
By.XPath(@"//*[@id=""app""]/div/section/aside/div/div/div/div/div[1]/div[3]/div[1]/div[1]/div/div/div/div[2]/div"));
foreach (IWebElement selectRegionTree in selectRegionTrees)
{
//点击下拉框 展示节点
selectRegionTree.FindElement(By.XPath("div/span[1]")).Click();
Thread.Sleep(1000);
selectRegionTree.FindElement(By.XPath("div/span[1]")).Click();
}
foreach (var e in requestWillBeSentEventArgs)
{
if (e.Request.Method == "GET")
{
if (e.Request.Url.Contains("vms/ui/unit/fetchUnitNodesByParent") ||
e.Request.Url.Contains("vms/ui/camera/fetchCaptureCamsPageQuery"))
{
var responseBody = await domain.Network.GetResponseBody(new GetResponseBodyCommandSettings()
{
RequestId = e.RequestId
});
Page<SearchRegionTree> page = JsonConvert.DeserializeObject<Page<SearchRegionTree>>(responseBody.Body);
foreach (var Row in page.Data.Rows)
{
await reptileRegionRespository.AddOrUpdateRegionAsync(new IReptileRegionRespository
.RegionDTO(Row.PId, Row.Name, Row.Id));
}
}
}
else if (e.Request.Method == "POST")
{
if (e.Request.Url.Contains("vms/ui/captureInfo/fetchCaptureInfoByCam"))
{
var responseBody = await domain.Network.GetResponseBody(new GetResponseBodyCommandSettings()
{
RequestId = e.RequestId
});
Page<List<ImagesInfo>> page = JsonConvert.DeserializeObject<Page<List<ImagesInfo>>>(responseBody.Body);
foreach (var data in page.Data)
{
await reptileCaptureRespository.NotNullAddCaptureAsync(new IReptileCaptureRespository
.CaptureDTO(data.CaptureUrl, data.CamIndexCode, data.CaptureTime, data.CaptureId));
}
}
}
}
}
Console.WriteLine(@$"任务完成{successCount}次,延迟1800000毫秒,约半小时");
successCount++;
Thread.Sleep(1800000);
}
catch (Exception ex)
{
Console.WriteLine($"进入异常{errorCount}次");
errorCount++;
}
}

23
ReptileCaptures/Repositories/IReptileCaptureRespository.cs

@ -0,0 +1,23 @@
namespace PC.Repositories
{
internal interface IReptileCaptureRespository
{
/// <summary>
/// 添加请求参数
/// </summary>
/// <param name="CaptureUrl">图片地址</param>
/// <param name="RegionId">区域Id</param>
/// <param name="CaptureTime">图片日期</param>
/// <param name="CaptureId">图片Id</param>
record CaptureDTO(
string CaptureUrl,
string RegionId,
DateTime CaptureTime,
string CaptureId);
/// <summary>
/// 添加图片
/// </summary>
Task NotNullAddCaptureAsync(CaptureDTO captureDTO);
}
}

20
ReptileCaptures/Repositories/IReptileRegionRespository.cs

@ -0,0 +1,20 @@
namespace PC.Repositories
{
internal interface IReptileRegionRespository
{
/// <summary>
/// 区域
/// </summary>
/// <param name="RegionPId">区域父Id</param>
/// <param name="RegionName">区域名称</param>
/// <param name="RegionId">区域Id</param>
record RegionDTO(
string RegionPId,
string RegionName,
string RegionId);
/// <summary>
/// 添加或者修改 区域
/// </summary>
Task AddOrUpdateRegionAsync(RegionDTO regionDTO);
}
}

35
ReptileCaptures/Repositories/ReptileCaptureRespository.cs

@ -0,0 +1,35 @@
using Microsoft.Extensions.Configuration;
using PC.Entites;
namespace PC.Repositories
{
internal class ReptileCaptureRespository : IReptileCaptureRespository
{
private readonly ODbContext _oDbContext;
public ReptileCaptureRespository(ODbContext oDbContext, IConfiguration configuration)
{
_oDbContext = oDbContext;
Configuration = configuration;
}
private readonly IConfiguration Configuration;
public async Task AddCaptureAsync(IReptileCaptureRespository.CaptureDTO captureDTO)
{
string imageURL = await Manage.DownImageNameAsync(Configuration, captureDTO.CaptureUrl);
await _oDbContext.ReptileCaptures.AddAsync(new ReptileCapture()
{
CaptureTime = captureDTO.CaptureTime,
RegionId = captureDTO.RegionId,
CaptureUrl = imageURL,
CaptureId = captureDTO.CaptureId,
}.Create());
_oDbContext.SaveChanges();
}
public async Task NotNullAddCaptureAsync(IReptileCaptureRespository.CaptureDTO captureDTO)
{
var region = _oDbContext.ReptileCaptures.FirstOrDefault(o => o.CaptureId == captureDTO.CaptureId);
if (region is null)
await AddCaptureAsync(captureDTO);
}
}
}

47
ReptileCaptures/Repositories/ReptileRegionRespository.cs

@ -0,0 +1,47 @@
using PC.Entites;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PC.Repositories
{
internal class ReptileRegionRespository : IReptileRegionRespository
{
private readonly ODbContext _oDbContext;
public ReptileRegionRespository(ODbContext oDbContext)
{
_oDbContext = oDbContext;
}
public async Task AddRegionAsync(IReptileRegionRespository.RegionDTO regionDTO)
{
await _oDbContext.ReptileRegions.AddAsync(new ReptileRegion()
{
RegionId = regionDTO.RegionId,
RegionName = regionDTO.RegionName,
RegionPId = regionDTO.RegionPId,
}.Create());
_oDbContext.SaveChanges();
}
public async Task AddOrUpdateRegionAsync(IReptileRegionRespository.RegionDTO regionDTO)
{
var region = _oDbContext.ReptileRegions.FirstOrDefault(o => o.RegionId == regionDTO.RegionId);
if (region != null)
{
if (region.RegionName != regionDTO.RegionName)
{
region.RegionName = regionDTO.RegionName;
_oDbContext.ReptileRegions.Update(region);
await _oDbContext.SaveChangesAsync();
}
}
else
{
await AddRegionAsync(regionDTO);
}
}
}
}

27
ReptileCaptures/ReptileCaptures.csproj

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
<PackageReference Include="Selenium.Support" Version="4.0.1" />
<PackageReference Include="Selenium.WebDriver" Version="4.0.1" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="96.0.4664.4500" />
</ItemGroup>
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

4
ReptileCaptures/appsettings.json

@ -0,0 +1,4 @@
{
"SqlConnection": "Data Source=192.168.2.166;Initial Catalog=InsectTrappingDb_Business;User ID=sa;Password=Athlon123;",
"Path": "D:\\IotSystem\\InsectTrapping.Business.Web\\wwwroot\\Upload\\ReptileCaptures"
}
Loading…
Cancel
Save