Added Dorcel Club with scene and actor scraping. Added count method to qu.
|
@ -178,7 +178,7 @@ function initEntitiesActions(store, router) {
|
||||||
$entitySlugs: [String!] = []
|
$entitySlugs: [String!] = []
|
||||||
) {
|
) {
|
||||||
entities(
|
entities(
|
||||||
orderBy: NAME_ASC
|
orderBy: SLUG_ASC
|
||||||
filter: {
|
filter: {
|
||||||
or: [
|
or: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -113,6 +113,7 @@ module.exports = {
|
||||||
],
|
],
|
||||||
'21sextury',
|
'21sextury',
|
||||||
'julesjordan',
|
'julesjordan',
|
||||||
|
'dorcelclub',
|
||||||
'bang',
|
'bang',
|
||||||
'pervcity',
|
'pervcity',
|
||||||
'kink',
|
'kink',
|
||||||
|
@ -153,20 +154,22 @@ module.exports = {
|
||||||
'pervertgallery',
|
'pervertgallery',
|
||||||
'povperverts',
|
'povperverts',
|
||||||
],
|
],
|
||||||
|
'pascalssubsluts',
|
||||||
'kellymadison',
|
'kellymadison',
|
||||||
'private',
|
'private',
|
||||||
'ddfnetwork',
|
'ddfnetwork',
|
||||||
'bangbros',
|
'bangbros',
|
||||||
'hitzefrei',
|
'hitzefrei',
|
||||||
[
|
|
||||||
'silverstonedvd',
|
|
||||||
'silviasaint',
|
|
||||||
],
|
|
||||||
'porncz',
|
'porncz',
|
||||||
|
'czechav',
|
||||||
'gangbangcreampie',
|
'gangbangcreampie',
|
||||||
'gloryholesecrets',
|
'gloryholesecrets',
|
||||||
'aziani',
|
'aziani',
|
||||||
'legalporno',
|
'legalporno',
|
||||||
|
[
|
||||||
|
'silverstonedvd',
|
||||||
|
'silviasaint',
|
||||||
|
],
|
||||||
'score',
|
'score',
|
||||||
'boobpedia',
|
'boobpedia',
|
||||||
'pornhub',
|
'pornhub',
|
||||||
|
|
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 170 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 18 KiB |
|
@ -1057,6 +1057,11 @@ const aliases = [
|
||||||
for: 'bts',
|
for: 'bts',
|
||||||
secondary: true,
|
secondary: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'making of',
|
||||||
|
for: 'bts',
|
||||||
|
secondary: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'mfm',
|
name: 'mfm',
|
||||||
for: 'mmf',
|
for: 'mmf',
|
||||||
|
|
|
@ -148,6 +148,11 @@ const networks = [
|
||||||
name: 'CzechAV',
|
name: 'CzechAV',
|
||||||
url: 'https://www.czechav.com',
|
url: 'https://www.czechav.com',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
slug: 'dorcel',
|
||||||
|
name: 'Marc Dorcel',
|
||||||
|
url: 'https://www.dorcel.com',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
slug: 'fcuk',
|
slug: 'fcuk',
|
||||||
name: 'Fcuk',
|
name: 'Fcuk',
|
||||||
|
|
|
@ -2182,6 +2182,13 @@ const sites = [
|
||||||
description: '',
|
description: '',
|
||||||
parent: 'dogfartnetwork',
|
parent: 'dogfartnetwork',
|
||||||
},
|
},
|
||||||
|
// DORCEL
|
||||||
|
{
|
||||||
|
slug: 'dorcelclub',
|
||||||
|
name: 'Dorcel Club',
|
||||||
|
url: 'https://www.dorcelclub.com',
|
||||||
|
parent: 'dorcel',
|
||||||
|
},
|
||||||
// ELEGANT ANGEL
|
// ELEGANT ANGEL
|
||||||
{
|
{
|
||||||
slug: 'elegantangel',
|
slug: 'elegantangel',
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const qu = require('../utils/q');
|
||||||
|
const slugify = require('../utils/slugify');
|
||||||
|
|
||||||
|
function scrapeAll(scenes) {
|
||||||
|
return scenes.map(({ query }) => {
|
||||||
|
const release = {};
|
||||||
|
|
||||||
|
release.url = query.url('.title a');
|
||||||
|
release.entryId = new URL(release.url).pathname.match(/\/scene\/(\d+)/)[1];
|
||||||
|
|
||||||
|
release.title = query.cnt('.title a');
|
||||||
|
|
||||||
|
release.date = query.date('.date', 'MMMM DD, YYYY', /\w+ \d{1,2}, \d{4}/);
|
||||||
|
release.duration = query.number('.length') * 60;
|
||||||
|
|
||||||
|
release.actors = query.all('.actors a').map(actorEl => ({
|
||||||
|
name: query.cnt(actorEl),
|
||||||
|
url: query.url(actorEl, null),
|
||||||
|
}));
|
||||||
|
|
||||||
|
release.poster = query.img('.poster noscript img');
|
||||||
|
release.stars = query.count('.rating .star1');
|
||||||
|
|
||||||
|
release.tags = [query.cnt('.collection a')];
|
||||||
|
|
||||||
|
return release;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeScene({ query }, url) {
|
||||||
|
const release = {};
|
||||||
|
|
||||||
|
release.entryId = new URL(url).pathname.match(/\/scene\/(\d+)/)[1];
|
||||||
|
|
||||||
|
release.title = query.cnt('.infos .title h1');
|
||||||
|
release.description = query.cnt('#description p:nth-child(2)');
|
||||||
|
|
||||||
|
release.date = query.date('.infos .date', 'MMMM DD, YYYY', /\w+ \d{1,2}, \d{4}/);
|
||||||
|
release.duration = query.number('.infos .length') * 60;
|
||||||
|
|
||||||
|
release.actors = query.all('.infos .actors a').map(actorEl => ({
|
||||||
|
name: query.cnt(actorEl),
|
||||||
|
url: query.url(actorEl, null),
|
||||||
|
}));
|
||||||
|
|
||||||
|
release.poster = query.img('.poster noscript img');
|
||||||
|
release.stars = query.count('.infos .rating .star1');
|
||||||
|
|
||||||
|
if (query.exists('.movie')) {
|
||||||
|
release.movie = {
|
||||||
|
name: query.cnt('.movie a'),
|
||||||
|
url: query.url('.movie a'),
|
||||||
|
};
|
||||||
|
|
||||||
|
release.movie.entryId = new URL(release.movie.url).pathname.split('/').slice(-1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return release;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrapeProfile({ query, el }, avatar) {
|
||||||
|
const profile = {};
|
||||||
|
|
||||||
|
profile.birthdate = qu.parseDate(query.text('.birthdate'), 'MMMM DD, YYYY');
|
||||||
|
profile.nationality = query.text('.nationality');
|
||||||
|
profile.hairColor = query.text('.hair');
|
||||||
|
|
||||||
|
profile.description = query.cnt('.bio_results p');
|
||||||
|
|
||||||
|
if (avatar) {
|
||||||
|
profile.avatar = [
|
||||||
|
avatar.replace('_crop', ''),
|
||||||
|
avatar,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add pagination
|
||||||
|
profile.releases = scrapeAll(qu.initAll(el, '.scene'));
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add movies
|
||||||
|
|
||||||
|
async function fetchLatest(channel, page = 1) {
|
||||||
|
const url = `${channel.url}/en/news-videos-x-marc-dorcel-ajax?page=${page}&sorting=publish_date`;
|
||||||
|
const res = await qu.getAll(url, '.scene', {
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
});
|
||||||
|
|
||||||
|
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, url, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchProfile({ name: actorName, url: actorUrl }, entity, include) {
|
||||||
|
const searchRes = await qu.getAll(`${entity.url}/en/pornstars?search=${slugify(actorName, '+')}`, '.actor');
|
||||||
|
|
||||||
|
const actorItem = searchRes.ok && searchRes.items.find(actor => slugify(actor.query.cnt('h2')) === slugify(actorName));
|
||||||
|
const actorItemUrl = actorItem?.query.url();
|
||||||
|
const actorItemAvatar = actorItem?.query.img();
|
||||||
|
|
||||||
|
const url = actorUrl || actorItemUrl || `${entity.url}/en/pornstar/${slugify(actorName, '-')}`;
|
||||||
|
const res = await qu.get(url);
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
return scrapeProfile(res.item, actorItemAvatar, entity, include);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchLatest,
|
||||||
|
fetchScene,
|
||||||
|
fetchProfile,
|
||||||
|
};
|
|
@ -65,7 +65,7 @@ function scrapeProfile({ query }) {
|
||||||
profile.nationality = bio.nationality;
|
profile.nationality = bio.nationality;
|
||||||
profile.height = feetInchesToCm(bio.height);
|
profile.height = feetInchesToCm(bio.height);
|
||||||
profile.age = bio.age;
|
profile.age = bio.age;
|
||||||
profile.hair = bio.hair;
|
profile.hairColor = bio.hair;
|
||||||
|
|
||||||
profile.description = query.cnt('.twocolumns');
|
profile.description = query.cnt('.twocolumns');
|
||||||
profile.avatar = query.img('#individual-description img');
|
profile.avatar = query.img('#individual-description img');
|
||||||
|
|
|
@ -16,6 +16,7 @@ const czechav = require('./czechav');
|
||||||
const ddfnetwork = require('./ddfnetwork');
|
const ddfnetwork = require('./ddfnetwork');
|
||||||
const digitalplayground = require('./digitalplayground');
|
const digitalplayground = require('./digitalplayground');
|
||||||
const dogfart = require('./dogfart');
|
const dogfart = require('./dogfart');
|
||||||
|
const dorcel = require('./dorcel');
|
||||||
const elegantangel = require('./elegantangel');
|
const elegantangel = require('./elegantangel');
|
||||||
const evilangel = require('./evilangel');
|
const evilangel = require('./evilangel');
|
||||||
const fakehub = require('./fakehub');
|
const fakehub = require('./fakehub');
|
||||||
|
@ -100,6 +101,7 @@ module.exports = {
|
||||||
digitalplayground,
|
digitalplayground,
|
||||||
dogfart,
|
dogfart,
|
||||||
dogfartnetwork: dogfart,
|
dogfartnetwork: dogfart,
|
||||||
|
dorcel,
|
||||||
elegantangel,
|
elegantangel,
|
||||||
evilangel,
|
evilangel,
|
||||||
fakehub,
|
fakehub,
|
||||||
|
@ -189,6 +191,7 @@ module.exports = {
|
||||||
devilsfilm: famedigital,
|
devilsfilm: famedigital,
|
||||||
digitalplayground,
|
digitalplayground,
|
||||||
dtfsluts: fullpornnetwork,
|
dtfsluts: fullpornnetwork,
|
||||||
|
dorcelclub: dorcel,
|
||||||
elegantangel,
|
elegantangel,
|
||||||
evilangel,
|
evilangel,
|
||||||
eyeontheguy: hush,
|
eyeontheguy: hush,
|
||||||
|
|
|
@ -95,6 +95,10 @@ function exists(context, selector) {
|
||||||
return !!q(context, selector);
|
return !!q(context, selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function count(context, selector) {
|
||||||
|
return all(context, selector)?.length || 0;
|
||||||
|
}
|
||||||
|
|
||||||
function content(context, selector, applyTrim = true) {
|
function content(context, selector, applyTrim = true) {
|
||||||
return q(context, selector, 'textContent', applyTrim);
|
return q(context, selector, 'textContent', applyTrim);
|
||||||
}
|
}
|
||||||
|
@ -323,6 +327,7 @@ const quFuncs = {
|
||||||
contents,
|
contents,
|
||||||
cnt: content,
|
cnt: content,
|
||||||
cnts: contents,
|
cnts: contents,
|
||||||
|
count,
|
||||||
date,
|
date,
|
||||||
dateAgo,
|
dateAgo,
|
||||||
dur: duration,
|
dur: duration,
|
||||||
|
|