Added Little Caprice Dreams scraped (WIP).
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 9.9 KiB |
After Width: | Height: | Size: 291 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 356 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 872 KiB |
After Width: | Height: | Size: 4.5 MiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 1.6 MiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 33 KiB |
|
@ -1098,6 +1098,10 @@ const aliases = [
|
||||||
for: 'bts',
|
for: 'bts',
|
||||||
secondary: true,
|
secondary: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'behind the scene',
|
||||||
|
for: 'bts',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'blindfolded',
|
name: 'blindfolded',
|
||||||
for: 'blindfold',
|
for: 'blindfold',
|
||||||
|
@ -1265,6 +1269,10 @@ const aliases = [
|
||||||
name: 'couples fantasies',
|
name: 'couples fantasies',
|
||||||
for: 'couples',
|
for: 'couples',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'couple sex',
|
||||||
|
for: 'couples',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'creampies',
|
name: 'creampies',
|
||||||
for: 'creampie',
|
for: 'creampie',
|
||||||
|
|
|
@ -4225,6 +4225,13 @@ const sites = [
|
||||||
url: 'https://letsdoeit.com/channels/bums-besuch.en.html',
|
url: 'https://letsdoeit.com/channels/bums-besuch.en.html',
|
||||||
parent: 'letsdoeit',
|
parent: 'letsdoeit',
|
||||||
},
|
},
|
||||||
|
// LITTLE CAPRICE
|
||||||
|
{
|
||||||
|
name: 'Little Caprice Dreams',
|
||||||
|
slug: 'littlecapricedreams',
|
||||||
|
alias: ['little caprice'],
|
||||||
|
url: 'https://www.littlecaprice-dreams.com',
|
||||||
|
},
|
||||||
// MAMACITAZ
|
// MAMACITAZ
|
||||||
{
|
{
|
||||||
name: 'Her Big Ass',
|
name: 'Her Big Ass',
|
||||||
|
|
|
@ -694,12 +694,14 @@ const tagPhotos = [
|
||||||
['anal', 3, 'Dakota Skye for Brazzers'],
|
['anal', 3, 'Dakota Skye for Brazzers'],
|
||||||
// ['anal', 1, 'Veronica Leal and Tina Kay in "Agents On Anal Mission" for Asshole Fever'],
|
// ['anal', 1, 'Veronica Leal and Tina Kay in "Agents On Anal Mission" for Asshole Fever'],
|
||||||
// ['anal', 0, 'Veronica Leal'],
|
// ['anal', 0, 'Veronica Leal'],
|
||||||
|
['anal-creampie', 3, 'Rose Valerie for Euro Sex Parties'],
|
||||||
['anal-creampie', 0, 'Gina Valentina and Jane Wilde in "A Very Special Anniversary" for Tushy'],
|
['anal-creampie', 0, 'Gina Valentina and Jane Wilde in "A Very Special Anniversary" for Tushy'],
|
||||||
['anal-creampie', 1, 'Aleska Diamond in "Aleska Wants More" for Asshole Fever'],
|
['anal-creampie', 1, 'Aleska Diamond in "Aleska Wants More" for Asshole Fever'],
|
||||||
['ass-eating', 4, 'Vanna Bardot and Isiah Maxwell in "Vanna Craves Isiah\'s Cock!" for DarkX'],
|
['ass-eating', 4, 'Vanna Bardot and Isiah Maxwell in "Vanna Craves Isiah\'s Cock!" for DarkX'],
|
||||||
['ass-eating', 3, 'Abella Danger and Karma Rx in "Neon Dreaming" for Brazzers'],
|
['ass-eating', 3, 'Abella Danger and Karma Rx in "Neon Dreaming" for Brazzers'],
|
||||||
['ass-eating', 1, 'Aidra Fox and Cassidy Klein in "Lesbian Anal Yoga" for LesbianX'],
|
['ass-eating', 1, 'Aidra Fox and Cassidy Klein in "Lesbian Anal Yoga" for LesbianX'],
|
||||||
['ass-eating', 0, 'Angelica Heart and Leanna Sweet in "ATM Bitches" for Asshole Fever'],
|
['ass-eating', 0, 'Angelica Heart and Leanna Sweet in "ATM Bitches" for Asshole Fever'],
|
||||||
|
['anal-fingering', 3, 'Rose Valerie for DDF Network'],
|
||||||
['anal-fingering', 1, 'Cherry Kiss, Veronica Leal and Sybil in "Capture This" for Lez Cuties'],
|
['anal-fingering', 1, 'Cherry Kiss, Veronica Leal and Sybil in "Capture This" for Lez Cuties'],
|
||||||
['anal-fingering', 2, 'Aidra Fox and Cassidy Klein in "Lesbian Anal Yoga" for LesbianX'],
|
['anal-fingering', 2, 'Aidra Fox and Cassidy Klein in "Lesbian Anal Yoga" for LesbianX'],
|
||||||
['bts', 0, 'Janice Griffith in "Day With A Pornstar: Janice" for Brazzers'],
|
['bts', 0, 'Janice Griffith in "Day With A Pornstar: Janice" for Brazzers'],
|
||||||
|
@ -708,6 +710,8 @@ const tagPhotos = [
|
||||||
['blonde', 3, 'Kylie Page in "A Juicy Afternoon Delight" for New Sensations'],
|
['blonde', 3, 'Kylie Page in "A Juicy Afternoon Delight" for New Sensations'],
|
||||||
['blonde', 2, 'Isabelle Deltore for Her Limit'],
|
['blonde', 2, 'Isabelle Deltore for Her Limit'],
|
||||||
['blowbang', 'poster', 'Marsha May in "Feeding Frenzy 12" for Jules Jordan'],
|
['blowbang', 'poster', 'Marsha May in "Feeding Frenzy 12" for Jules Jordan'],
|
||||||
|
['blowjob', 3, 'Rose Valie for Hands On Hardcore'],
|
||||||
|
['blowjob', 2, 'Luna Kitsuen in "Gag Reflex" for Evil Angel'],
|
||||||
['blowjob', 1, 'Kylie Page in "Stepsis Gives Soapy Handjob In Shower" for Spy Fam'],
|
['blowjob', 1, 'Kylie Page in "Stepsis Gives Soapy Handjob In Shower" for Spy Fam'],
|
||||||
// ['bukkake', 'poster', 'Mia Malkova in "Facialized 2" for HardX'],
|
// ['bukkake', 'poster', 'Mia Malkova in "Facialized 2" for HardX'],
|
||||||
['caucasian', 0, 'Remy Lacroix for HardX'],
|
['caucasian', 0, 'Remy Lacroix for HardX'],
|
||||||
|
@ -819,6 +823,7 @@ const tagPhotos = [
|
||||||
['maid', 1, 'Alessandra Jane for Brazzers'],
|
['maid', 1, 'Alessandra Jane for Brazzers'],
|
||||||
// ['milf', 0, 'Olivia Austin in "Dredd 3" for Jules Jordan'],
|
// ['milf', 0, 'Olivia Austin in "Dredd 3" for Jules Jordan'],
|
||||||
['mff', 0, 'Madison Ivy, Adriana Chechik and Keiran Lee in "Day With A Pornstar" for Brazzers'],
|
['mff', 0, 'Madison Ivy, Adriana Chechik and Keiran Lee in "Day With A Pornstar" for Brazzers'],
|
||||||
|
['mfm', 7, 'Rose Valerie for Euro Sex Parties'],
|
||||||
['mfm', 1, 'Lana Rhoades in "Gangbang Me 3" for HardX'],
|
['mfm', 1, 'Lana Rhoades in "Gangbang Me 3" for HardX'],
|
||||||
['mfm', 6, 'Honey Gold in "Slut Puppies 12" for Jules Jordan'],
|
['mfm', 6, 'Honey Gold in "Slut Puppies 12" for Jules Jordan'],
|
||||||
['natural-boobs', 1, 'Nia Nacci for First Class POV'],
|
['natural-boobs', 1, 'Nia Nacci for First Class POV'],
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const qu = require('../utils/qu');
|
||||||
|
|
||||||
|
function scrapeAll(scenes) {
|
||||||
|
return scenes.map(({ query, el }) => {
|
||||||
|
const release = {};
|
||||||
|
|
||||||
|
release.url = query.url('a');
|
||||||
|
release.entryId = query.q(el, null, 'id')?.match(/post-(\d+)/)?.[1];
|
||||||
|
|
||||||
|
release.title = query.cnt('.meta h3');
|
||||||
|
release.date = query.date('.meta .post-meta', 'MMMM D, YYYY');
|
||||||
|
|
||||||
|
release.poster = query.img('img');
|
||||||
|
|
||||||
|
return release;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeScene({ query }) {
|
||||||
|
const release = {};
|
||||||
|
|
||||||
|
const script = query.cnt('script.yoast-schema-graph');
|
||||||
|
const data = script && JSON.parse(script);
|
||||||
|
|
||||||
|
release.entryId = query.q('article.project', 'id')?.match(/post-(\d+)/)?.[1];
|
||||||
|
|
||||||
|
release.title = query.cnt('.vid_title');
|
||||||
|
release.description = query.cnt('.vid_desc p');
|
||||||
|
|
||||||
|
release.date = query.date('.vid_date', 'MMMM D, YYYY');
|
||||||
|
release.duration = query.dur('.vid_length');
|
||||||
|
|
||||||
|
release.actors = query.all('.vid_infos a[href*="author/"]').map(actorEl => ({
|
||||||
|
name: query.cnt(actorEl),
|
||||||
|
url: query.url(actorEl, null),
|
||||||
|
}));
|
||||||
|
|
||||||
|
release.tags = query.cnts('.vid_infos a[rel="tag"]');
|
||||||
|
|
||||||
|
const posterData = data['@graph']?.find(item => item['@type'] === 'ImageObject');
|
||||||
|
|
||||||
|
release.poster = posterData?.url
|
||||||
|
|| query.q('meta[property="og:image"]', 'content')
|
||||||
|
|| query.q('meta[name="twitter:image"]', 'content');
|
||||||
|
|
||||||
|
release.stars = Math.min(Number(query.q('.post-ratings-image', 'title')?.match(/average:\s*(\d\.\d+)/)?.[1]), 5) || null; // rating out of 5, yet sometimes 5.07?
|
||||||
|
|
||||||
|
// TODO: photo gallery, find if any video has a trailer
|
||||||
|
console.log(release);
|
||||||
|
return release;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchLatest(channel) {
|
||||||
|
// no apparent pagination, all updates on one page
|
||||||
|
const res = await qu.getAll(`${channel.url}/videos/`, '.project');
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
return scrapeAll(res.items, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchScene(url, channel) {
|
||||||
|
const res = await qu.get(url);
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
return scrapeScene(res.item, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchLatest,
|
||||||
|
fetchScene,
|
||||||
|
};
|
|
@ -38,6 +38,7 @@ const kellymadison = require('./kellymadison');
|
||||||
const killergram = require('./killergram');
|
const killergram = require('./killergram');
|
||||||
const kink = require('./kink');
|
const kink = require('./kink');
|
||||||
const legalporno = require('./legalporno');
|
const legalporno = require('./legalporno');
|
||||||
|
const littlecapricedreams = require('./littlecapricedreams');
|
||||||
const porndoe = require('./porndoe');
|
const porndoe = require('./porndoe');
|
||||||
const men = require('./men');
|
const men = require('./men');
|
||||||
const metrohd = require('./metrohd');
|
const metrohd = require('./metrohd');
|
||||||
|
@ -53,7 +54,6 @@ const perfectgonzo = require('./perfectgonzo');
|
||||||
const pervcity = require('./pervcity');
|
const pervcity = require('./pervcity');
|
||||||
const porncz = require('./porncz');
|
const porncz = require('./porncz');
|
||||||
const pornhub = require('./pornhub');
|
const pornhub = require('./pornhub');
|
||||||
const whalemember = require('./whalemember');
|
|
||||||
const pascalssubsluts = require('./pascalssubsluts'); // reserved keyword
|
const pascalssubsluts = require('./pascalssubsluts'); // reserved keyword
|
||||||
const privateNetwork = require('./private'); // reserved keyword
|
const privateNetwork = require('./private'); // reserved keyword
|
||||||
const puretaboo = require('./puretaboo');
|
const puretaboo = require('./puretaboo');
|
||||||
|
@ -69,6 +69,7 @@ const twistys = require('./twistys');
|
||||||
const vivid = require('./vivid');
|
const vivid = require('./vivid');
|
||||||
const vixen = require('./vixen');
|
const vixen = require('./vixen');
|
||||||
const vogov = require('./vogov');
|
const vogov = require('./vogov');
|
||||||
|
const whalemember = require('./whalemember');
|
||||||
const wicked = require('./wicked');
|
const wicked = require('./wicked');
|
||||||
const xempire = require('./xempire');
|
const xempire = require('./xempire');
|
||||||
const zerotolerance = require('./zerotolerance');
|
const zerotolerance = require('./zerotolerance');
|
||||||
|
@ -128,6 +129,7 @@ const scrapers = {
|
||||||
kink,
|
kink,
|
||||||
legalporno,
|
legalporno,
|
||||||
letsdoeit: porndoe,
|
letsdoeit: porndoe,
|
||||||
|
littlecapricedreams,
|
||||||
mamacitaz: porndoe,
|
mamacitaz: porndoe,
|
||||||
men,
|
men,
|
||||||
metrohd,
|
metrohd,
|
||||||
|
|
|
@ -9,6 +9,7 @@ const Bottleneck = require('bottleneck');
|
||||||
const { JSDOM } = require('jsdom');
|
const { JSDOM } = require('jsdom');
|
||||||
|
|
||||||
const logger = require('../logger')(__filename);
|
const logger = require('../logger')(__filename);
|
||||||
|
const virtualConsole = require('./virtual-console')(__filename);
|
||||||
const argv = require('../argv');
|
const argv = require('../argv');
|
||||||
|
|
||||||
const pipeline = util.promisify(stream.pipeline);
|
const pipeline = util.promisify(stream.pipeline);
|
||||||
|
@ -105,7 +106,7 @@ async function request(method = 'get', url, body, requestOptions = {}, limiter)
|
||||||
|
|
||||||
if (Buffer.isBuffer(res.body)) {
|
if (Buffer.isBuffer(res.body)) {
|
||||||
const html = res.body.toString();
|
const html = res.body.toString();
|
||||||
const window = new JSDOM(html).window;
|
const window = new JSDOM(html, { virtualConsole }).window;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...res,
|
...res,
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
const { JSDOM } = require('jsdom');
|
const { JSDOM } = require('jsdom');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const http = require('./http');
|
const http = require('./http');
|
||||||
|
const virtualConsole = require('./virtual-console')(__filename);
|
||||||
|
|
||||||
const { window: globalWindow } = new JSDOM('');
|
const { window: globalWindow } = new JSDOM('', { virtualConsole });
|
||||||
|
|
||||||
function trim(str) {
|
function trim(str) {
|
||||||
if (typeof str !== 'string') {
|
if (typeof str !== 'string') {
|
||||||
|
@ -440,7 +441,7 @@ function initAll(context, selector, window) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function extract(htmlValue, selector) {
|
function extract(htmlValue, selector) {
|
||||||
const { window } = new JSDOM(htmlValue);
|
const { window } = new JSDOM(htmlValue, { virtualConsole });
|
||||||
|
|
||||||
if (selector) {
|
if (selector) {
|
||||||
return init(window.document.querySelector(selector), window);
|
return init(window.document.querySelector(selector), window);
|
||||||
|
@ -450,7 +451,7 @@ function extract(htmlValue, selector) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractAll(htmlValue, selector) {
|
function extractAll(htmlValue, selector) {
|
||||||
const { window } = new JSDOM(htmlValue);
|
const { window } = new JSDOM(htmlValue, { virtualConsole });
|
||||||
|
|
||||||
return initAll(window.document, selector, window);
|
return initAll(window.document, selector, window);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { VirtualConsole } = require('jsdom');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const logger = require('../logger')(__filename);
|
||||||
|
|
||||||
|
function getVirtualConsole(filepath) {
|
||||||
|
const virtualConsole = new VirtualConsole();
|
||||||
|
const context = path.basename(filepath);
|
||||||
|
|
||||||
|
virtualConsole.on('error', message => logger.warn(`Error from JSDOM in ${context}: ${message}`));
|
||||||
|
virtualConsole.on('jsdomError', message => logger.warn(`Error from JSDOM in ${context}: ${message}`));
|
||||||
|
|
||||||
|
return virtualConsole;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = getVirtualConsole;
|