Refactored Cherry Pimps to use unprint, added series as channels.
This commit is contained in:
parent
d0bb56e436
commit
b7beea60ce
|
|
@ -2703,32 +2703,160 @@ const sites = [
|
||||||
},
|
},
|
||||||
// CHERRY PIMPS
|
// CHERRY PIMPS
|
||||||
{
|
{
|
||||||
slug: 'cherrypimps',
|
|
||||||
name: 'Cherry Pimps',
|
name: 'Cherry Pimps',
|
||||||
alias: ['cps'],
|
slug: 'cherrypimps',
|
||||||
url: 'https://cherrypimps.com',
|
url: 'https://cherrypimps.com/series/cherrypimps.html',
|
||||||
description: 'CherryPimps your premium porn site to Download and Stream the hottest and most exclusive 4K HD videos and pictures on your phone, tablet, TV or console.',
|
|
||||||
parent: 'cherrypimps',
|
parent: 'cherrypimps',
|
||||||
parameters: {
|
|
||||||
extract: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'wildoncam',
|
|
||||||
name: 'Wild On Cam',
|
name: 'Wild On Cam',
|
||||||
|
slug: 'wildoncam',
|
||||||
|
url: 'https://cherrypimps.com/series/wild-on-cam.html',
|
||||||
alias: ['woc'],
|
alias: ['woc'],
|
||||||
url: 'https://wildoncam.com',
|
|
||||||
tags: ['live'],
|
|
||||||
parent: 'cherrypimps',
|
parent: 'cherrypimps',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'britneyamber',
|
name: 'Cherry of the Month',
|
||||||
|
slug: 'cherryofthemonth',
|
||||||
|
url: 'https://cherrypimps.com/series/cotm.html',
|
||||||
|
alias: ['cotm'],
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ALT',
|
||||||
|
slug: 'alt',
|
||||||
|
url: 'https://cherrypimps.com/series/alt.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Big Cock Mood',
|
||||||
|
slug: 'bigcockmood',
|
||||||
|
tags: ['bbc'],
|
||||||
|
alias: ['bcm'],
|
||||||
|
url: 'https://cherrypimps.com/series/bcm.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bush',
|
||||||
|
slug: 'bush',
|
||||||
|
url: 'https://cherrypimps.com/series/bush.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Busted',
|
||||||
|
slug: 'busted',
|
||||||
|
url: 'https://cherrypimps.com/series/busted.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cheese',
|
||||||
|
slug: 'cheese',
|
||||||
|
url: 'https://cherrypimps.com/series/cheese.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Confessions',
|
||||||
|
slug: 'confessions',
|
||||||
|
url: 'https://cherrypimps.com/series/confessions.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cucked',
|
||||||
|
slug: 'cucked',
|
||||||
|
tags: ['cuckold'],
|
||||||
|
url: 'https://cherrypimps.com/series/cucked.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Drilled',
|
||||||
|
slug: 'drilled',
|
||||||
|
url: 'https://cherrypimps.com/series/drilled.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Ebony',
|
||||||
|
slug: 'ebony',
|
||||||
|
tags: ['black'],
|
||||||
|
url: 'https://cherrypimps.com/series/ebony-xxx.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Exotic',
|
||||||
|
slug: 'exotic',
|
||||||
|
url: 'https://cherrypimps.com/series/exotic.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Femme',
|
||||||
|
slug: 'femme',
|
||||||
|
tags: ['lesbian'],
|
||||||
|
url: 'https://cherrypimps.com/series/femme.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Fresh',
|
||||||
|
slug: 'fresh',
|
||||||
|
url: 'https://cherrypimps.com/series/fresh.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Ginger',
|
||||||
|
slug: 'ginger',
|
||||||
|
tags: ['redhead'],
|
||||||
|
url: 'https://cherrypimps.com/series/ginger.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'GFE',
|
||||||
|
slug: 'gfe',
|
||||||
|
tags: ['vr'],
|
||||||
|
url: 'https://cherrypimps.com/series/gfe.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'MILF',
|
||||||
|
slug: 'milf',
|
||||||
|
tags: ['milf'],
|
||||||
|
url: 'https://cherrypimps.com/series/milf-xxx.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Pegged',
|
||||||
|
slug: 'pegged',
|
||||||
|
tags: ['pegging'],
|
||||||
|
url: 'https://cherrypimps.com/series/pegged.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Petite',
|
||||||
|
slug: 'petite',
|
||||||
|
url: 'https://cherrypimps.com/series/petite-xxx.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Taboo',
|
||||||
|
slug: 'taboo',
|
||||||
|
url: 'https://cherrypimps.com/series/taboo.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cherry Spot',
|
||||||
|
slug: 'cherryspot',
|
||||||
|
url: 'https://cherrypimps.com/series/cherry-spot.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Archives',
|
||||||
|
slug: 'cherrypimpsarchives',
|
||||||
|
url: 'https://cherrypimps.com/series/archives.html',
|
||||||
|
parent: 'cherrypimps',
|
||||||
|
},
|
||||||
|
{
|
||||||
name: 'Britney Amber',
|
name: 'Britney Amber',
|
||||||
|
slug: 'britneyamber',
|
||||||
|
delete: true,
|
||||||
url: 'https://www.britneyamber.com',
|
url: 'https://www.britneyamber.com',
|
||||||
parent: 'cherrypimps',
|
parent: 'cherrypimps',
|
||||||
parameters: {
|
|
||||||
extract: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
// CLIFF MEDIA / VANESSA CLIFF
|
// CLIFF MEDIA / VANESSA CLIFF
|
||||||
{
|
{
|
||||||
|
|
@ -9127,6 +9255,7 @@ const sites = [
|
||||||
{
|
{
|
||||||
slug: 'drilledxxx',
|
slug: 'drilledxxx',
|
||||||
name: 'Drilled.XXX',
|
name: 'Drilled.XXX',
|
||||||
|
delete: true,
|
||||||
url: 'https://drilled.xxx',
|
url: 'https://drilled.xxx',
|
||||||
tags: ['anal'],
|
tags: ['anal'],
|
||||||
parent: 'pimpxxx',
|
parent: 'pimpxxx',
|
||||||
|
|
@ -9134,6 +9263,7 @@ const sites = [
|
||||||
{
|
{
|
||||||
slug: 'cuckedxxx',
|
slug: 'cuckedxxx',
|
||||||
name: 'Cucked.XXX',
|
name: 'Cucked.XXX',
|
||||||
|
delete: true,
|
||||||
url: 'https://cucked.xxx',
|
url: 'https://cucked.xxx',
|
||||||
tags: ['cuckold'],
|
tags: ['cuckold'],
|
||||||
parent: 'pimpxxx',
|
parent: 'pimpxxx',
|
||||||
|
|
@ -9141,6 +9271,7 @@ const sites = [
|
||||||
{
|
{
|
||||||
slug: 'familyxxx',
|
slug: 'familyxxx',
|
||||||
name: 'Family.XXX',
|
name: 'Family.XXX',
|
||||||
|
delete: true,
|
||||||
url: 'https://family.xxx',
|
url: 'https://family.xxx',
|
||||||
tags: ['family'],
|
tags: ['family'],
|
||||||
parent: 'pimpxxx',
|
parent: 'pimpxxx',
|
||||||
|
|
@ -9148,18 +9279,21 @@ const sites = [
|
||||||
{
|
{
|
||||||
slug: 'petitexxx',
|
slug: 'petitexxx',
|
||||||
name: 'Petite.XXX',
|
name: 'Petite.XXX',
|
||||||
|
delete: true,
|
||||||
url: 'https://petite.xxx',
|
url: 'https://petite.xxx',
|
||||||
parent: 'pimpxxx',
|
parent: 'pimpxxx',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'confessionsxxx',
|
slug: 'confessionsxxx',
|
||||||
name: 'Confessions.XXX',
|
name: 'Confessions.XXX',
|
||||||
|
delete: true,
|
||||||
url: 'https://confessions.xxx',
|
url: 'https://confessions.xxx',
|
||||||
parent: 'pimpxxx',
|
parent: 'pimpxxx',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
slug: 'bcmxxx',
|
slug: 'bcmxxx',
|
||||||
name: 'BCM.XXX',
|
name: 'BCM.XXX',
|
||||||
|
delete: true,
|
||||||
url: 'https://bcm.xxx',
|
url: 'https://bcm.xxx',
|
||||||
parent: 'pimpxxx',
|
parent: 'pimpxxx',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,92 +1,119 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const qu = require('../utils/qu');
|
const unprint = require('unprint');
|
||||||
|
|
||||||
const slugify = require('../utils/slugify');
|
const slugify = require('../utils/slugify');
|
||||||
|
const tryUrls = require('../utils/try-urls');
|
||||||
|
|
||||||
function scrapeAll(scenes, site) {
|
function scrapeAll(scenes) {
|
||||||
return scenes.map(({ query }) => {
|
return scenes.map(({ query }) => {
|
||||||
const url = query.url('.text-thumb a');
|
|
||||||
const { pathname } = new URL(url);
|
|
||||||
const channelUrl = query.url('.badge');
|
|
||||||
|
|
||||||
if (site?.parameters?.extract && query.q('.badge', true) !== site.name) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const release = {};
|
const release = {};
|
||||||
|
|
||||||
release.url = channelUrl ? `${channelUrl}${pathname}` : url;
|
const url = query.url('.item-title a');
|
||||||
|
const { pathname } = new URL(url);
|
||||||
|
|
||||||
|
release.url = url;
|
||||||
release.entryId = pathname.match(/\/trailers\/(.*).html/)[1];
|
release.entryId = pathname.match(/\/trailers\/(.*).html/)[1];
|
||||||
release.title = query.q('.text-thumb a', true);
|
|
||||||
|
|
||||||
release.date = query.date('.date', 'YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/);
|
release.title = query.content('.item-title a');
|
||||||
release.duration = query.dur('.date', /(\d{2}:)?\d{2}:\d{2}/);
|
|
||||||
|
|
||||||
release.actors = query.all('.category a', true);
|
release.date = query.date('.item-date', 'MMMM D, YYYY');
|
||||||
|
release.duration = query.duration('.item-date', /(\d{2}:)?\d{2}:\d{2}/);
|
||||||
|
|
||||||
release.poster = query.img('img.video_placeholder, .video-images img');
|
release.actors = query.all('.item-models a').map((actorEl) => ({
|
||||||
release.teaser = { src: query.trailer() };
|
name: unprint.query.content(actorEl),
|
||||||
|
url: unprint.query.url(actorEl, null),
|
||||||
|
}));
|
||||||
|
|
||||||
|
release.poster = query.img('.item-video-thumb', { attribute: 'data-videoposter' }) || query.img('img.video_placeholder');
|
||||||
|
release.teaser = query.video('.item-video-thumb', { attribute: 'data-videosrc' });
|
||||||
|
|
||||||
|
release.photoCount = query.number('.item-date', { match: /(\d+) photos/i, matchIndex: 1 });
|
||||||
|
release.channel = slugify(query.content('.item-sitename a'), '');
|
||||||
|
|
||||||
return release;
|
return release;
|
||||||
}).filter(Boolean);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeScene({ query, html }, url, _site, baseRelease) {
|
async function fetchLatest(channel, page = 1) {
|
||||||
const release = { url };
|
const slug = channel.parameters?.slug || new URL(channel.url).pathname.match(/\/series\/([\w-]+)/)[1];
|
||||||
|
const res = await unprint.get(`https://cherrypimps.com/categories/${slug}_${page}_d.html`, { selectAll: '.item-updates .item-video' });
|
||||||
|
|
||||||
const { pathname } = new URL(url);
|
if (res.ok) {
|
||||||
release.entryId = pathname.match(/\/\d+/)[0].slice(1);
|
return scrapeAll(res.context, channel);
|
||||||
|
|
||||||
release.title = query.q('.trailer-block_title', true);
|
|
||||||
release.description = query.q('.info-block:nth-child(3) .text', true);
|
|
||||||
release.date = query.date('.info-block_data .text', 'MMMM D, YYYY', /\w+ \d{1,2}, \d{4}/);
|
|
||||||
|
|
||||||
const duration = baseRelease?.duration || Number(query.q('.info-block_data .text', true).match(/(\d+)\s+min/)?.[1]) * 60;
|
|
||||||
if (duration) release.duration = duration;
|
|
||||||
|
|
||||||
release.actors = query.all('.info-block_data a[href*="/models"]', true);
|
|
||||||
release.tags = query.all('.info-block a[href*="/categories"]', true);
|
|
||||||
|
|
||||||
const posterEl = query.q('.update_thumb');
|
|
||||||
const poster = posterEl?.getAttribute('src0_3x') || posterEl?.getAttribute('src0_2x') || posterEl?.dataset.src;
|
|
||||||
|
|
||||||
if (poster && baseRelease?.poster) release.photos = [poster];
|
|
||||||
else if (poster) release.poster = poster;
|
|
||||||
|
|
||||||
const trailer = html.match(/video src="(.*?)"/);
|
|
||||||
|
|
||||||
if (trailer) {
|
|
||||||
release.trailer = trailer[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeScene({ query }, url) {
|
||||||
|
const release = { url };
|
||||||
|
const { pathname } = new URL(url);
|
||||||
|
|
||||||
|
release.entryId = pathname.match(/\/trailers\/(.*).html/)[1];
|
||||||
|
|
||||||
|
release.title = query.content('.item-title h1');
|
||||||
|
release.description = query.content('.update-info-block p');
|
||||||
|
|
||||||
|
release.date = query.date('.update-info-row:first-child', 'MMMM D, YYYY');
|
||||||
|
release.duration = query.duration('.update-info-row:last-child');
|
||||||
|
release.photoCount = query.number('.update-info-row:last-child', { match: /(\d+) photos/i, matchIndex: 1 });
|
||||||
|
|
||||||
|
release.actors = query.all('.models-list-thumbs .model-list-item').map((actorEl) => ({
|
||||||
|
name: unprint.query.content(actorEl, 'span'),
|
||||||
|
url: unprint.query.url(actorEl, 'a'),
|
||||||
|
avatar: [
|
||||||
|
unprint.query.img(actorEl, 'img', { attribute: 'src0_3x' }),
|
||||||
|
unprint.query.img(actorEl, 'img', { attribute: 'src0_2x' }),
|
||||||
|
unprint.query.img(actorEl, 'img', { attribute: 'src0_1x' }),
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
|
release.tags = query.contents('.update-info-block a[href*="categories/"]');
|
||||||
|
|
||||||
|
release.poster = [
|
||||||
|
query.img('.update_thumb', { attribute: 'src0_3x' }),
|
||||||
|
query.img('.update_thumb', { attribute: 'src0_2x' }),
|
||||||
|
query.img('.update_thumb', { attribute: 'src0_1x' }), // usually only this one available
|
||||||
|
].filter(Boolean);
|
||||||
|
|
||||||
|
// faux video trailer player redirects to signup
|
||||||
|
|
||||||
return release;
|
return release;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeProfile({ query }) {
|
async function fetchScene(url, site, release) {
|
||||||
const profile = {};
|
const res = await unprint.get(url);
|
||||||
|
|
||||||
const keys = query.all('.model-descr_line:not(.model-descr_rait) p.text span', true);
|
if (res.ok) {
|
||||||
const values = query.all('.model-descr_line:not(.model-descr_rait) p.text').map((el) => query.text(el));
|
return scrapeScene(res.context, url, site, release);
|
||||||
const bio = keys.reduce((acc, key, index) => ({ ...acc, [slugify(key, '_')]: values[index] }), {});
|
|
||||||
|
|
||||||
if (bio.height) profile.height = Number(bio.height.match(/\((\d+)\s*cm\)/)?.[1]);
|
|
||||||
if (bio.weight) profile.weight = Number(bio.weight.match(/\((\d+)kg\)/)?.[1]);
|
|
||||||
if (bio.race) profile.ethnicity = bio.race;
|
|
||||||
|
|
||||||
if (bio.date_of_birth) profile.birthdate = qu.extractDate(bio.date_of_birth, 'MMMM D, YYYY');
|
|
||||||
if (bio.birthplace) profile.birthPlace = bio.birthplace;
|
|
||||||
|
|
||||||
if (bio.measurements) {
|
|
||||||
const [bust, waist, hip] = bio.measurements.split('-');
|
|
||||||
if (!/\?/.test(bust)) profile.bust = bust;
|
|
||||||
if (!/\?/.test(waist)) profile.waist = waist;
|
|
||||||
if (!/\?/.test(hip)) profile.hip = hip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bio.hair) profile.hair = bio.hair;
|
return res.status;
|
||||||
if (bio.eyes) profile.eyes = bio.eyes;
|
}
|
||||||
|
|
||||||
if (/various/i.test(bio.tattoos)) profile.hasTattoos = true;
|
function scrapeProfile({ query }, url) {
|
||||||
|
const profile = { url };
|
||||||
|
|
||||||
|
const bio = Object.fromEntries(query.all('.model-stats li').map((bioEl) => [
|
||||||
|
slugify(unprint.query.content(bioEl, 'strong'), '_'),
|
||||||
|
unprint.query.text(bioEl),
|
||||||
|
]));
|
||||||
|
|
||||||
|
profile.height = Number(bio.height?.match(/\((\d+)\s*cm\)/)?.[1]) || null;
|
||||||
|
profile.weight = Number(bio.weight?.match(/\((\d+)\s*kg\)/)?.[1]) || null;
|
||||||
|
|
||||||
|
profile.age = parseInt(bio.age, 10) || null;
|
||||||
|
profile.dateOfBirth = unprint.extractDate(bio.date_of_birth, 'MMMM D, YYYY');
|
||||||
|
profile.birthPlace = bio.birthplace;
|
||||||
|
profile.ethnicity = bio.race;
|
||||||
|
|
||||||
|
profile.measurements = bio.measurements;
|
||||||
|
|
||||||
|
profile.hair = bio.hair_color;
|
||||||
|
profile.eyes = bio.eye_color;
|
||||||
|
|
||||||
|
if (/various|several/i.test(bio.tattoos)) profile.hasTattoos = true;
|
||||||
else if (/none/i.test(bio.tattoos)) profile.hasTattoos = false;
|
else if (/none/i.test(bio.tattoos)) profile.hasTattoos = false;
|
||||||
else if (bio.tattoos) {
|
else if (bio.tattoos) {
|
||||||
profile.hasTattoos = true;
|
profile.hasTattoos = true;
|
||||||
|
|
@ -100,47 +127,31 @@ function scrapeProfile({ query }) {
|
||||||
profile.piercings = bio.piercings;
|
profile.piercings = bio.piercings;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bio.aliases) profile.aliases = bio.aliases.split(',').map((alias) => alias.trim());
|
profile.aliases = bio.aliases?.split(',').map((alias) => alias.trim());
|
||||||
|
|
||||||
const avatar = query.q('.model-img img');
|
profile.avatar = [
|
||||||
profile.avatar = avatar.getAttribute('src0_3x') || avatar.getAttribute('src0_2x') || avatar.dataset.src;
|
query.img('.model-img img, .model_bio_thumb', { attribute: 'src0_3x' }),
|
||||||
|
query.img('.model-img img, .model_bio_thumb', { attribute: 'src0_2x' }),
|
||||||
const releases = query.all('.video-thumb');
|
query.img('.model-img img, .model_bio_thumb', { attribute: 'src0_1x' }),
|
||||||
profile.releases = scrapeAll(qu.initAll(releases));
|
];
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchLatest(site, page = 1) {
|
async function fetchProfile({ name: actorName, url: actorUrl }, { channel, network }) {
|
||||||
const url = site.parameters?.extract
|
const origin = new URL(channel?.url || network.url).origin;
|
||||||
? `https://cherrypimps.com/categories/movies_${page}.html`
|
|
||||||
: `${site.url}/categories/movies_${page}.html`;
|
|
||||||
const res = await qu.getAll(url, 'div.video-thumb');
|
|
||||||
|
|
||||||
return res.ok ? scrapeAll(res.items, site) : res.status;
|
const { res, url } = await tryUrls([
|
||||||
}
|
actorUrl,
|
||||||
|
`${origin}/models/${slugify(actorName, '')}.html`,
|
||||||
|
`${origin}/models/${slugify(actorName)}.html`,
|
||||||
|
]);
|
||||||
|
|
||||||
async function fetchScene(url, site, release) {
|
if (res.ok) {
|
||||||
const res = await qu.get(url);
|
return scrapeProfile(res.context, url);
|
||||||
|
}
|
||||||
|
|
||||||
return res.ok ? scrapeScene(res.item, url, site, release) : res.status;
|
return res.status;
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchProfile({ name: actorName }, { site, network, scraper }) {
|
|
||||||
const actorSlug = slugify(actorName);
|
|
||||||
const actorSlug2 = slugify(actorName, '');
|
|
||||||
|
|
||||||
const origin = site?.url || network.url;
|
|
||||||
|
|
||||||
const [url, url2] = ['cherrypimps', 'wildoncam'].includes(scraper)
|
|
||||||
? [`${origin}/models/${actorSlug}.html`, `${origin}/models/${actorSlug2}.html`]
|
|
||||||
: [`${origin}/models/${actorSlug}.html`, `${origin}/models/${actorSlug2}.html`];
|
|
||||||
|
|
||||||
const res = await qu.get(url);
|
|
||||||
if (res.ok) return scrapeProfile(res.item);
|
|
||||||
|
|
||||||
const res2 = await qu.get(url2);
|
|
||||||
return res2.ok ? scrapeProfile(res2.item) : res2.status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ async function scrapeProfile({ query }, url, include) {
|
||||||
if (tags.includes('tattoo') || tags.includes('tattoos')) profile.hasTattoos = true;
|
if (tags.includes('tattoo') || tags.includes('tattoos')) profile.hasTattoos = true;
|
||||||
if (tags.includes('piercing') || tags.includes('piercings')) profile.hasPiercings = true;
|
if (tags.includes('piercing') || tags.includes('piercings')) profile.hasPiercings = true;
|
||||||
|
|
||||||
profile.description = query.text('[class$="description"] [class*="more-less"]');
|
profile.description = query.content('[class$="description"] [class*="more-less"]');
|
||||||
profile.avatar = query.img('[class*="poster"] img') || null;
|
profile.avatar = query.img('[class*="poster"] img') || null;
|
||||||
|
|
||||||
if (include.releases) {
|
if (include.releases) {
|
||||||
|
|
|
||||||
|
|
@ -60,13 +60,19 @@ function scrapeScene({ query }, { url }) {
|
||||||
return release;
|
return release;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrapeProfile({ query }) {
|
function scrapeProfile({ query }, searchAvatar) {
|
||||||
const profile = {};
|
const profile = {};
|
||||||
|
|
||||||
profile.nationality = query.content('//h3[contains(text(), "Nationality:")]/span') || null;
|
profile.nationality = query.content('//h3[contains(text(), "Nationality:")]/span') || null;
|
||||||
profile.age = query.number('//h3[contains(text(), "Age:")]/span');
|
profile.age = query.number('//h3[contains(text(), "Age:")]/span');
|
||||||
|
|
||||||
profile.avatar = query.img();
|
const pageAvatar = query.img();
|
||||||
|
|
||||||
|
profile.avatar = searchAvatar || pageAvatar;
|
||||||
|
|
||||||
|
if (searchAvatar) {
|
||||||
|
profile.photos = [pageAvatar];
|
||||||
|
}
|
||||||
|
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
@ -94,18 +100,20 @@ async function fetchUpcoming(channel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchProfile({ name: actorName }, entity) {
|
async function fetchProfile({ name: actorName }, entity) {
|
||||||
|
// don't skip search, avatar not available on actor page
|
||||||
const searchUrl = `${entity.url}/models?name=${actorName}&sort=popularity`;
|
const searchUrl = `${entity.url}/models?name=${actorName}&sort=popularity`;
|
||||||
const searchRes = await unprint.get(searchUrl);
|
const searchRes = await unprint.get(searchUrl);
|
||||||
|
|
||||||
if (searchRes.ok) {
|
if (searchRes.ok) {
|
||||||
const actorEl = searchRes.context.query.all('.pagination-items .model a').find((resultEl) => unprint.query.attribute(resultEl, null, 'title') === actorName);
|
const actorEl = searchRes.context.query.all('.pagination-items .model a').find((resultEl) => unprint.query.attribute(resultEl, null, 'title') === actorName);
|
||||||
const actorUrl = unprint.query.url(actorEl, null);
|
const actorUrl = unprint.query.url(actorEl, null);
|
||||||
|
const avatar = unprint.query.img(actorEl, '.card-img');
|
||||||
|
|
||||||
if (actorUrl) {
|
if (actorUrl) {
|
||||||
const res = await unprint.get(actorUrl, { select: '.model-detail-card' });
|
const res = await unprint.get(actorUrl, { select: '.model-detail-card' });
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
return scrapeProfile(res.context, actorName, entity);
|
return scrapeProfile(res.context, avatar, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status;
|
return res.status;
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,6 @@ const getRecursiveParameters = require('../src/utils/get-recursive-parameters');
|
||||||
const knex = require('../src/knex');
|
const knex = require('../src/knex');
|
||||||
|
|
||||||
const actors = [
|
const actors = [
|
||||||
// jules jordan
|
|
||||||
{ entity: 'julesjordan', name: 'Vanna Bardot', fields: ['height', 'dateOfBirth', 'measurements', 'description', 'avatar'] },
|
|
||||||
// vixen
|
// vixen
|
||||||
{ entity: 'vixen', name: 'Abella Danger', fields: ['gender', 'avatar', 'description'] },
|
{ entity: 'vixen', name: 'Abella Danger', fields: ['gender', 'avatar', 'description'] },
|
||||||
{ entity: 'tushy', name: 'Abella Danger', fields: ['gender', 'avatar', 'description'] },
|
{ entity: 'tushy', name: 'Abella Danger', fields: ['gender', 'avatar', 'description'] },
|
||||||
|
|
@ -28,8 +26,6 @@ const actors = [
|
||||||
// teamskeet
|
// teamskeet
|
||||||
{ entity: 'teamskeet', name: 'Abella Danger', fields: ['description', 'avatar', 'measurements', 'birthPlace', 'nationality', 'ethnicity', 'height', 'weight', 'hairColor', 'hasPiercings'] },
|
{ entity: 'teamskeet', name: 'Abella Danger', fields: ['description', 'avatar', 'measurements', 'birthPlace', 'nationality', 'ethnicity', 'height', 'weight', 'hairColor', 'hasPiercings'] },
|
||||||
{ entity: 'teamskeet', name: 'Kali Roses', fields: ['description', 'avatar', 'measurements', 'nationality', 'ethnicity', 'hairColor', 'hasPiercings', 'hasTattoos'] }, // tattoos
|
{ entity: 'teamskeet', name: 'Kali Roses', fields: ['description', 'avatar', 'measurements', 'nationality', 'ethnicity', 'hairColor', 'hasPiercings', 'hasTattoos'] }, // tattoos
|
||||||
// analvids
|
|
||||||
{ entity: 'analvids', name: 'Veronica Leal', fields: ['avatar', 'gender', 'birthCountry', 'nationality', 'age', 'aliases', 'nationality'] },
|
|
||||||
// mike adriano
|
// mike adriano
|
||||||
{ entity: 'trueanal', name: 'Brenna McKenna', fields: ['avatar', 'gender', 'description', 'dateOfBirth', 'birthPlace', 'measurements', 'eyes', 'weight', 'height', 'hairColor', 'hasTattoos'] },
|
{ entity: 'trueanal', name: 'Brenna McKenna', fields: ['avatar', 'gender', 'description', 'dateOfBirth', 'birthPlace', 'measurements', 'eyes', 'weight', 'height', 'hairColor', 'hasTattoos'] },
|
||||||
{ entity: 'analonly', name: 'Lilith Grace', fields: ['avatar', 'gender', 'description', 'dateOfBirth', 'birthPlace', 'measurements', 'eyes', 'weight', 'height', 'hairColor'] },
|
{ entity: 'analonly', name: 'Lilith Grace', fields: ['avatar', 'gender', 'description', 'dateOfBirth', 'birthPlace', 'measurements', 'eyes', 'weight', 'height', 'hairColor'] },
|
||||||
|
|
@ -77,8 +73,6 @@ const actors = [
|
||||||
{ entity: 'realityjunkies', name: 'Scarlett Alexis', fields: ['avatar', 'gender'] },
|
{ entity: 'realityjunkies', name: 'Scarlett Alexis', fields: ['avatar', 'gender'] },
|
||||||
{ entity: 'sweetheartvideo', name: 'Lexi Lore', fields: ['avatar', 'gender', 'hairColor', 'ethnicity', 'hasTattoos', 'hasPiercings'] },
|
{ entity: 'sweetheartvideo', name: 'Lexi Lore', fields: ['avatar', 'gender', 'hairColor', 'ethnicity', 'hasTattoos', 'hasPiercings'] },
|
||||||
{ entity: 'sweetsinner', name: 'Anna Claire Clouds', fields: ['avatar', 'gender'] },
|
{ entity: 'sweetsinner', name: 'Anna Claire Clouds', fields: ['avatar', 'gender'] },
|
||||||
// bangros
|
|
||||||
{ entity: 'bangbros', name: 'Kira Perez', fields: ['avatar', 'gender', 'ethnicity', 'hairColor'] },
|
|
||||||
// gamma
|
// gamma
|
||||||
{ entity: '21sextury', name: 'Aletta Ocean', fields: ['avatar', 'gender', 'description', 'eyes', 'hairColor'] },
|
{ entity: '21sextury', name: 'Aletta Ocean', fields: ['avatar', 'gender', 'description', 'eyes', 'hairColor'] },
|
||||||
{ entity: 'biphoria', name: 'Cherry Kiss', fields: ['avatar', 'gender'] },
|
{ entity: 'biphoria', name: 'Cherry Kiss', fields: ['avatar', 'gender'] },
|
||||||
|
|
@ -120,12 +114,6 @@ const actors = [
|
||||||
{ entity: 'inserted', name: 'Anissa Kate', fields: ['avatar', 'description', 'gender', 'dateOfBirth', 'birthPlace', 'measurements', 'height', 'weight', 'eyes', 'hairColor'] },
|
{ entity: 'inserted', name: 'Anissa Kate', fields: ['avatar', 'description', 'gender', 'dateOfBirth', 'birthPlace', 'measurements', 'height', 'weight', 'eyes', 'hairColor'] },
|
||||||
{ entity: 'topwebmodels', name: 'Lexi Belle', fields: ['avatar', 'gender', 'dateOfBirth', 'birthPlace', 'measurements', 'height', 'weight', 'eyes', 'hairColor'] },
|
{ entity: 'topwebmodels', name: 'Lexi Belle', fields: ['avatar', 'gender', 'dateOfBirth', 'birthPlace', 'measurements', 'height', 'weight', 'eyes', 'hairColor'] },
|
||||||
{ entity: 'purgatoryx', name: 'Kenzie Reeves', fields: ['avatar', 'description', 'gender', 'dateOfBirth', 'birthPlace', 'measurements', 'height', 'weight', 'eyes', 'hairColor'] },
|
{ entity: 'purgatoryx', name: 'Kenzie Reeves', fields: ['avatar', 'description', 'gender', 'dateOfBirth', 'birthPlace', 'measurements', 'height', 'weight', 'eyes', 'hairColor'] },
|
||||||
// etc.
|
|
||||||
{ entity: 'archangel', name: 'Summer Brielle', fields: ['avatar', 'description', 'dateOfBirth', 'age', 'measurements', 'height', 'aliases'] },
|
|
||||||
{ entity: 'theflourishxxx', name: 'XWifeKaren', fields: ['avatar', 'description'] },
|
|
||||||
{ entity: 'hookuphotshot', name: 'Kenzie Reeves', fields: ['avatar', 'description'] },
|
|
||||||
{ entity: 'tokyohot', name: 'Mai Kawana', url: 'https://my.tokyo-hot.com/cast/2099/', fields: ['avatar', 'birthPlace', 'height', 'cup', 'bust', 'waist', 'hip', 'hairStyle', 'shoeSize', 'bloodType'] },
|
|
||||||
{ entity: 'teenmegaworld', name: 'Sheri Vi', fields: ['avatar', 'description', 'hairColor', 'eyes'] },
|
|
||||||
// wankz
|
// wankz
|
||||||
{ entity: 'wankzvr', name: 'Melody Marks', fields: ['avatar', 'gender', 'description', 'birthPlace', 'height', 'measurements', 'age'] },
|
{ entity: 'wankzvr', name: 'Melody Marks', fields: ['avatar', 'gender', 'description', 'birthPlace', 'height', 'measurements', 'age'] },
|
||||||
{ entity: 'milfvr', name: 'Ember Snow', fields: ['avatar', 'gender', 'description', 'measurements', 'birthPlace', 'height', 'age'] },
|
{ entity: 'milfvr', name: 'Ember Snow', fields: ['avatar', 'gender', 'description', 'measurements', 'birthPlace', 'height', 'age'] },
|
||||||
|
|
@ -145,6 +133,22 @@ const actors = [
|
||||||
{ entity: 'thatsitcomshow', name: 'Casey Calvert', fields: ['avatar', 'age', 'residencePlace', 'height', 'measurements', 'photos'] },
|
{ entity: 'thatsitcomshow', name: 'Casey Calvert', fields: ['avatar', 'age', 'residencePlace', 'height', 'measurements', 'photos'] },
|
||||||
// porndoe
|
// porndoe
|
||||||
{ entity: 'vipsexvault', name: 'Amirah Adara', fields: ['avatar', 'nationality', 'placeOfBirth', 'age', 'naturalBoobs', 'hairColor', 'description'] },
|
{ entity: 'vipsexvault', name: 'Amirah Adara', fields: ['avatar', 'nationality', 'placeOfBirth', 'age', 'naturalBoobs', 'hairColor', 'description'] },
|
||||||
|
{ entity: 'amateureuro', name: 'Luna Oara', fields: ['avatar', 'nationality', 'placeOfBirth', 'age', 'naturalBoobs', 'description'] },
|
||||||
|
{ entity: 'mamacitaz', name: 'Julia De Lucia', fields: ['avatar', 'nationality', 'placeOfBirth', 'age', 'naturalBoobs', 'description', 'hairColor'] },
|
||||||
|
{ entity: 'transbella', name: 'Kalena Rios', fields: ['avatar', 'nationality', 'placeOfBirth', 'age', 'naturalBoobs', 'description', 'hairColor'] },
|
||||||
|
// etc.
|
||||||
|
{ entity: 'analvids', name: 'Veronica Leal', fields: ['avatar', 'gender', 'birthCountry', 'nationality', 'age', 'aliases', 'nationality'] },
|
||||||
|
{ entity: 'archangel', name: 'Summer Brielle', fields: ['avatar', 'description', 'dateOfBirth', 'age', 'measurements', 'height', 'aliases'] },
|
||||||
|
{ entity: 'bangbros', name: 'Kira Perez', fields: ['avatar', 'gender', 'ethnicity', 'hairColor'] },
|
||||||
|
{ entity: 'hookuphotshot', name: 'Kenzie Reeves', fields: ['avatar', 'description'] },
|
||||||
|
{ entity: 'julesjordan', name: 'Vanna Bardot', fields: ['height', 'dateOfBirth', 'measurements', 'description', 'avatar'] },
|
||||||
|
{ entity: 'pornworld', name: 'Veronica Leal', fields: ['avatar', 'nationality', 'age'] },
|
||||||
|
{ entity: 'private', name: 'Cherry Kiss', fields: ['avatar', 'description', 'nationality', 'measurements', 'height', 'weight', 'hairColor', 'eye', 'hasTattoos', 'tattoos', 'hasPiercings', 'piercings'] },
|
||||||
|
{ entity: 'teenmegaworld', name: 'Sheri Vi', fields: ['avatar', 'description', 'hairColor', 'eyes'] },
|
||||||
|
{ entity: 'theflourishxxx', name: 'XWifeKaren', fields: ['avatar', 'description'] },
|
||||||
|
{ entity: 'tokyohot', name: 'Mai Kawana', url: 'https://my.tokyo-hot.com/cast/2099/', fields: ['avatar', 'birthPlace', 'height', 'cup', 'bust', 'waist', 'hip', 'hairStyle', 'shoeSize', 'bloodType'] },
|
||||||
|
{ entity: 'rickysroom', name: 'Liz Jordan', fields: ['avatar', 'description', 'birthPlace', 'dateOfBirth', 'measurements', 'height', 'weight', 'eyes', 'hairColor'] },
|
||||||
|
{ entity: 'cherrypimps', name: 'Andi Avalon', fields: ['avatar', 'height', 'weight', 'dateOfBirth', 'birthPlace', 'ethnicity', 'measurements', 'hair', 'eyes', 'hasTattoos', 'age'] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const actorScrapers = scrapers.actors;
|
const actorScrapers = scrapers.actors;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue