Added The Flourish, adapted Arch Angel scraper.
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 98 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 32 KiB |
|
@ -855,6 +855,10 @@ const tags = [
|
||||||
name: 'pissing',
|
name: 'pissing',
|
||||||
slug: 'pissing',
|
slug: 'pissing',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'pole dancing',
|
||||||
|
slug: 'pole-dancing',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'POV',
|
name: 'POV',
|
||||||
slug: 'pov',
|
slug: 'pov',
|
||||||
|
@ -2423,6 +2427,10 @@ const aliases = [
|
||||||
name: 'coroas',
|
name: 'coroas',
|
||||||
for: 'milf',
|
for: 'milf',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'strip pole dancing',
|
||||||
|
for: 'strip-pole-dancing',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const priorities = [ // higher index is higher priority
|
const priorities = [ // higher index is higher priority
|
||||||
|
|
|
@ -323,6 +323,11 @@ const networks = [
|
||||||
name: 'First Anal Quest',
|
name: 'First Anal Quest',
|
||||||
url: 'http://www.firstanalquest.com',
|
url: 'http://www.firstanalquest.com',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slug: 'theflourish',
|
||||||
|
name: 'The Flourish',
|
||||||
|
url: 'https://theflourish.io',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
slug: 'forbondage',
|
slug: 'forbondage',
|
||||||
name: 'ForBondage',
|
name: 'ForBondage',
|
||||||
|
|
|
@ -717,6 +717,9 @@ const sites = [
|
||||||
slug: 'archangel',
|
slug: 'archangel',
|
||||||
name: 'ArchAngel',
|
name: 'ArchAngel',
|
||||||
url: 'https://www.archangelvideo.com',
|
url: 'https://www.archangelvideo.com',
|
||||||
|
parameters: {
|
||||||
|
path: '/tour',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
// ASSYLUM
|
// ASSYLUM
|
||||||
{
|
{
|
||||||
|
@ -3842,6 +3845,39 @@ const sites = [
|
||||||
layout: 'c',
|
layout: 'c',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
// FLOURISH
|
||||||
|
{
|
||||||
|
slug: 'theflourishxxx',
|
||||||
|
name: 'The Flourish XXX',
|
||||||
|
url: 'https://tour.theflourishxxx.com',
|
||||||
|
parent: 'theflourish',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'theflourishamateurs',
|
||||||
|
name: 'The Flourish Amateurs',
|
||||||
|
url: 'https://tour.theflourishamateurs.com',
|
||||||
|
parent: 'theflourish',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'theflourishfetish',
|
||||||
|
name: 'The Flourish Fetish',
|
||||||
|
url: 'https://tour.theflourishfetish.com',
|
||||||
|
parent: 'theflourish',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'theflourishpov',
|
||||||
|
name: 'The Flourish POV',
|
||||||
|
url: 'https://tour.theflourishxxx.com',
|
||||||
|
tags: ['pov'],
|
||||||
|
parent: 'theflourish',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
slug: 'milfcandy',
|
||||||
|
name: 'MILF Candy',
|
||||||
|
url: 'https://tour.milfcandy.com',
|
||||||
|
tags: ['milf'],
|
||||||
|
parent: 'theflourish',
|
||||||
|
},
|
||||||
// FOR BONDAGE
|
// FOR BONDAGE
|
||||||
{
|
{
|
||||||
name: 'Crowd Bondage',
|
name: 'Crowd Bondage',
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// ALSO USED BY THE FLOURISH
|
||||||
|
|
||||||
const unprint = require('unprint');
|
const unprint = require('unprint');
|
||||||
|
|
||||||
const slugify = require('../utils/slugify');
|
const slugify = require('../utils/slugify');
|
||||||
|
@ -29,12 +31,27 @@ function scrapeAll(scenes) {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const poster = query.img('img.mainThumb');
|
const poster = query.img('img.mainThumb');
|
||||||
|
const previewCount = query.number('img.mainThumb', { attribute: 'cnt' });
|
||||||
|
|
||||||
if (poster && !placeholder.test(poster)) {
|
if (poster && !placeholder.test(poster)) {
|
||||||
release.poster = poster;
|
const posterFallbacks = [
|
||||||
|
poster.replace('-1x', '-3x'),
|
||||||
|
poster.replace('-1x', '-2x'),
|
||||||
|
poster.replace('-1x', '-4x'),
|
||||||
|
poster,
|
||||||
|
];
|
||||||
|
|
||||||
|
release.poster = posterFallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
release.photoCount = query.number('.timeDate');
|
if (previewCount) {
|
||||||
|
release.photos = Array.from(
|
||||||
|
{ length: previewCount - 1 },
|
||||||
|
(value, index) => [3, 2, 4, 1].map((scale) => unprint.prefixUrl(query.img('img.mainThumb', { attribute: `src${index + 1}_${scale}x` }))).filter(Boolean), // 4x is unnecessarily big and possibly upscaled
|
||||||
|
).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
release.photoCount = query.number('.timeDate', { match: /(\d+) photos/i, matchIndex: 1 });
|
||||||
|
|
||||||
release.entryId = getEntryId(release);
|
release.entryId = getEntryId(release);
|
||||||
|
|
||||||
|
@ -42,7 +59,7 @@ function scrapeAll(scenes) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeScene({ query, html }, { url }) {
|
function scrapeScene({ query, html }, { url, entity, baseRelease }) {
|
||||||
const release = { url };
|
const release = { url };
|
||||||
|
|
||||||
release.title = query.content('.title h2');
|
release.title = query.content('.title h2');
|
||||||
|
@ -56,18 +73,35 @@ function scrapeScene({ query, html }, { url }) {
|
||||||
url: unprint.query.url(actorEl, null),
|
url: unprint.query.url(actorEl, null),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const poster = query.img('.update_thumb') || html.match(/poster="(.*\.jpg)"/)?.[1];
|
const poster = unprint.prefixUrl(query.img('.update_thumb') || html.match(/poster="(.*\.jpg)"/)?.[1], entity.url);
|
||||||
|
|
||||||
if (poster && !placeholder.test(poster)) {
|
if (poster && !placeholder.test(poster)) {
|
||||||
release.poster = poster;
|
const posterFallbacks = [
|
||||||
|
poster.replace('-1x', '-3x'),
|
||||||
|
poster.replace('-1x', '-2x'),
|
||||||
|
poster.replace('-1x', '-4x'),
|
||||||
|
poster,
|
||||||
|
];
|
||||||
|
|
||||||
|
// scene page poster usually different from overview page, don't replace
|
||||||
|
if (baseRelease?.poster && baseRelease.poster !== poster) {
|
||||||
|
release.photos = baseRelease.photos
|
||||||
|
? [posterFallbacks, ...baseRelease.photos]
|
||||||
|
: [posterFallbacks];
|
||||||
|
} else {
|
||||||
|
release.poster = posterFallbacks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
release.trailer = html.match(/src="(.*\.mp4)"/)?.[1];
|
const trailer = html.match(/src="(.*\.mp4)"/)?.[1];
|
||||||
|
|
||||||
release.photoCount = query.number('.info', { match: /(\d+) photos/i, matchIndex: 1 });
|
if (trailer) {
|
||||||
|
release.trailer = unprint.prefixUrl(encodeURI(trailer), entity.url);
|
||||||
|
}
|
||||||
|
|
||||||
release.tags = query.contents('.info .tags a');
|
release.tags = query.contents('.info .tags a');
|
||||||
|
|
||||||
|
release.photoCount = query.number('.info', { match: /(\d+) photos/i, matchIndex: 1 });
|
||||||
release.entryId = getEntryId(release);
|
release.entryId = getEntryId(release);
|
||||||
|
|
||||||
return release;
|
return release;
|
||||||
|
@ -129,8 +163,8 @@ function scrapeProfile({ query, element }, { url, entity }) {
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchLatest(channel, page = 1) {
|
async function fetchLatest(channel, page = 1, context) {
|
||||||
const url = `${channel.url}/tour/categories/movies_${page}_d.html`;
|
const url = `${channel.url}${context.parameters.path || ''}/categories/movies_${page}_d.html`;
|
||||||
const res = await unprint.get(url, { selectAll: '.item-video' });
|
const res = await unprint.get(url, { selectAll: '.item-video' });
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
@ -140,11 +174,11 @@ async function fetchLatest(channel, page = 1) {
|
||||||
return res.status;
|
return res.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchProfile({ name: actorName, url: actorUrl }, { entity, include }) {
|
async function fetchProfile({ name: actorName, url: actorUrl }, { entity, include, parameters }) {
|
||||||
const res = await [
|
const res = await [
|
||||||
actorUrl,
|
actorUrl,
|
||||||
`${entity.url}/tour/models/${slugify(actorName, '-')}.html`,
|
`${entity.url}${parameters.path || ''}/models/${slugify(actorName, '-')}.html`,
|
||||||
`${entity.url}/tour/models/${slugify(actorName, '')}.html`,
|
`${entity.url}${parameters.path || ''}/models/${slugify(actorName, '')}.html`,
|
||||||
].reduce(async (chain, url) => {
|
].reduce(async (chain, url) => {
|
||||||
const prevRes = await chain;
|
const prevRes = await chain;
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@ const scrapers = {
|
||||||
sexyhub: mindgeek,
|
sexyhub: mindgeek,
|
||||||
spizoo,
|
spizoo,
|
||||||
swallowsalon: julesjordan,
|
swallowsalon: julesjordan,
|
||||||
|
theflourish: archangel,
|
||||||
teencoreclub,
|
teencoreclub,
|
||||||
teenmegaworld,
|
teenmegaworld,
|
||||||
teamskeet,
|
teamskeet,
|
||||||
|
@ -294,6 +295,11 @@ const scrapers = {
|
||||||
silviasaint: famedigital,
|
silviasaint: famedigital,
|
||||||
spizoo,
|
spizoo,
|
||||||
swallowed: mikeadriano,
|
swallowed: mikeadriano,
|
||||||
|
milfcandy: archangel,
|
||||||
|
theflourishamateurs: archangel,
|
||||||
|
theflourishpov: archangel,
|
||||||
|
theflourishfetish: archangel,
|
||||||
|
theflourishxxx: archangel,
|
||||||
teamskeet,
|
teamskeet,
|
||||||
teencoreclub,
|
teencoreclub,
|
||||||
teenmegaworld,
|
teenmegaworld,
|
||||||
|
|
|
@ -90,9 +90,6 @@ function scrapeProfile({ query }, url, entity) {
|
||||||
profile.avatar = query.img('.model-profile-image-picture source', { origin: entity.url, attribute: 'srcset' }) || query.img('.model-profile-image-picture img', { origin: entity.url });
|
profile.avatar = query.img('.model-profile-image-picture source', { origin: entity.url, attribute: 'srcset' }) || query.img('.model-profile-image-picture img', { origin: entity.url });
|
||||||
profile.scenes = scrapeAll(unprint.initAll(query.all('.video-list .thumb')), entity);
|
profile.scenes = scrapeAll(unprint.initAll(query.all('.video-list .thumb')), entity);
|
||||||
|
|
||||||
console.log(bio);
|
|
||||||
console.log(profile);
|
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|