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',
|
||||
slug: 'pissing',
|
||||
},
|
||||
{
|
||||
name: 'pole dancing',
|
||||
slug: 'pole-dancing',
|
||||
},
|
||||
{
|
||||
name: 'POV',
|
||||
slug: 'pov',
|
||||
|
@ -2423,6 +2427,10 @@ const aliases = [
|
|||
name: 'coroas',
|
||||
for: 'milf',
|
||||
},
|
||||
{
|
||||
name: 'strip pole dancing',
|
||||
for: 'strip-pole-dancing',
|
||||
},
|
||||
];
|
||||
|
||||
const priorities = [ // higher index is higher priority
|
||||
|
|
|
@ -323,6 +323,11 @@ const networks = [
|
|||
name: 'First Anal Quest',
|
||||
url: 'http://www.firstanalquest.com',
|
||||
},
|
||||
{
|
||||
slug: 'theflourish',
|
||||
name: 'The Flourish',
|
||||
url: 'https://theflourish.io',
|
||||
},
|
||||
{
|
||||
slug: 'forbondage',
|
||||
name: 'ForBondage',
|
||||
|
|
|
@ -717,6 +717,9 @@ const sites = [
|
|||
slug: 'archangel',
|
||||
name: 'ArchAngel',
|
||||
url: 'https://www.archangelvideo.com',
|
||||
parameters: {
|
||||
path: '/tour',
|
||||
},
|
||||
},
|
||||
// ASSYLUM
|
||||
{
|
||||
|
@ -3842,6 +3845,39 @@ const sites = [
|
|||
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
|
||||
{
|
||||
name: 'Crowd Bondage',
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
// ALSO USED BY THE FLOURISH
|
||||
|
||||
const unprint = require('unprint');
|
||||
|
||||
const slugify = require('../utils/slugify');
|
||||
|
@ -29,12 +31,27 @@ function scrapeAll(scenes) {
|
|||
}));
|
||||
|
||||
const poster = query.img('img.mainThumb');
|
||||
const previewCount = query.number('img.mainThumb', { attribute: 'cnt' });
|
||||
|
||||
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);
|
||||
|
||||
|
@ -42,7 +59,7 @@ function scrapeAll(scenes) {
|
|||
});
|
||||
}
|
||||
|
||||
function scrapeScene({ query, html }, { url }) {
|
||||
function scrapeScene({ query, html }, { url, entity, baseRelease }) {
|
||||
const release = { url };
|
||||
|
||||
release.title = query.content('.title h2');
|
||||
|
@ -56,18 +73,35 @@ function scrapeScene({ query, html }, { url }) {
|
|||
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)) {
|
||||
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.photoCount = query.number('.info', { match: /(\d+) photos/i, matchIndex: 1 });
|
||||
release.entryId = getEntryId(release);
|
||||
|
||||
return release;
|
||||
|
@ -129,8 +163,8 @@ function scrapeProfile({ query, element }, { url, entity }) {
|
|||
return profile;
|
||||
}
|
||||
|
||||
async function fetchLatest(channel, page = 1) {
|
||||
const url = `${channel.url}/tour/categories/movies_${page}_d.html`;
|
||||
async function fetchLatest(channel, page = 1, context) {
|
||||
const url = `${channel.url}${context.parameters.path || ''}/categories/movies_${page}_d.html`;
|
||||
const res = await unprint.get(url, { selectAll: '.item-video' });
|
||||
|
||||
if (res.ok) {
|
||||
|
@ -140,11 +174,11 @@ async function fetchLatest(channel, page = 1) {
|
|||
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 [
|
||||
actorUrl,
|
||||
`${entity.url}/tour/models/${slugify(actorName, '-')}.html`,
|
||||
`${entity.url}/tour/models/${slugify(actorName, '')}.html`,
|
||||
`${entity.url}${parameters.path || ''}/models/${slugify(actorName, '-')}.html`,
|
||||
`${entity.url}${parameters.path || ''}/models/${slugify(actorName, '')}.html`,
|
||||
].reduce(async (chain, url) => {
|
||||
const prevRes = await chain;
|
||||
|
||||
|
|
|
@ -153,6 +153,7 @@ const scrapers = {
|
|||
sexyhub: mindgeek,
|
||||
spizoo,
|
||||
swallowsalon: julesjordan,
|
||||
theflourish: archangel,
|
||||
teencoreclub,
|
||||
teenmegaworld,
|
||||
teamskeet,
|
||||
|
@ -294,6 +295,11 @@ const scrapers = {
|
|||
silviasaint: famedigital,
|
||||
spizoo,
|
||||
swallowed: mikeadriano,
|
||||
milfcandy: archangel,
|
||||
theflourishamateurs: archangel,
|
||||
theflourishpov: archangel,
|
||||
theflourishfetish: archangel,
|
||||
theflourishxxx: archangel,
|
||||
teamskeet,
|
||||
teencoreclub,
|
||||
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.scenes = scrapeAll(unprint.initAll(query.all('.video-list .thumb')), entity);
|
||||
|
||||
console.log(bio);
|
||||
console.log(profile);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
|
|