wip archival commit, unclear what I was doing here

This commit is contained in:
2025-06-12 16:38:49 -04:00
parent 382185f623
commit 94eaf8f833
33 changed files with 6747 additions and 571 deletions

7
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}

3667
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,10 +4,22 @@ version = "0.1.0"
edition = "2021"
[dependencies]
mistralrs.git = "https://github.com/EricLBuehler/mistral.rs.git"
mistralrs.tag = "v0.3.4"
mistralrs.features = ["cuda", "cudnn"]
scraper = "0.19.0"
log = "0.4.21"
anyhow = { version = "1.0.82", features = ["backtrace", "std"] }
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
regex = "1.10.4"
reqwest = { version = "0.12.3", features = ["blocking"] }
reqwest = { version = "0.12.3", features = ["blocking"] }
test-log = { version = "0.2.16", features = ["color", "log", "trace"] }
strum = { version = "0.26.3", features = [
"std",
"derive",
"phf",
"strum_macros",
] }
tokio = "1.41.1"
image = "0.25.5"

9
diesel.toml Normal file
View File

@ -0,0 +1,9 @@
# For documentation on how to configure this file,
# see https://diesel.rs/guides/configuring-diesel-cli
[print_schema]
file = "src/schema.rs"
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
[migrations_directory]
dir = "/home/hak8or/code/ebay_compute_scraper/migrations"

BIN
foo.db Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

View File

@ -0,0 +1,77 @@
Here is a table of processors (with one or more spaces as delimiters), their specs, and some benchmark results. Note, "CB R15" = Cinebench R15, with the 2nd last column being the multithreaded score, and the last column being the single threaded score.
```
Type CPU Family Name Released Cores Pass Mark CB R15
Desktop Intel I9 i9-13900KS Q1 2023 24/32 63,087
Amd EPYC 7513 Q2 2021 32/64 59,988
Desktop Intel I9 i9-13900K Q3 2022 24/32 59,968 6,141 330
Dekstop AMD Ryzen 9 7950x Q3 2022 16/32 64,552 6,580 336
Desktop AMD Ryzen 9 5950X Q4 2020 16/32 46,746 4,569 272
Server AMD Epyc 7313 Q1 2021 16/32 40,075
Server Intel Xeon Platinum 8180 35,208 4,355 165
Desktop AMD Ryzen 9 5900X Q4 2020 12/24 39,858 3,684 269
Server AMD Epyc 7282 Q4 2019 16/32 29,496
Desktop AMD Ryzen 7 5800X Q4 2020 8/16 28,647 2,611 270
Desktop AMD Ryzen 7 5800X3D Q2 2022 8/16 27,636 2,477 249
Desktop AMD Ryzen 7 5700X Q2 2022 8/16 26,694 2,307 253
Server AMD Threadripper 2950X Q4 2018 16/32 25,769 3,261 175
Desktop AMD Ryzen 7 3700X Q3 2019 8/16 22,816 2,114 204
Server AMD Threadripper 2920X Q4 2018 12/24 22,001 2,636 176
Server AMD Threadripper 1950X Q3 2017 16/32 21,931 3,151 166
Server AMD Threadripper 1920X Q3 2017 12/24 19,363 2,459 168
Desktop AMD Ryzen 7 2700X Q1 2018 8/16 17,587 1,828 180
Server Intel Xeon s Q4 2013 12/24 16,041 1,659
Server AMD Threadripper 1900X Q3 2017 8/16 16,005 1,805
Server Intel Xeon E5-2697 v2 Q2 2013 12/24 14,152 1,557 98
Desktop AMD Ryzen 7 1700 Q1 2017 8/16 13,805 1,473
Laptop AMD Ryzen 5 4650U Q1 2020 6/12 13,009 1,160 175
Server Intel Xeon Scalable Silver 4110 Q3 2017 8/16 10,028 1,148 131
Server Intel Xeon E5-2620 v4 Q1 2016 8/16 11,376 1,096 125
Server Intel Xeon E5-2650 V2 Q2 2013 8/16 13,053 1,063 128
Laptop AMD Ryzen 7 4700U Q1 2020 8/8 13,843 1,050 188
Laptop AMD Ryzen 5 4500U Q1 2020 6/6 11,304 889 176
Laptop Intel I5-1135G7 Q3 2020 4/8 8,623 855
Laptop Intel i7-1165G7 Q2 2020 4/8 11,086 809
Desktop AMD Ryzen 5 1500x Q1 2017 4/8 10,715 809
Server Intel Xeon E5-2650 Q1 2012 8/16 10,190 790
Server Intel Xeon E5-2630L v2 Q4 2014 6/12 9,088 800 147
Laptop Intel i7-1065G7 Q3 2019 4/8 8,980 704
Server Intel Xeon E3-1230 V2 Q2 2012 4/8 8,863 650
Laptop AMD Ryzen 5 3500U Q1 2018 4/8 7,157 620
Desktop Intel i7-8550U Q3 2017 4/8 8,317 558
Desktop AMD Ryzen 3 1300x Q1 2017 4/4 8,109 554
Server Intel Xeon X5670 Q1 2010 6/12 8,013 675
Laptop Intel i5-1035G1 Q3 2019 4/8 8,007 606
Server Intel Xeon E3-1230 Q2 2011 4/8 7,939 581
Desktop Intel i5-8500 Q2 2018 6/6 7,737 751 148
Desktop Intel I5-3570K Q2 2012 4/4 7,153 522
Server Intel Xeon E3-1220 v3 Q2 2013 4/4 6,966 500
Server Intel Xeon E5645 Q2 2011 6/12 6,545 573
Server Intel Xeon E3-1260L Q2 2011 4/8 6,534
Laptop Intel i5-10210U Q3 2019 4/8 6,532 567
Server Intel Xeon L5640 Q2 2010 6/12 6,451 497
Server Intel Xeon L5640 Q1 2010 6/12 6,451 497
Server Intel Xeon E3-1220 Q2 2011 4/4 6,086 433
Server Intel N100 Q1 2023 4/4 5,489 477 154
Desktop Intel i5-7500T Q1 2017 4/4 5,263 528 141
Laptop Intel i3-8130U Q2 2018 2/2 5,019 338
Desktop Intel i5-6500T Q4 2015 4/4 4,768 464 132
Server Intel Xeon L5520 Q1 2009 4/8 4,387
Server Intel Xeon E7-4850 Q2 2011 10/20 4,000 752
??? Intel G3258 Q2 2014 2/2 3,918 247
??? Intel C2750 Q3 2013 8/8 3,771 317
Server Intel Xeon E5-2407 Q2 2012 4/4 3,693 341
Server Intel N5100 Q2 2021 4/4 3,331 ????
Laptop Intel i5-2410M Q1 2011 2/4 3,161 236
Laptop Intel I3-5010u 2/4 218
??? Intel J4205 Q3 2016 4/4 2,688 196
??? Intel J3455 Q3 2016 4/4 2,153 181
??? Intel N3450 Q4 2016 4/4 1,805 135
Laptop Intel 3867U Q2 2019 2/2 1,483 139 71
Laptop Intel 2955U Q4 2016 2/2 1,450 100
??? Intel Atom x5-Z8300 Q2 2015 4/4 1,204 111
Laptop Intel 3205U Q2 2015 2/2 946 117 61
??? Intel N3050 Q1 2015 2/2 885 69
??? Intel Z3735F Q1 2014 4/4 879
??? AMD APU E-350 Q4 2012 2/2 782 50
```

View File

@ -0,0 +1,843 @@
[
{
"Type": "Desktop",
"CPU Family": "Intel I9",
"Name": "i9-13900KS",
"Released": "Q1 2023",
"Cores": "24/32",
"Pass Mark": "63,087",
"CB R15": null
},
{
"Type": null,
"CPU Family": "Amd EPYC",
"Name": "7513",
"Released": "Q2 2021",
"Cores": "32/64",
"Pass Mark": "59,988",
"CB R15": null
},
{
"Type": "Desktop",
"CPU Family": "Intel I9",
"Name": "i9-13900K",
"Released": "Q3 2022",
"Cores": "24/32",
"Pass Mark": "59,968",
"CB R15": {
"multithreaded": "6,141",
"singlethreaded": "330"
}
},
{
"Type": "Dekstop",
"CPU Family": "AMD Ryzen 9",
"Name": "7950x",
"Released": "Q3 2022",
"Cores": "16/32",
"Pass Mark": "64,552",
"CB R15": {
"multithreaded": "6,580",
"singlethreaded": "336"
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 9",
"Name": "5950X",
"Released": "Q4 2020",
"Cores": "16/32",
"Pass Mark": "46,746",
"CB R15": {
"multithreaded": "4,569",
"singlethreaded": "272"
}
},
{
"Type": "Server",
"CPU Family": "AMD Epyc",
"Name": "7313",
"Released": "Q1 2021",
"Cores": "16/32",
"Pass Mark": "40,075",
"CB R15": null
},
{
"Type": "Server",
"CPU Family": "Intel Xeon Platinum",
"Name": "8180",
"Released": null,
"Cores": null,
"Pass Mark": "35,208",
"CB R15": {
"multithreaded": "4,355",
"singlethreaded": "165"
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 9",
"Name": "5900X",
"Released": "Q4 2020",
"Cores": "12/24",
"Pass Mark": "39,858",
"CB R15": {
"multithreaded": "3,684",
"singlethreaded": "269"
}
},
{
"Type": "Server",
"CPU Family": "AMD Epyc",
"Name": "7282",
"Released": "Q4 2019",
"Cores": "16/32",
"Pass Mark": "29,496",
"CB R15": null
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 7",
"Name": "5800X",
"Released": "Q4 2020",
"Cores": "8/16",
"Pass Mark": "28,647",
"CB R15": {
"multithreaded": "2,611",
"singlethreaded": "270"
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 7",
"Name": "5800X3D",
"Released": "Q2 2022",
"Cores": "8/16",
"Pass Mark": "27,636",
"CB R15": {
"multithreaded": "2,477",
"singlethreaded": "249"
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 7",
"Name": "5700X",
"Released": "Q2 2022",
"Cores": "8/16",
"Pass Mark": "26,694",
"CB R15": {
"multithreaded": "2,307",
"singlethreaded": "253"
}
},
{
"Type": "Server",
"CPU Family": "AMD Threadripper",
"Name": "2950X",
"Released": "Q4 2018",
"Cores": "16/32",
"Pass Mark": "25,769",
"CB R15": {
"multithreaded": "3,261",
"singlethreaded": "175"
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 7",
"Name": "3700X",
"Released": "Q3 2019",
"Cores": "8/16",
"Pass Mark": "22,816",
"CB R15": {
"multithreaded": "2,114",
"singlethreaded": "204"
}
},
{
"Type": "Server",
"CPU Family": "AMD Threadripper",
"Name": "2920X",
"Released": "Q4 2018",
"Cores": "12/24",
"Pass Mark": "22,001",
"CB R15": {
"multithreaded": "2,636",
"singlethreaded": "176"
}
},
{
"Type": "Server",
"CPU Family": "AMD Threadripper",
"Name": "1950X",
"Released": "Q3 2017",
"Cores": "16/32",
"Pass Mark": "21,931",
"CB R15": {
"multithreaded": "3,151",
"singlethreaded": "166"
}
},
{
"Type": "Server",
"CPU Family": "AMD Threadripper",
"Name": "1920X",
"Released": "Q3 2017",
"Cores": "12/24",
"Pass Mark": "19,363",
"CB R15": {
"multithreaded": "2,459",
"singlethreaded": "168"
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 7",
"Name": "2700X",
"Released": "Q1 2018",
"Cores": "8/16",
"Pass Mark": "17,587",
"CB R15": {
"multithreaded": "1,828",
"singlethreaded": "180"
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "s",
"Released": "Q4 2013",
"Cores": "12/24",
"Pass Mark": "16,041",
"CB R15": {
"multithreaded": "1,659",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "AMD Threadripper",
"Name": "1900X",
"Released": "Q3 2017",
"Cores": "8/16",
"Pass Mark": "16,005",
"CB R15": {
"multithreaded": "1,805",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E5-2697 v2",
"Released": "Q2 2013",
"Cores": "12/24",
"Pass Mark": "14,152",
"CB R15": {
"multithreaded": "1,557",
"singlethreaded": "98"
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 7",
"Name": "1700",
"Released": "Q1 2017",
"Cores": "8/16",
"Pass Mark": "13,805",
"CB R15": {
"multithreaded": "1,473",
"singlethreaded": null
}
},
{
"Type": "Laptop",
"CPU Family": "AMD Ryzen 5",
"Name": "4650U",
"Released": "Q1 2020",
"Cores": "6/12",
"Pass Mark": "13,009",
"CB R15": {
"multithreaded": "1,160",
"singlethreaded": "175"
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon Scalable",
"Name": "Silver 4110",
"Released": "Q3 2017",
"Cores": "8/16",
"Pass Mark": "10,028",
"CB R15": {
"multithreaded": "1,148",
"singlethreaded": "131"
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E5-2620 v4",
"Released": "Q1 2016",
"Cores": "8/16",
"Pass Mark": "11,376",
"CB R15": {
"multithreaded": "1,096",
"singlethreaded": "125"
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E5-2650 V2",
"Released": "Q2 2013",
"Cores": "8/16",
"Pass Mark": "13,053",
"CB R15": {
"multithreaded": "1,063",
"singlethreaded": "128"
}
},
{
"Type": "Laptop",
"CPU Family": "AMD Ryzen 7",
"Name": "4700U",
"Released": "Q1 2020",
"Cores": "8/8",
"Pass Mark": "13,843",
"CB R15": {
"multithreaded": "1,050",
"singlethreaded": "188"
}
},
{
"Type": "Laptop",
"CPU Family": "AMD Ryzen 5",
"Name": "4500U",
"Released": "Q1 2020",
"Cores": "6/6",
"Pass Mark": "11,304",
"CB R15": {
"multithreaded": "889",
"singlethreaded": "176"
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "I5-1135G7",
"Released": "Q3 2020",
"Cores": "4/8",
"Pass Mark": "8,623",
"CB R15": {
"multithreaded": "855",
"singlethreaded": null
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "i7-1165G7",
"Released": "Q2 2020",
"Cores": "4/8",
"Pass Mark": "11,086",
"CB R15": {
"multithreaded": "809",
"singlethreaded": null
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 5",
"Name": "1500x",
"Released": "Q1 2017",
"Cores": "4/8",
"Pass Mark": "10,715",
"CB R15": {
"multithreaded": "809",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E5-2650",
"Released": "Q1 2012",
"Cores": "8/16",
"Pass Mark": "10,190",
"CB R15": {
"multithreaded": "790",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E5-2630L v2",
"Released": "Q4 2014",
"Cores": "6/12",
"Pass Mark": "9,088",
"CB R15": {
"multithreaded": "800",
"singlethreaded": "147"
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "i7-1065G7",
"Released": "Q3 2019",
"Cores": "4/8",
"Pass Mark": "8,980",
"CB R15": {
"multithreaded": "704",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E3-1230 V2",
"Released": "Q2 2012",
"Cores": "4/8",
"Pass Mark": "8,863",
"CB R15": {
"multithreaded": "650",
"singlethreaded": null
}
},
{
"Type": "Laptop",
"CPU Family": "AMD Ryzen 5",
"Name": "3500U",
"Released": "Q1 2018",
"Cores": "4/8",
"Pass Mark": "7,157",
"CB R15": {
"multithreaded": "620",
"singlethreaded": null
}
},
{
"Type": "Desktop",
"CPU Family": "Intel",
"Name": "i7-8550U",
"Released": "Q3 2017",
"Cores": "4/8",
"Pass Mark": "8,317",
"CB R15": {
"multithreaded": "558",
"singlethreaded": null
}
},
{
"Type": "Desktop",
"CPU Family": "AMD Ryzen 3",
"Name": "1300x",
"Released": "Q1 2017",
"Cores": "4/4",
"Pass Mark": "8,109",
"CB R15": {
"multithreaded": "554",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "X5670",
"Released": "Q1 2010",
"Cores": "6/12",
"Pass Mark": "8,013",
"CB R15": {
"multithreaded": "675",
"singlethreaded": null
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "i5-1035G1",
"Released": "Q3 2019",
"Cores": "4/8",
"Pass Mark": "8,007",
"CB R15": {
"multithreaded": "606",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E3-1230",
"Released": "Q2 2011",
"Cores": "4/8",
"Pass Mark": "7,939",
"CB R15": {
"multithreaded": "581",
"singlethreaded": null
}
},
{
"Type": "Desktop",
"CPU Family": "Intel",
"Name": "i5-8500",
"Released": "Q2 2018",
"Cores": "6/6",
"Pass Mark": "7,737",
"CB R15": {
"multithreaded": "751",
"singlethreaded": "148"
}
},
{
"Type": "Desktop",
"CPU Family": "Intel",
"Name": "I5-3570K",
"Released": "Q2 2012",
"Cores": "4/4",
"Pass Mark": "7,153",
"CB R15": {
"multithreaded": "522",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E3-1220 v3",
"Released": "Q2 2013",
"Cores": "4/4",
"Pass Mark": "6,966",
"CB R15": {
"multithreaded": "500",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E5645",
"Released": "Q2 2011",
"Cores": "6/12",
"Pass Mark": "6,545",
"CB R15": {
"multithreaded": "573",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E3-1260L",
"Released": "Q2 2011",
"Cores": "4/8",
"Pass Mark": "6,534",
"CB R15": null
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "i5-10210U",
"Released": "Q3 2019",
"Cores": "4/8",
"Pass Mark": "6,532",
"CB R15": {
"multithreaded": "567",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "L5640",
"Released": "Q2 2010",
"Cores": "6/12",
"Pass Mark": "6,451",
"CB R15": {
"multithreaded": "497",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "L5640",
"Released": "Q1 2010",
"Cores": "6/12",
"Pass Mark": "6,451",
"CB R15": {
"multithreaded": "497",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E3-1220",
"Released": "Q2 2011",
"Cores": "4/4",
"Pass Mark": "6,086",
"CB R15": {
"multithreaded": "433",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel",
"Name": "N100",
"Released": "Q1 2023",
"Cores": "4/4",
"Pass Mark": "5,489",
"CB R15": {
"multithreaded": "477",
"singlethreaded": "154"
}
},
{
"Type": "Desktop",
"CPU Family": "Intel",
"Name": "i5-7500T",
"Released": "Q1 2017",
"Cores": "4/4",
"Pass Mark": "5,263",
"CB R15": {
"multithreaded": "528",
"singlethreaded": "141"
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "i3-8130U",
"Released": "Q2 2018",
"Cores": "2/2",
"Pass Mark": "5,019",
"CB R15": {
"multithreaded": "338",
"singlethreaded": null
}
},
{
"Type": "Desktop",
"CPU Family": "Intel",
"Name": "i5-6500T",
"Released": "Q4 2015",
"Cores": "4/4",
"Pass Mark": "4,768",
"CB R15": {
"multithreaded": "464",
"singlethreaded": "132"
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "L5520",
"Released": "Q1 2009",
"Cores": "4/8",
"Pass Mark": "4,387",
"CB R15": null
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E7-4850",
"Released": "Q2 2011",
"Cores": "10/20",
"Pass Mark": "4,000",
"CB R15": {
"multithreaded": "752",
"singlethreaded": null
}
},
{
"Type": "???",
"CPU Family": "Intel",
"Name": "G3258",
"Released": "Q2 2014",
"Cores": "2/2",
"Pass Mark": "3,918",
"CB R15": {
"multithreaded": "247",
"singlethreaded": null
}
},
{
"Type": "???",
"CPU Family": "Intel",
"Name": "C2750",
"Released": "Q3 2013",
"Cores": "8/8",
"Pass Mark": "3,771",
"CB R15": {
"multithreaded": "317",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel Xeon",
"Name": "E5-2407",
"Released": "Q2 2012",
"Cores": "4/4",
"Pass Mark": "3,693",
"CB R15": {
"multithreaded": "341",
"singlethreaded": null
}
},
{
"Type": "Server",
"CPU Family": "Intel",
"Name": "N5100",
"Released": "Q2 2021",
"Cores": "4/4",
"Pass Mark": "3,331",
"CB R15": null
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "i5-2410M",
"Released": "Q1 2011",
"Cores": "2/4",
"Pass Mark": "3,161",
"CB R15": {
"multithreaded": "236",
"singlethreaded": null
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "I3-5010u",
"Released": null,
"Cores": "2/4",
"Pass Mark": null,
"CB R15": {
"multithreaded": "218",
"singlethreaded": null
}
},
{
"Type": "???",
"CPU Family": "Intel",
"Name": "J4205",
"Released": "Q3 2016",
"Cores": "4/4",
"Pass Mark": "2,688",
"CB R15": {
"multithreaded": "196",
"singlethreaded": null
}
},
{
"Type": "???",
"CPU Family": "Intel",
"Name": "J3455",
"Released": "Q3 2016",
"Cores": "4/4",
"Pass Mark": "2,153",
"CB R15": {
"multithreaded": "181",
"singlethreaded": null
}
},
{
"Type": "???",
"CPU Family": "Intel",
"Name": "N3450",
"Released": "Q4 2016",
"Cores": "4/4",
"Pass Mark": "1,805",
"CB R15": {
"multithreaded": "135",
"singlethreaded": null
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "3867U",
"Released": "Q2 2019",
"Cores": "2/2",
"Pass Mark": "1,483",
"CB R15": {
"multithreaded": "139",
"singlethreaded": "71"
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "2955U",
"Released": "Q4 2016",
"Cores": "2/2",
"Pass Mark": "1,450",
"CB R15": {
"multithreaded": "100",
"singlethreaded": null
}
},
{
"Type": "???",
"CPU Family": "Intel Atom",
"Name": "x5-Z8300",
"Released": "Q2 2015",
"Cores": "4/4",
"Pass Mark": "1,204",
"CB R15": {
"multithreaded": "111",
"singlethreaded": null
}
},
{
"Type": "Laptop",
"CPU Family": "Intel",
"Name": "3205U",
"Released": "Q2 2015",
"Cores": "2/2",
"Pass Mark": "946",
"CB R15": {
"multithreaded": "117",
"singlethreaded": "61"
}
},
{
"Type": "???",
"CPU Family": "Intel",
"Name": "N3050",
"Released": "Q1 2015",
"Cores": "2/2",
"Pass Mark": "885",
"CB R15": {
"multithreaded": "69",
"singlethreaded": null
}
},
{
"Type": "???",
"CPU Family": "Intel",
"Name": "Z3735F",
"Released": "Q1 2014",
"Cores": "4/4",
"Pass Mark": "879",
"CB R15": null
},
{
"Type": "???",
"CPU Family": "AMD APU",
"Name": "E-350",
"Released": "Q4 2012",
"Cores": "2/2",
"Pass Mark": "782",
"CB R15": {
"multithreaded": "50",
"singlethreaded": null
}
}
]

View File

@ -0,0 +1,125 @@
Here is a table of processors, their specs, and some benchmark results. Note, "CB R15" = Cinebench R15, with the 2nd last column being the multithreaded score, and the last column being the single threaded score.
```
Type CPU Family Name Released Cores Pass Mark CB R15
Desktop Intel I9 i9-13900KS Q1 2023 24/32 63,087
Amd EPYC 7513 Q2 2021 32/64 59,988
Desktop Intel I9 i9-13900K Q3 2022 24/32 59,968 6,141 330
Dekstop AMD Ryzen 9 7950x Q3 2022 16/32 64,552 6,580 336
Desktop AMD Ryzen 9 5950X Q4 2020 16/32 46,746 4,569 272
Server AMD Epyc 7313 Q1 2021 16/32 40,075
Server Intel Xeon Platinum 8180 35,208 4,355 165
Desktop AMD Ryzen 9 5900X Q4 2020 12/24 39,858 3,684 269
Server AMD Epyc 7282 Q4 2019 16/32 29,496
Desktop AMD Ryzen 7 5800X Q4 2020 8/16 28,647 2,611 270
Desktop AMD Ryzen 7 5800X3D Q2 2022 8/16 27,636 2,477 249
Desktop AMD Ryzen 7 5700X Q2 2022 8/16 26,694 2,307 253
Server AMD Threadripper 2950X Q4 2018 16/32 25,769 3,261 175
Desktop AMD Ryzen 7 3700X Q3 2019 8/16 22,816 2,114 204
Server AMD Threadripper 2920X Q4 2018 12/24 22,001 2,636 176
Server AMD Threadripper 1950X Q3 2017 16/32 21,931 3,151 166
Server AMD Threadripper 1920X Q3 2017 12/24 19,363 2,459 168
Desktop AMD Ryzen 7 2700X Q1 2018 8/16 17,587 1,828 180
Server Intel Xeon s Q4 2013 12/24 16,041 1,659
Server AMD Threadripper 1900X Q3 2017 8/16 16,005 1,805
Server Intel Xeon E5-2697 v2 Q2 2013 12/24 14,152 1,557 98
Desktop AMD Ryzen 7 1700 Q1 2017 8/16 13,805 1,473
Laptop AMD Ryzen 5 4650U Q1 2020 6/12 13,009 1,160 175
Server Intel Xeon Scalable Silver 4110 Q3 2017 8/16 10,028 1,148 131
Server Intel Xeon E5-2620 v4 Q1 2016 8/16 11,376 1,096 125
Server Intel Xeon E5-2650 V2 Q2 2013 8/16 13,053 1,063 128
Laptop AMD Ryzen 7 4700U Q1 2020 8/8 13,843 1,050 188
Laptop AMD Ryzen 5 4500U Q1 2020 6/6 11,304 889 176
Laptop Intel I5-1135G7 Q3 2020 4/8 8,623 855
Laptop Intel i7-1165G7 Q2 2020 4/8 11,086 809
Desktop AMD Ryzen 5 1500x Q1 2017 4/8 10,715 809
Server Intel Xeon E5-2650 Q1 2012 8/16 10,190 790
Server Intel Xeon E5-2630L v2 Q4 2014 6/12 9,088 800 147
Laptop Intel i7-1065G7 Q3 2019 4/8 8,980 704
Server Intel Xeon E3-1230 V2 Q2 2012 4/8 8,863 650
Laptop AMD Ryzen 5 3500U Q1 2018 4/8 7,157 620
Desktop Intel i7-8550U Q3 2017 4/8 8,317 558
Desktop AMD Ryzen 3 1300x Q1 2017 4/4 8,109 554
Server Intel Xeon X5670 Q1 2010 6/12 8,013 675
Laptop Intel i5-1035G1 Q3 2019 4/8 8,007 606
Server Intel Xeon E3-1230 Q2 2011 4/8 7,939 581
Desktop Intel i5-8500 Q2 2018 6/6 7,737 751 148
Desktop Intel I5-3570K Q2 2012 4/4 7,153 522
Server Intel Xeon E3-1220 v3 Q2 2013 4/4 6,966 500
Server Intel Xeon E5645 Q2 2011 6/12 6,545 573
Server Intel Xeon E3-1260L Q2 2011 4/8 6,534
Laptop Intel i5-10210U Q3 2019 4/8 6,532 567
Server Intel Xeon L5640 Q2 2010 6/12 6,451 497
Server Intel Xeon L5640 Q1 2010 6/12 6,451 497
Server Intel Xeon E3-1220 Q2 2011 4/4 6,086 433
Server Intel N100 Q1 2023 4/4 5,489 477 154
Desktop Intel i5-7500T Q1 2017 4/4 5,263 528 141
Laptop Intel i3-8130U Q2 2018 2/2 5,019 338
Desktop Intel i5-6500T Q4 2015 4/4 4,768 464 132
Server Intel Xeon L5520 Q1 2009 4/8 4,387
Server Intel Xeon E7-4850 Q2 2011 10/20 4,000 752
??? Intel G3258 Q2 2014 2/2 3,918 247
??? Intel C2750 Q3 2013 8/8 3,771 317
Server Intel Xeon E5-2407 Q2 2012 4/4 3,693 341
Server Intel N5100 Q2 2021 4/4 3,331 ????
Laptop Intel i5-2410M Q1 2011 2/4 3,161 236
Laptop Intel I3-5010u 2/4 218
??? Intel J4205 Q3 2016 4/4 2,688 196
??? Intel J3455 Q3 2016 4/4 2,153 181
??? Intel N3450 Q4 2016 4/4 1,805 135
Laptop Intel 3867U Q2 2019 2/2 1,483 139 71
Laptop Intel 2955U Q4 2016 2/2 1,450 100
??? Intel Atom x5-Z8300 Q2 2015 4/4 1,204 111
Laptop Intel 3205U Q2 2015 2/2 946 117 61
??? Intel N3050 Q1 2015 2/2 885 69
??? Intel Z3735F Q1 2014 4/4 879
??? AMD APU E-350 Q4 2012 2/2 782 50
```
Try to convert that table into rust code, assuming the following rust struct;
```
#[derive(Clone, Copy, Debug)]
enum CPUClass {
MobileEmbedded,
Desktop,
Server,
}
#[derive(Clone, Debug)]
struct PassMarkEntry {
name: Cow<'static, str>,
class: CPUClass,
ghz_normal: f32,
ghz_turbo: f32,
physical_cores: u16,
threads: u16,
tdp: u16,
released: Cow<'static, str>,
passmark_st: u32,
passmark_mt: u32,
cb_r15_st: Option<u32>,
cb_r15_mt: Option<u32>,
}
```
With an example;
```
static ENTRIES: &'static [PassMarkEntry] = &[
PassMarkEntry {
name: Cow::Borrowed("n100"),
class: CPUClass::MobileEmbedded,
ghz_normal: 0.7,
ghz_turbo: 3.4,
physical_cores: 4,
threads: 4,
tdp: 6,
released: Cow::Borrowed("Q1 2023"),
passmark_st: 1936,
passmark_mt: 5489,
cb_r15_st: Some(154),
cb_r15_mt: Some(477),
}
]
```
If needed then modify the struct to mark certain properties as optional. Only output the rust code. Handle all the processors found in the table.

1
src/benchmarks/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod passmark;

125
src/benchmarks/passmark.rs Normal file
View File

@ -0,0 +1,125 @@
use std::borrow::Cow;
#[derive(Clone, Copy, Debug)]
enum CPUClass {
MobileEmbedded,
Desktop,
Server,
}
#[derive(Clone, Debug)]
struct PassMarkEntry {
name: Cow<'static, str>,
class: CPUClass,
ghz_normal: f32,
ghz_turbo: f32,
physical_cores: u16,
threads: u16,
tdp: u16,
released: Cow<'static, str>,
passmark_st: u32,
passmark_mt: u32,
cb_r15_st: Option<u32>,
cb_r15_mt: Option<u32>,
}
pub static ENTRIES: &'static [PassMarkEntry] = &[
PassMarkEntry {
name: Cow::Borrowed("n100"),
class: CPUClass::MobileEmbedded,
ghz_normal: 0.7,
ghz_turbo: 3.4,
physical_cores: 4,
threads: 4,
tdp: 6,
released: Cow::Borrowed("Q1 2023"),
passmark_st: 1936,
passmark_mt: 5489,
cb_r15_st: Some(154),
cb_r15_mt: Some(477),
},
PassMarkEntry {
name: Cow::Borrowed("i7-10710U"),
class: CPUClass::MobileEmbedded,
ghz_normal: 1.1,
ghz_turbo: 4.7,
physical_cores: 6,
threads: 12,
tdp: 15,
released: Cow::Borrowed("Q4 2019"),
passmark_st: 2336,
passmark_mt: 9551,
cb_r15_st: None,
cb_r15_mt: None,
},
PassMarkEntry {
name: Cow::Borrowed("i5-6500T"),
class: CPUClass::Desktop,
ghz_normal: 2.5,
ghz_turbo: 3.1,
physical_cores: 4,
threads: 4,
tdp: 35,
released: Cow::Borrowed("Q4 2015"),
passmark_st: 1793,
passmark_mt: 4768,
cb_r15_st: Some(132),
cb_r15_mt: Some(464),
},
PassMarkEntry {
name: Cow::Borrowed("i7-7700T"),
class: CPUClass::Desktop,
ghz_normal: 2.9,
ghz_turbo: 3.8,
physical_cores: 4,
threads: 8,
tdp: 35,
released: Cow::Borrowed("Q1 2017"),
passmark_st: 2147,
passmark_mt: 7589,
cb_r15_st: None,
cb_r15_mt: None,
},
PassMarkEntry {
name: Cow::Borrowed("7950x"),
class: CPUClass::Desktop,
ghz_normal: 4.5,
ghz_turbo: 5.7,
physical_cores: 16,
threads: 32,
tdp: 170,
released: Cow::Borrowed("Q3 2022"),
passmark_st: 4276,
passmark_mt: 62705,
cb_r15_st: Some(336),
cb_r15_mt: Some(6580),
},
PassMarkEntry {
name: Cow::Borrowed("2700x"),
class: CPUClass::Desktop,
ghz_normal: 3.7,
ghz_turbo: 4.3,
physical_cores: 8,
threads: 16,
tdp: 105,
released: Cow::Borrowed("Q2 2018"),
passmark_st: 2421,
passmark_mt: 17516,
cb_r15_st: Some(180),
cb_r15_mt: Some(1828),
},
PassMarkEntry {
name: Cow::Borrowed("E5-2630L V2"),
class: CPUClass::Server,
ghz_normal: 2.4,
ghz_turbo: 2.8,
physical_cores: 2,
threads: 12,
tdp: 60,
released: Cow::Borrowed("Q4 2014"),
passmark_st: 1396,
passmark_mt: 6703,
cb_r15_st: Some(147),
cb_r15_mt: Some(800),
},
];

View File

@ -1,14 +1,11 @@
use std::collections::HashMap;
use anyhow::{bail, Result};
use tracing::{info, error, instrument};
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::collections::HashMap;
use std::thread;
use std::thread::Thread;
pub struct Context {
pub urls: HashMap<String, String>,
pub threads: Vec<std::thread::JoinHandle<Result<String, anyhow::Error>>>
pub threads: Vec<std::thread::JoinHandle<Result<String, anyhow::Error>>>,
}
impl Default for Context {
@ -30,7 +27,12 @@ impl Default for Context {
}
impl Context {
pub fn ebay_fetch_html(&mut self, filename: String, url: String, outdir_dir: String) -> Result<()> {
pub fn ebay_fetch_html(
&mut self,
filename: String,
url: String,
outdir_dir: String,
) -> Result<()> {
let thr = thread::spawn(move || {
// let body = reqwest::blocking::get(url)?.text()?;
@ -45,4 +47,3 @@ impl Context {
Ok(())
}
}

2
src/lib.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod benchmarks;
pub mod parser;

View File

@ -1,219 +1,30 @@
mod ebay_fetcher;
use std::{fs::File, io::Read, path::PathBuf};
use scraper::{ElementRef, Html, Selector, selector::ToCss};
use anyhow::{bail, Result};
use tracing::{info, error, instrument};
use anyhow::Result;
use ebay_compute_scraper::parser::search_results::parse_ebay_results;
use std::path::PathBuf;
use tracing::info;
use tracing_subscriber::FmtSubscriber;
use regex::Regex;
use crate::ebay_fetcher::Context;
#[allow(dead_code)]
#[derive(Debug, Default, Clone)]
struct ParsedFile {
filename: String,
listings: Vec<EbayResult>
}
// #[derive(Debug, Default, Clone)]
// struct ParsedFile {
// filename: String,
// listings: Vec<parser::EbayResult>,
// }
#[allow(dead_code)]
#[derive(Debug, Clone)]
struct EbayResult {
pub price: f64,
pub shipping: f64,
pub title: String,
pub has_bids: bool,
pub allows_best_offer: bool,
pub item_num: u64,
}
#[instrument]
fn parse_ebay_results(filepath: PathBuf) -> Result<Vec<EbayResult>> {
let mut f = File::open(filepath).unwrap();
let mut contents = String::new();
f.read_to_string(&mut contents).unwrap();
let document = Html::parse_document(contents.as_str());
let selector = Selector::parse(".srp-results").unwrap();
let srp_results = document.select(&selector).next().unwrap();
let (elems, errs): (Vec<_>, Vec<_>) = get_items(&srp_results)?
.iter()
.map(parse_item)
.partition(Result::is_ok);
for err in errs {
error!("Hit error: {:?}", err);
}
Ok(elems.into_iter().map(Result::unwrap).collect())
}
#[instrument(skip_all)]
fn get_items<'a>(page: &'a ElementRef<'a>) -> Result<Vec<ElementRef<'a>>> {
let selector = Selector::parse(".s-item").unwrap();
let found = page.select(&selector);
Ok(found.collect())
}
#[instrument(skip_all)]
fn parse_item_title(binding: &ElementRef) -> Result<String> {
let selector = Selector::parse(".s-item__title").unwrap();
let found = binding.select(&selector);
let mut iter = found.into_iter();
if iter.clone().count() != 1 {
bail!("Expecting only a single title per result! Found:{:?}", iter.count());
}
let b1 = iter.next().unwrap().text().collect::<Vec<_>>();
let b2 = b1.iter().filter(|&e| *e != "New Listing").collect::<Vec<_>>();
if b2.len() != 1 {
bail!("Only expecting one title section per result!");
}
return Ok(b2.first().unwrap().to_string())
}
#[instrument(skip_all)]
fn parse_item_price(binding: &ElementRef) -> Result<f64> {
let selector = Selector::parse(".s-item__price").unwrap();
let found = binding.select(&selector);
let mut iter = found.into_iter();
if iter.clone().count() != 1 {
bail!("Expecting only a single price per result! Found:{}", iter.clone().count());
}
let b1 = iter.next().unwrap().text().collect::<Vec<_>>();
let b2 = b1.iter().filter(|&e| *e != "New Listing").collect::<Vec<_>>();
let mut price_str = match b2.len() {
1 => { *b1.first().unwrap() }
3 => {
if *b2[1] == " to " {
bail!("Ignoring ranged listings, range:{:?}", b2);
}
bail!("Found three elements in pricing but unexpected values:{:?}", b2);
}
_ => { bail!("Found unexpected pricing: {:?}", b2); }
};
price_str = price_str.trim_start_matches("$");
Ok(price_str.parse().unwrap())
}
#[instrument(skip_all)]
fn parse_item_shipping(binding: &ElementRef) -> Result<f64> {
let free_x_days_shipping = {
let selector = Selector::parse(".s-item__freeXDays").unwrap();
match binding.select(&selector).count() {
0 => { false }
1 => { true }
unknown => {
bail!("Expecting only a single item__freeXDays per result! Found:{}", unknown);
}
}
};
if free_x_days_shipping {
return Ok(0.00);
}
let selector = Selector::parse(".s-item__shipping").unwrap();
let found = binding.select(&selector);
let mut iter = found.into_iter();
if iter.clone().count() != 1 {
bail!("Expecting only a single shipping price per result! Found:{}", iter.clone().count());
}
let b1 = iter.next().unwrap().text().collect::<Vec<_>>();
if b1.len() != 1 {
bail!("Expected only a single shipping price per result! Found:{:?}", b1);
}
let price_str = *b1.first().unwrap();
if price_str == "Free shipping" {
return Ok(0.00);
}
let price_otherstr = Regex::new(r"\d+\.\d+")
.unwrap()
.find(price_str)
.unwrap().as_str();
Ok(price_otherstr.parse().unwrap())
}
#[instrument(skip_all)]
fn parse_item_ebay_itm(binding: &ElementRef) -> Result<u64> {
let selector = Selector::parse(".s-item__link").unwrap();
let found = binding.select(&selector);
let mut iter = found.into_iter();
if iter.clone().count() != 1 {
bail!("Expecting only a single item link per result! Found:{}", iter.clone().count());
}
let b1 = iter.next().unwrap().attr("href").into_iter().collect::<Vec<_>>();
if b1.len() != 1 {
bail!("Expected only a single item link per result! Found:{:?}", b1);
}
let mut url = *b1.first().unwrap();
url = url.trim_start_matches("https://www.ebay.com/itm/");
let price_otherstr = Regex::new(r"\d+")
.unwrap()
.find(url)
.unwrap().as_str();
Ok(price_otherstr.parse().unwrap())
}
#[instrument(skip_all)]
fn item_has_bids(binding: &ElementRef) -> bool {
let selector_bids = Selector::parse(".s-item__bids").unwrap();
// let selector_bidcount = Selector::parse("s-item__bidCount").unwrap();
match binding.select(&selector_bids).count() {
0 => { false }
1 => { true }
uhm => { error!("Found {} an unexpected {} times", selector_bids.to_css_string(), uhm); false }
}
}
fn item_has_bestoffer(binding: &ElementRef) -> bool {
let selector_bids = Selector::parse(".s-item__purchaseOptions").unwrap();
let elems: Vec<&str> = binding.select(&selector_bids)
.map(|e| e.text().collect::<Vec<_>>())
.collect::<Vec<_>>()
.into_iter().flatten()
.collect();
elems.contains(&"or Best Offer")
}
#[instrument(skip_all)]
fn parse_item(elem: &ElementRef) -> Result<EbayResult> {
Ok(EbayResult {
price: parse_item_price(elem)?,
title: parse_item_title(elem)?,
has_bids: item_has_bids(elem),
shipping: parse_item_shipping(elem)?,
item_num: parse_item_ebay_itm(elem)?,
allows_best_offer: item_has_bestoffer(elem)
})
}
fn main() -> Result<()>{
fn main() -> Result<()> {
tracing::subscriber::set_global_default(
FmtSubscriber::builder()
.with_max_level(tracing::Level::INFO)
.finish()
.finish(),
)
.expect("setting default subscriber failed");
.expect("setting default subscriber failed");
let parsed_files = vec![ParsedFile::default(); 0];
let mut ebay_ctx = ebay_fetcher::Context::default();
ebay_ctx.ebay_fetch_html("filename".to_string(), "someurl".to_string(), "somedir".to_string())?;
// let parsed_files = vec![ParsedFile::default(); 0];
// let mut ebay_ctx = ebay_fetcher::Context::default();
// ebay_ctx.ebay_fetch_html(
// "filename".to_string(),
// "someurl".to_string(),
// "somedir".to_string(),
// )?;
for e in parse_ebay_results(PathBuf::from("EbayScrape_ryzen_1713039640.html"))? {
info!("{:?}", e);

5
src/parser/common.rs Normal file
View File

@ -0,0 +1,5 @@
#[derive(Debug, Clone)]
pub enum Pricing {
Singular(f64),
Range(f64, f64),
}

148
src/parser/listing.rs Normal file
View File

@ -0,0 +1,148 @@
use anyhow::Result;
use reqwest::Url;
use scraper::{Html, Selector};
use std::{fs::File, io::Read, path::PathBuf, str::FromStr};
use strum::*;
use tracing::error;
#[derive(Clone, Copy, EnumString, Debug, PartialEq)]
pub enum Condition {
New,
OpenBox,
RefurbishedCertified,
RefurbishedExcellent,
RefurbishedVeryGood,
ReburbishedGood,
Used,
PartsOrNotWorking,
}
#[derive(Clone, PartialEq, Debug)]
pub enum Description {
Text(String),
IframeURL(Url),
}
#[derive(Clone)]
pub struct Listing {
pub item_num: u64,
pub condition: Condition,
pub condition_notes: String,
pub description: Description,
}
impl Listing {
pub fn from_file(filepath: PathBuf) -> Result<Self> {
let mut f = File::open(filepath).unwrap();
let mut contents = String::new();
f.read_to_string(&mut contents).unwrap();
let document = Html::parse_document(contents.as_str());
let condition_res = document
.select(&Selector::parse(".x-item-condition-text").unwrap())
.next()
.unwrap()
.text()
.take(1)
.collect::<Vec<_>>()
.concat();
let condition_notes_res = document
.select(&Selector::parse(".ux-labels-values--sellerNotes").unwrap())
.next()
.unwrap()
.text()
.skip_while(|e| !e.contains("about the seller notes"))
.collect::<Vec<_>>()[1]
.trim_start_matches('“')
.trim_end_matches('”');
let description_url = document
.select(&Selector::parse(".d-item-description").unwrap())
.next()
.unwrap()
.select(&Selector::parse("iframe").unwrap())
.next()
.unwrap()
.attr("src")
.unwrap();
Ok(Self {
condition: Condition::from_str(&condition_res)?,
condition_notes: condition_notes_res.to_owned(),
description: Description::IframeURL(Url::parse(description_url).unwrap()),
item_num: 0,
})
}
fn parse_description_iframe(html: &Html) -> Option<&str> {
html.select(&Selector::parse(".d-item-description").ok()?)
.next()?
.select(&Selector::parse("iframe").unwrap())
.next()?
.attr("src")
.to_owned()
}
fn parse_description_text(html: &Html) -> Option<String> {
let s = html
.select(&Selector::parse(".d-item-description").ok()?)
.next()?
.text()
.collect::<Vec<_>>();
Some(s.concat())
}
}
#[cfg(test)]
mod tests {
use super::*;
// use test_log::test;
use mistralrs::{
IsqType, TextMessageRole, VisionLoaderType, VisionMessages, VisionModelBuilder,
};
use tokio;
#[tokio::test(flavor = "multi_thread")]
async fn it_works() -> Result<()> {
// let listing = Listing::from_file(
// "tests/html/KAMRUI Mini PC Core i7-10710U 1.1GHz 16GB 512GB UHD Graphics CK10 _ eBay.html".into(),
// )
// .unwrap();
// assert_eq!(listing.condition, Condition::Used);
// assert_eq!(listing.condition_notes, "4 of 5. This item is gently used. The item shows minor signs of wear and tear including scuff marks and worn finishes. Please refer to the pictures to get a better idea of the physical condition. We could not get Windows to activate properly, and thus it is the new owner's expense/responsibility to activate. There are also a host of drivers and updates needed at the new owner's expense.");
// assert_eq!(listing.item_num, 0);
// assert_eq!(listing.description, Description::IframeURL(Url::parse(
// "https://vi.vipr.ebaydesc.com/itmdesc/276620722441?t=0&category=179&seller=jaybrokers&excSoj=1&ver=0&excTrk=1&lsite=0&ittenable=true&domain=ebay.com&descgauge=1&cspheader=1&oneClk=2&secureDesc=1"
// ).unwrap()));
// const MODEL_ID: &str = "Qwen/Qwen2-VL-7B-Instruct";
const MODEL_ID: &str = "HuggingFaceTB/SmolVLM-Instruct";
let model = VisionModelBuilder::new(MODEL_ID, VisionLoaderType::Idefics3)
.with_isq(IsqType::Q8_0)
.with_logging()
// .from_max_edge(800)
// .with_force_cpu()
.build()
.await?;
// let ipath = "tests/2024-11-27_21-01.png";
let ipath = "tests/2024-11-27_21-01_40percent.png";
let image = image::load_from_memory(&tokio::fs::read(ipath).await.unwrap()).unwrap();
let messages = VisionMessages::new().add_image_message(
TextMessageRole::User,
"This is an ebay product listing. Describe as JSON the processor model, monitor size, RAM size, and disk capacity.",
image.resize(600, 300, image::imageops::FilterType::Lanczos3),
&model,
)?;
let response = model.send_chat_request(messages).await?;
println!("{}", response.choices[0].message.content.as_ref().unwrap());
println!("{:?}", response);
let a = tokio::fs::read("aaaatests/2024-11-27_21-01.png").await?;
Ok(())
}
}

3
src/parser/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod common;
pub mod listing;
pub mod search_results;

View File

@ -0,0 +1,243 @@
use crate::parser::common::*;
use anyhow::{bail, Result};
use regex::Regex;
use scraper::{selector::ToCss, ElementRef, Html, Selector};
use std::{fs::File, io::Read, path::PathBuf};
use tracing::error;
#[derive(Debug, Clone)]
pub struct EbayResult {
pub price: Pricing,
pub shipping: f64,
pub title: String,
pub has_bids: bool,
pub allows_best_offer: bool,
pub item_num: u64,
}
pub fn parse_ebay_results(filepath: PathBuf) -> Result<Vec<EbayResult>> {
let mut f = File::open(filepath).unwrap();
let mut contents = String::new();
f.read_to_string(&mut contents).unwrap();
let document = Html::parse_document(contents.as_str());
let selector = Selector::parse(".srp-results").unwrap();
let srp_results = document.select(&selector).next().unwrap();
let (elems, errs): (Vec<_>, Vec<_>) = get_items(&srp_results)?
.iter()
.map(parse_item)
.partition(Result::is_ok);
for err in errs {
error!("Hit error: {:?}", err);
}
Ok(elems.into_iter().map(Result::unwrap).collect())
}
fn get_items<'a>(page: &'a ElementRef<'a>) -> Result<Vec<ElementRef<'a>>> {
let selector = Selector::parse(".s-item").unwrap();
let found = page.select(&selector);
Ok(found.collect())
}
fn parse_item_title(binding: &ElementRef) -> Result<String> {
let selector = Selector::parse(".s-item__title").unwrap();
let found = binding.select(&selector);
let mut iter = found.into_iter();
if iter.clone().count() != 1 {
bail!(
"Expecting only a single title per result! Found:{:?}",
iter.count()
);
}
let b1 = iter.next().unwrap().text().collect::<Vec<_>>();
let b2 = b1
.iter()
.filter(|&e| *e != "New Listing")
.collect::<Vec<_>>();
if b2.len() != 1 {
bail!("Only expecting one title section per result!");
}
return Ok(b2.first().unwrap().to_string());
}
fn parse_item_price(binding: &ElementRef) -> Result<Pricing> {
let selector = Selector::parse(".s-item__price").unwrap();
let found = binding.select(&selector);
let mut iter = found.clone().into_iter();
if iter.clone().count() != 1 {
bail!(
"Expecting only a single .s-item__price per result! Found:{} elems",
iter.clone().count()
);
}
let b = iter
.next()
.unwrap()
.text()
.filter(|e| !e.contains("New Listing"))
.filter(|e| !e.contains(" to "))
.map(|e| e.trim_start_matches("$"))
.map(|s| s.parse::<f32>().unwrap())
.collect::<Vec<_>>();
match b.len() {
1 => Ok(Pricing::Singular(b[0].into())),
2 => Ok(Pricing::Range(b[0].into(), b[1].into())),
_ => bail!("Failed parsing {:?} as 1 or 2 prices", b),
}
}
fn parse_item_shipping(binding: &ElementRef) -> Result<f64> {
let free_x_days_shipping = {
let selector = Selector::parse(".s-item__freeXDays").unwrap();
match binding.select(&selector).count() {
0 => false,
1 => true,
unknown => {
bail!(
"Expecting only a single item__freeXDays per result! Found:{}",
unknown
);
}
}
};
if free_x_days_shipping {
return Ok(0.00);
}
let selector = Selector::parse(".s-item__shipping").unwrap();
let found = binding.select(&selector);
let mut iter = found.into_iter();
if iter.clone().count() != 1 {
bail!(
"Expecting only a single shipping price per result! Found:{}",
iter.clone().count()
);
}
let b1 = iter.next().unwrap().text().collect::<Vec<_>>();
if b1.len() != 1 {
bail!(
"Expected only a single shipping price per result! Found:{:?}",
b1
);
}
let price_str = *b1.first().unwrap();
if price_str == "Free shipping" {
return Ok(0.00);
}
let price_otherstr = Regex::new(r"\d+\.\d+")
.unwrap()
.find(price_str)
.unwrap()
.as_str();
Ok(price_otherstr.parse().unwrap())
}
fn parse_item_ebay_itm(binding: &ElementRef) -> Result<u64> {
let selector = Selector::parse(".s-item__link").unwrap();
let found = binding.select(&selector);
let mut iter = found.into_iter();
if iter.clone().count() != 1 {
bail!(
"Expecting only a single item link per result! Found:{}",
iter.clone().count()
);
}
let b1 = iter
.next()
.unwrap()
.attr("href")
.into_iter()
.collect::<Vec<_>>();
if b1.len() != 1 {
bail!(
"Expected only a single item link per result! Found:{:?}",
b1
);
}
let mut url = *b1.first().unwrap();
url = url.trim_start_matches("https://www.ebay.com/itm/");
let price_otherstr = Regex::new(r"\d+").unwrap().find(url).unwrap().as_str();
Ok(price_otherstr.parse().unwrap())
}
fn item_has_bids(binding: &ElementRef) -> bool {
let selector_bids = Selector::parse(".s-item__bids").unwrap();
// let selector_bidcount = Selector::parse("s-item__bidCount").unwrap();
match binding.select(&selector_bids).count() {
0 => false,
1 => true,
uhm => {
error!(
"Found {} an unexpected {} times",
selector_bids.to_css_string(),
uhm
);
false
}
}
}
fn item_has_bestoffer(binding: &ElementRef) -> bool {
let selector_bids = Selector::parse(".s-item__purchaseOptions").unwrap();
let elems: Vec<&str> = binding
.select(&selector_bids)
.map(|e| e.text().collect::<Vec<_>>())
.collect::<Vec<_>>()
.into_iter()
.flatten()
.collect();
elems.contains(&"or Best Offer")
}
fn parse_item(elem: &ElementRef) -> Result<EbayResult> {
Ok(EbayResult {
price: parse_item_price(elem)?,
title: parse_item_title(elem)?,
has_bids: item_has_bids(elem),
shipping: parse_item_shipping(elem)?,
item_num: parse_item_ebay_itm(elem)?,
allows_best_offer: item_has_bestoffer(elem),
})
}
#[cfg(test)]
mod tests {
use super::*;
use test_log::test;
use tokio;
#[test(tokio::test)]
async fn it_works() {
// Should have been 60, but alas.
assert_eq!(
parse_ebay_results("tests/html/EbayScrape_16GB_100to200_Used_1732476548.html".into())
.unwrap()
.len(),
60 - 2 - 1
);
assert_eq!(
parse_ebay_results("tests/html/EbayScrape_ryzen_1713039640.html".into())
.unwrap()
.len(),
60 - 2 - 1
);
}
}

BIN
tests/2024-11-27_21-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
tests/IMG_6245.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,253 @@
@import url(https://fonts.googleapis.com/css?family=Montserrat:400,700);
@import url('https://fonts.googleapis.com/css?family=Raleway:600,700');
@import url('https://fonts.googleapis.com/css?family=Lato:400,700');
body {
color: #40474f;
font-size: 14px;
font-family: Lato, Arial, Helvetica, sans-serif;
background-color: white;
margin: 0
}
p {
font-size: 14px;
font-family: Lato, Arial, Helvetica, sans-serif;
line-height: 18px;
margin: 2px 0 9px
}
h1 {
font-family: Montserrat, sans-serif;
font-size: 36px;
color: #0076be;
margin-top: 10px;
margin-bottom: 40px;
font-weight: bold;
}
h2 {
font-family: Montserrat, sans-serif;
font-size: 24px;
color: #0076be;
font-weight: bold;
}
h3 {
font-family: Montserrat, sans-serif;
font-size: 24px;
color: #3f474f;
font-weight: bold;
}
h4 {
font-family: Montserrat, sans-serif;
font-size: 18px;
color: #0076be;
margin-top: 3px;
margin-bottom: 3px;
font-weight: bold;
}
h5 {
font-family: Montserrat, sans-serif;
font-size: 16px;
color: #3f474f;
margin-top: 3px;
margin-bottom: 3px;
font-weight: bold;
}
h6 {
font-family: Montserrat, sans-serif;
font-size: 16px;
color: #40474f;
margin-top: 3px;
margin-bottom: 6px;
font-weight: bold;
}
ul {
margin-top: 5px;
margin-left: 0px;
padding-left: 20px
font-family: Lato, Arial, Helvetica, sans-serif;
list-style-type: square;
}
ol {
margin-top: 5px;
margin-left: 0px;
padding-left: 20px;
font-family: Lato, Arial, Helvetica, sans-serif;
list-style: none;
counter-reset: li;
}
li {
font-family: Lato, Arial, Helvetica, sans-serif;
counter-increment: li;
padding-bottom: 0.5em;
}
a {
color: #0076be;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.wrapper {
text-align: center;
width: 100%;
}
.content-wrapper {
width: 100%;
margin-right: auto;
margin-left: auto;
}
.header-group {
font-family: Arial, sans-serif;
color: #000;
text-align: left;
}
.mantra {
height: 35px;
background-color: #40474f;
}
.header {
height: 66px;
border-bottom-width: 2px;
border-bottom-style: solid;
border-bottom-color: #8e8e8e;
}
.logo {
padding-left: 25px;
}
.menu {
font-family: Arial, sans-serif;
color: #40474f;
text-align: left;
position: relative;
top: -27px;
left: 120px;
width: 600px;
overflow: visible;
font-size: 14px;
}
.menu span {
font-family: Arial, sans-serif;
margin-right: 15px;
margin-left: 15px;
}
.menu a {
font-family: Arial, sans-serif;
color: #40474f;
}
.menu a:hover {
text-decoration: none;
}
menu a:visited {
color: #40474f;
}
.content {
text-align: left;
font-size: 14px;
padding-top: 40px;
padding-right: 50px;
padding-bottom: 40px;
padding-left: 50px;
}
#title {
font-family: Montserrat, sans-serif;
font-size: 24px;
color: #0076be;
font-weight: bold;
}
#specs {
}
#specs div {
margin-top: 15px;
margin-bottom: 2px;
font-family: Lato, Arial, Helvetica, sans-serif;
}
#specs span {
font-family: Montserrat, sans-serif;
font-size: 16px;
color: #3f474f;
font-weight: bold;
}
.terms {
font-size: 14px;
color: #3f474f;
margin-top: 50px;
margin-bottom: 50px;
}
.term-box {
padding: 24px;
margin-top: 24px;
margin-bottom: 24px;
background-color: #f8f8f8;
border: 1px solid #3f474f;
}
.term-box div {
font-family: Montserrat, sans-serif;
font-size: 18px;
color: #3f474f;
margin-bottom: 4px;
font-weight: bold;
}
.term-box p {
font-size: 14px;
font-family: Lato, Arial, Helvetica, sans-serif;
}
.pledge {
font-family: Raleway, sans-serif;
padding-top: 32px;
padding-bottom: 20px;
text-align: center;
}
.pledge span{
font-family: Raleway, sans-serif;
font-size: 32px;
color: #0076be;
font-weight: bold;
font-style: italic;
}
.term-box ol li::before {
content: counter(li);
color: #0076be;
font-weight: bold;
display: inline-block;
width: 1em;
margin-left: -1.5em;
margin-right: 0.5em;
text-align: right;
direction: rtl;
}
.highlight {
font-family: Raleway, sans-serif;
color: #0076be;
font-weight: bold;
font-style: italic;
text-transform: uppercase;
}
.button, #button {
font-family: Lato, Arial, Helvetica, sans-serif;
color:#FFF;
display:inline-block;
font-size:14px;
border:1px solid #fff;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
text-align:center;
height: 36px;
padding-top: 0;
padding-right: 18px;
padding-bottom: 0;
padding-left: 18px;
font-weight: bold;
line-height: 36px;
background-color: #003e6b;
cursor:pointer;
text-transform: uppercase;
margin-top: 20px;
margin-right: 0px;
margin-bottom: 20px;
margin-left: 0px;
}

View File

@ -0,0 +1 @@
.x-item-description-child{font-family:"Market Sans",Arial,sans-serif;line-height:1.43;text-indent:initial;white-space:normal;font-weight:normal;font-style:normal;text-align:start;font-variant:normal}.x-item-description-child div#ds_div{text-align:start}.x-diagnostics{margin:2rem 1rem}@media(max-width:768px){.x-diagnostics{margin:0}}.x-diagnostics h2{display:inline-block;width:100%}.x-diagnostics details{border:1px solid #aaa;border-radius:4px;padding:.5rem .5rem 0;margin:.5rem 0;word-wrap:break-word}.x-diagnostics summary{font-weight:bold;margin:-0.5rem -0.5rem 0;padding:.5rem;cursor:pointer}.x-diagnostics details[open]{padding:.5rem}.x-diagnostics details[open] summary{border-bottom:1px solid #aaa;margin-bottom:.5rem}

File diff suppressed because one or more lines are too long