初始化6.2.2

Signed-off-by: HITSword <admin@huayizhiyun.com>
This commit is contained in:
HITSword
2020-04-16 16:26:24 +08:00
commit 26e6687c3f
1630 changed files with 144200 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
<?php
namespace InstagramScraper;
class Endpoints
{
const BASE_URL = 'https://www.instagram.com';
const LOGIN_URL = 'https://www.instagram.com/accounts/login/ajax/';
const ACCOUNT_PAGE = 'https://www.instagram.com/{username}';
const MEDIA_LINK = 'https://www.instagram.com/p/{code}';
const ACCOUNT_MEDIAS = 'https://www.instagram.com/graphql/query/?query_hash=42323d64886122307be10013ad2dcc44&variables={variables}';
const ACCOUNT_JSON_INFO = 'https://www.instagram.com/{username}/?__a=1';
const MEDIA_JSON_INFO = 'https://www.instagram.com/p/{code}/?__a=1';
const MEDIA_JSON_BY_LOCATION_ID = 'https://www.instagram.com/explore/locations/{{facebookLocationId}}/?__a=1&max_id={{maxId}}';
const MEDIA_JSON_BY_TAG = 'https://www.instagram.com/explore/tags/{tag}/?__a=1&max_id={max_id}';
const GENERAL_SEARCH = 'https://www.instagram.com/web/search/topsearch/?query={query}';
const ACCOUNT_JSON_INFO_BY_ID = 'ig_user({userId}){id,username,external_url,full_name,profile_pic_url,biography,followed_by{count},follows{count},media{count},is_private,is_verified}';
const COMMENTS_BEFORE_COMMENT_ID_BY_CODE = 'https://www.instagram.com/graphql/query/?query_id=17852405266163336&shortcode={{shortcode}}&first={{count}}&after={{commentId}}';
const LAST_LIKES_BY_CODE = 'ig_shortcode({{code}}){likes{nodes{id,user{id,profile_pic_url,username,follows{count},followed_by{count},biography,full_name,media{count},is_private,external_url,is_verified}},page_info}}';
const LIKES_BY_SHORTCODE = 'https://www.instagram.com/graphql/query/?query_id=17864450716183058&variables={"shortcode":"{{shortcode}}","first":{{count}},"after":"{{likeId}}"}';
const FOLLOWING_URL = 'https://www.instagram.com/graphql/query/?query_id=17874545323001329&id={{accountId}}&first={{count}}&after={{after}}';
const FOLLOWERS_URL = 'https://www.instagram.com/graphql/query/?query_id=17851374694183129&id={{accountId}}&first={{count}}&after={{after}}';
const FOLLOW_URL = 'https://www.instagram.com/web/friendships/{{accountId}}/follow/';
const UNFOLLOW_URL = 'https://www.instagram.com/web/friendships/{{accountId}}/unfollow/';
const USER_FEED = 'https://www.instagram.com/graphql/query/?query_id=17861995474116400&fetch_media_item_count=12&fetch_media_item_cursor=&fetch_comment_count=4&fetch_like=10';
const USER_FEED2 = 'https://www.instagram.com/?__a=1';
const INSTAGRAM_QUERY_URL = 'https://www.instagram.com/query/';
const INSTAGRAM_CDN_URL = 'https://scontent.cdninstagram.com/';
const ACCOUNT_JSON_PRIVATE_INFO_BY_ID = 'https://i.instagram.com/api/v1/users/{userId}/info/';
const ACCOUNT_MEDIAS2 = 'https://www.instagram.com/graphql/query/?query_id=17880160963012870&id={{accountId}}&first=10&after=';
// Look alike??
const URL_SIMILAR = 'https://www.instagram.com/graphql/query/?query_id=17845312237175864&id=4663052';
const GRAPH_QL_QUERY_URL = 'https://www.instagram.com/graphql/query/?query_id={{queryId}}';
private static $requestMediaCount = 30;
/**
* @param int $count
*/
public static function setAccountMediasRequestCount($count)
{
static::$requestMediaCount = $count;
}
public static function getAccountMediasRequestCount()
{
return static::$requestMediaCount;
}
public static function getAccountPageLink($username)
{
return str_replace('{username}', urlencode($username), static::ACCOUNT_PAGE);
}
public static function getAccountJsonLink($username)
{
return str_replace('{username}', urlencode($username), static::ACCOUNT_JSON_INFO);
}
public static function getAccountJsonInfoLinkByAccountId($id)
{
return str_replace('{userId}', urlencode($id), static::ACCOUNT_JSON_INFO_BY_ID);
}
public static function getAccountJsonPrivateInfoLinkByAccountId($id)
{
return str_replace('{userId}', urlencode($id), static::ACCOUNT_JSON_PRIVATE_INFO_BY_ID);
}
public static function getAccountMediasJsonLink($variables)
{
return str_replace('{variables}', urlencode($variables), static::ACCOUNT_MEDIAS);
}
public static function getMediaPageLink($code)
{
return str_replace('{code}', urlencode($code), static::MEDIA_LINK);
}
public static function getMediaJsonLink($code)
{
return str_replace('{code}', urlencode($code), static::MEDIA_JSON_INFO);
}
public static function getMediasJsonByLocationIdLink($facebookLocationId, $maxId = '')
{
$url = str_replace('{{facebookLocationId}}', urlencode($facebookLocationId), static::MEDIA_JSON_BY_LOCATION_ID);
return str_replace('{{maxId}}', urlencode($maxId), $url);
}
public static function getMediasJsonByTagLink($tag, $maxId = '')
{
$url = str_replace('{tag}', urlencode($tag), static::MEDIA_JSON_BY_TAG);
return str_replace('{max_id}', urlencode($maxId), $url);
}
public static function getGeneralSearchJsonLink($query)
{
return str_replace('{query}', urlencode($query), static::GENERAL_SEARCH);
}
public static function getCommentsBeforeCommentIdByCode($code, $count, $commentId)
{
$url = str_replace('{{shortcode}}', urlencode($code), static::COMMENTS_BEFORE_COMMENT_ID_BY_CODE);
$url = str_replace('{{count}}', urlencode($count), $url);
return str_replace('{{commentId}}', urlencode($commentId), $url);
}
public static function getLastLikesByCodeLink($code)
{
$url = str_replace('{{code}}', urlencode($code), static::LAST_LIKES_BY_CODE);
return $url;
}
public static function getLastLikesByCode($code, $count, $lastLikeID)
{
$url = str_replace('{{shortcode}}', urlencode($code), static::LIKES_BY_SHORTCODE);
$url = str_replace('{{count}}', urlencode($count), $url);
$url = str_replace('{{likeId}}', urlencode($lastLikeID), $url);
return $url;
}
public static function getGraphQlUrl($queryId, $parameters)
{
$url = str_replace('{{queryId}}', urlencode($queryId), static::GRAPH_QL_QUERY_URL);
if (!empty($parameters)) {
$query_string = http_build_query($parameters);
$url .= '&' . $query_string;
}
return $url;
}
public static function getFollowUrl($accountId)
{
$url = str_replace('{{accountId}}', urlencode($accountId), static::FOLLOW_URL);
return $url;
}
public static function getFollowersJsonLink($accountId, $count, $after = '')
{
$url = str_replace('{{accountId}}', urlencode($accountId), static::FOLLOWERS_URL);
$url = str_replace('{{count}}', urlencode($count), $url);
if ($after === '') {
$url = str_replace('&after={{after}}', '', $url);
} else {
$url = str_replace('{{after}}', urlencode($after), $url);
}
return $url;
}
public static function getFollowingJsonLink($accountId, $count, $after = '')
{
$url = str_replace('{{accountId}}', urlencode($accountId), static::FOLLOWING_URL);
$url = str_replace('{{count}}', urlencode($count), $url);
if ($after === '') {
$url = str_replace('&after={{after}}', '', $url);
} else {
$url = str_replace('{{after}}', urlencode($after), $url);
}
return $url;
}
public static function getUserStoriesLink()
{
$url = self::getGraphQlUrl(InstagramQueryId::USER_STORIES, ['variables' => json_encode([])]);
return $url;
}
public static function getStoriesLink($variables)
{
$url = self::getGraphQlUrl(InstagramQueryId::STORIES, ['variables' => json_encode($variables)]);
return $url;
}
}
@@ -0,0 +1,9 @@
<?php
namespace InstagramScraper\Exception;
class InstagramAuthException extends \Exception
{
}
@@ -0,0 +1,7 @@
<?php
namespace InstagramScraper\Exception;
class InstagramException extends \Exception
{
}
@@ -0,0 +1,7 @@
<?php
namespace InstagramScraper\Exception;
class InstagramNotFoundException extends \Exception
{
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,15 @@
<?php
namespace InstagramScraper;
class InstagramQueryId
{
/**
* id = {{accoundId}}, first = {{count}}, after = {{mediaId}}
*/
const USER_MEDIAS = '17880160963012870';
const USER_STORIES = '17890626976041463';
const STORIES = '17873473675158481';
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,28 @@
<?php
namespace InstagramScraper\Model;
use InstagramScraper\Traits\ArrayLikeTrait;
use InstagramScraper\Traits\InitializerTrait;
/**
* Class AbstractModel
* @package InstagramScraper\Model
*/
abstract class AbstractModel implements \ArrayAccess
{
use InitializerTrait, ArrayLikeTrait;
/**
* @var array
*/
protected static $initPropertiesMap = [];
/**
* @return array
*/
public static function getColumns()
{
return \array_keys(static::$initPropertiesMap);
}
}
+249
View File
@@ -0,0 +1,249 @@
<?php
namespace InstagramScraper\Model;
/**
* Class Account
* @package InstagramScraper\Model
*/
class Account extends AbstractModel
{
/**
* User id
* @var string
*/
protected $id = 0;
/**
* Username
* @var string
*/
protected $username = '';
/**
* Full name
* @var string
*/
protected $fullName = '';
/**
* Profile picture url
* @var string
*/
protected $profilePicUrl = '';
/**
* Profile picture url HD
* @var string
*/
protected $profilePicUrlHd = '';
/**
* Information filled by user
* @var string
*/
protected $biography = '';
/**
* Url provided by user in profile
* @var string
*/
protected $externalUrl = '';
/**
* Number of subscriptions
* @var integer
*/
protected $followsCount = 0;
/**
* Number of followers
* @var integer
*/
protected $followedByCount = 0;
/**
* Number of medias published by user
* @var integer
*/
protected $mediaCount = 0;
/**
* true if account is private
* @var boolean
*/
protected $isPrivate = false;
/**
* true if verified by Instagram as celebrity
* @var boolean
*/
protected $isVerified = false;
/**
* @var bool
*/
protected $isLoaded = false;
/**
* @return bool
*/
public function isLoaded()
{
return $this->isLoaded;
}
/**
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* @return int
*/
public function getId()
{
if (PHP_INT_SIZE > 4) {
$this->id = (int)$this->id;
}
return $this->id;
}
/**
* @return string
*/
public function getFullName()
{
return $this->fullName;
}
/**
* @return string
*/
public function getProfilePicUrl()
{
return $this->profilePicUrl;
}
/**
* @return string
*/
public function getProfilePicUrlHd()
{
$toReturn = $this->profilePicUrl;
if ($this->profilePicUrlHd !== '') {
$toReturn = $this->profilePicUrlHd;
}
return $toReturn;
}
/**
* @return string
*/
public function getBiography()
{
return $this->biography;
}
/**
* @return string
*/
public function getExternalUrl()
{
return $this->externalUrl;
}
/**
* @return int
*/
public function getFollowsCount()
{
return $this->followsCount;
}
/**
* @return int
*/
public function getFollowedByCount()
{
return $this->followedByCount;
}
/**
* @return int
*/
public function getMediaCount()
{
return $this->mediaCount;
}
/**
* @return bool
*/
public function isPrivate()
{
return $this->isPrivate;
}
/**
* @return bool
*/
public function isVerified()
{
return $this->isVerified;
}
/**
* @param $value
* @param $prop
* @param $array
*/
protected function initPropertiesCustom($value, $prop, $array)
{
switch ($prop) {
case 'id':
case 'pk':
$this->id = $value;
break;
case 'username':
$this->username = $value;
break;
case 'full_name':
$this->fullName = $value;
break;
case 'profile_pic_url':
$this->profilePicUrl = $value;
break;
case 'profile_pic_url_hd':
$this->profilePicUrlHd = $value;
break;
case 'biography':
$this->biography = $value;
break;
case 'external_url':
$this->externalUrl = $value;
break;
case 'edge_follow':
$this->followsCount = !empty($array[$prop]['count']) ? (int)$array[$prop]['count'] : 0;
break;
case 'edge_followed_by':
$this->followedByCount = !empty($array[$prop]['count']) ? (int)$array[$prop]['count'] : 0;
break;
case 'edge_owner_to_timeline_media':
$this->mediaCount = !empty($array[$prop]['count']) ? $array[$prop]['count'] : 0;
break;
case 'is_private':
$this->isPrivate = (bool)$value;
break;
case 'is_verified':
$this->isVerified = (bool)$value;
break;
}
}
}
@@ -0,0 +1,235 @@
<?php
namespace InstagramScraper\Model;
/**
* Class CarouselMedia
* @package InstagramScraper\Model
*/
class CarouselMedia
{
/**
* @var string
*/
private $type;
/**
* @var string
*/
private $imageLowResolutionUrl;
/**
* @var string
*/
private $imageThumbnailUrl;
/**
* @var string
*/
private $imageStandardResolutionUrl;
/**
* @var string
*/
private $imageHighResolutionUrl;
/**
* @var string
*/
private $videoLowResolutionUrl;
/**
* @var string
*/
private $videoStandardResolutionUrl;
/**
* @var string
*/
private $videoLowBandwidthUrl;
/**
* @var
*/
private $videoViews;
/**
* CarouselMedia constructor.
*/
public function __construct()
{
return $this;
}
/**
* @return mixed
*/
public function getType()
{
return $this->type;
}
/**
* @param mixed $type
*
* @return $this
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* @return mixed
*/
public function getImageLowResolutionUrl()
{
return $this->imageLowResolutionUrl;
}
/**
* @param mixed $imageLowResolutionUrl
*
* @return CarouselMedia
*/
public function setImageLowResolutionUrl($imageLowResolutionUrl)
{
$this->imageLowResolutionUrl = $imageLowResolutionUrl;
return $this;
}
/**
* @return mixed
*/
public function getImageThumbnailUrl()
{
return $this->imageThumbnailUrl;
}
/**
* @param mixed $imageThumbnailUrl
*
* @return CarouselMedia
*/
public function setImageThumbnailUrl($imageThumbnailUrl)
{
$this->imageThumbnailUrl = $imageThumbnailUrl;
return $this;
}
/**
* @return mixed
*/
public function getImageStandardResolutionUrl()
{
return $this->imageStandardResolutionUrl;
}
/**
* @param mixed $imageStandardResolutionUrl
*
* @return CarouselMedia
*/
public function setImageStandardResolutionUrl($imageStandardResolutionUrl)
{
$this->imageStandardResolutionUrl = $imageStandardResolutionUrl;
return $this;
}
/**
* @return mixed
*/
public function getImageHighResolutionUrl()
{
return $this->imageHighResolutionUrl;
}
/**
* @param mixed $imageHighResolutionUrl
*
* @return CarouselMedia
*/
public function setImageHighResolutionUrl($imageHighResolutionUrl)
{
$this->imageHighResolutionUrl = $imageHighResolutionUrl;
return $this;
}
/**
* @return mixed
*/
public function getVideoLowResolutionUrl()
{
return $this->videoLowResolutionUrl;
}
/**
* @param mixed $videoLowResolutionUrl
*
* @return CarouselMedia
*/
public function setVideoLowResolutionUrl($videoLowResolutionUrl)
{
$this->videoLowResolutionUrl = $videoLowResolutionUrl;
return $this;
}
/**
* @return mixed
*/
public function getVideoStandardResolutionUrl()
{
return $this->videoStandardResolutionUrl;
}
/**
* @param mixed $videoStandardResolutionUrl
*
* @return CarouselMedia
*/
public function setVideoStandardResolutionUrl($videoStandardResolutionUrl)
{
$this->videoStandardResolutionUrl = $videoStandardResolutionUrl;
return $this;
}
/**
* @return mixed
*/
public function getVideoLowBandwidthUrl()
{
return $this->videoLowBandwidthUrl;
}
/**
* @param mixed $videoLowBandwidthUrl
*
* @return CarouselMedia
*/
public function setVideoLowBandwidthUrl($videoLowBandwidthUrl)
{
$this->videoLowBandwidthUrl = $videoLowBandwidthUrl;
return $this;
}
/**
* @return mixed
*/
public function getVideoViews()
{
return $this->videoViews;
}
/**
* @param mixed $videoViews
*
* @return CarouselMedia
*/
public function setVideoViews($videoViews)
{
$this->videoViews = $videoViews;
return $this;
}
}
@@ -0,0 +1,87 @@
<?php
namespace InstagramScraper\Model;
class Comment extends AbstractModel
{
/**
* @var
*/
protected $id;
/**
* @var
*/
protected $text;
/**
* @var
*/
protected $createdAt;
/**
* @var Account
*/
protected $owner;
/**
* @var bool
*/
protected $isLoaded = false;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return mixed
*/
public function getText()
{
return $this->text;
}
/**
* @return mixed
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* @return Account
*/
public function getOwner()
{
return $this->owner;
}
/**
* @param $value
* @param $prop
*/
protected function initPropertiesCustom($value, $prop)
{
switch ($prop) {
case 'id':
$this->id = $value;
break;
case 'created_at':
$this->createdAt = $value;
break;
case 'text':
$this->text = $value;
break;
case 'owner':
$this->owner = Account::create($value);
break;
}
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
namespace InstagramScraper\Model;
class Like extends AbstractModel
{
/**
* @var
*/
protected $id;
/**
* @var Account
*/
protected $username;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return mixed
*/
public function getUserName()
{
return $this->username;
}
/**
* @param $value
* @param $prop
*/
protected function initPropertiesCustom($value, $prop)
{
switch ($prop) {
case 'id':
$this->id = $value;
break;
case 'username':
$this->username = $value;
break;
}
}
}
@@ -0,0 +1,109 @@
<?php
namespace InstagramScraper\Model;
class Location extends AbstractModel
{
/**
* @var array
*/
protected static $initPropertiesMap = [
'id' => 'id',
'has_public_page' => 'hasPublicPage',
'name' => 'name',
'slug' => 'slug',
'lat' => 'lat',
'lng' => 'lng',
'modified' => 'modified'
];
/**
* @var
*/
protected $id;
/**
* @var
*/
protected $hasPublicPage;
/**
* @var
*/
protected $name;
/**
* @var
*/
protected $slug;
/**
* @var
*/
protected $lng;
/**
* @var
*/
protected $lat;
/**
* @var bool
*/
protected $isLoaded = false;
/**
* @var
*/
protected $modified;
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return mixed
*/
public function getHasPublicPage()
{
return $this->hasPublicPage;
}
/**
* @return mixed
*/
public function getName()
{
return $this->name;
}
/**
* @return mixed
*/
public function getSlug()
{
return $this->slug;
}
/**
* @return mixed
*/
public function getLng()
{
return $this->lng;
}
/**
* @return mixed
*/
public function getLat()
{
return $this->lat;
}
/**
* @return mixed
*/
public function getModified()
{
return $this->modified;
}
}
+663
View File
@@ -0,0 +1,663 @@
<?php
namespace InstagramScraper\Model;
use InstagramScraper\Endpoints;
/**
* Class Media
* @package InstagramScraper\Model
*/
class Media extends AbstractModel
{
const TYPE_IMAGE = 'image';
const TYPE_VIDEO = 'video';
const TYPE_SIDECAR = 'sidecar';
const TYPE_CAROUSEL = 'carousel';
/**
* @var string
*/
protected $id = '';
/**
* @var string
*/
protected $shortCode = '';
/**
* @var int
*/
protected $createdTime = 0;
/**
* @var string
*/
protected $type = '';
/**
* @var string
*/
protected $link = '';
/**
* @var string
*/
protected $imageLowResolutionUrl = '';
/**
* @var string
*/
protected $imageThumbnailUrl = '';
/**
* @var string
*/
protected $imageStandardResolutionUrl = '';
/**
* @var string
*/
protected $imageHighResolutionUrl = '';
/**
* @var array
*/
protected $squareThumbnailsUrl = [];
/**
* @var array
*/
protected $carouselMedia = [];
/**
* @var string
*/
protected $caption = '';
/**
* @var bool
*/
protected $isCaptionEdited = false;
/**
* @var bool
*/
protected $isAd = false;
/**
* @var string
*/
protected $videoLowResolutionUrl = '';
/**
* @var string
*/
protected $videoStandardResolutionUrl = '';
/**
* @var string
*/
protected $videoLowBandwidthUrl = '';
/**
* @var int
*/
protected $videoViews = 0;
/**
* @var Account
*/
protected $owner;
/**
* @var int
*/
protected $ownerId = 0;
/**
* @var int
*/
protected $likesCount = 0;
/**
* @var
*/
protected $locationId;
/**
* @var string
*/
protected $locationName = '';
/**
* @var string
*/
protected $commentsCount = 0;
/**
* @var Comment[]
*/
protected $comments = [];
/**
* @var bool
*/
protected $hasMoreComments = false;
/**
* @var string
*/
protected $commentsNextPage = '';
/**
* @var Media[]|array
*/
protected $sidecarMedias = [];
/**
* @param string $code
*
* @return int
*/
public static function getIdFromCode($code)
{
$alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
$id = 0;
for ($i = 0; $i < strlen($code); $i++) {
$c = $code[$i];
$id = $id * 64 + strpos($alphabet, $c);
}
return $id;
}
/**
* @param string $id
*
* @return mixed
*/
public static function getLinkFromId($id)
{
$code = Media::getCodeFromId($id);
return Endpoints::getMediaPageLink($code);
}
/**
* @param string $id
*
* @return string
*/
public static function getCodeFromId($id)
{
$parts = explode('_', $id);
$id = $parts[0];
$alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
$code = '';
while ($id > 0) {
$remainder = $id % 64;
$id = ($id - $remainder) / 64;
$code = $alphabet{$remainder} . $code;
};
return $code;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getShortCode()
{
return $this->shortCode;
}
/**
* @return int
*/
public function getCreatedTime()
{
return $this->createdTime;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @return string
*/
public function getLink()
{
return $this->link;
}
/**
* @return string
*/
public function getImageLowResolutionUrl()
{
return $this->imageLowResolutionUrl;
}
/**
* @return string
*/
public function getImageThumbnailUrl()
{
return $this->imageThumbnailUrl;
}
/**
* @return string
*/
public function getImageStandardResolutionUrl()
{
return $this->imageStandardResolutionUrl;
}
/**
* @return string
*/
public function getImageHighResolutionUrl()
{
return $this->imageHighResolutionUrl;
}
/**
* @return array
*/
public function getSquareThumbnailsUrl()
{
return $this->squareThumbnailsUrl;
}
/**
* @return array
*/
public function getCarouselMedia()
{
return $this->carouselMedia;
}
/**
* @return string
*/
public function getCaption()
{
return $this->caption;
}
/**
* @return bool
*/
public function isCaptionEdited()
{
return $this->isCaptionEdited;
}
/**
* @return bool
*/
public function isAd()
{
return $this->isAd;
}
/**
* @return string
*/
public function getVideoLowResolutionUrl()
{
return $this->videoLowResolutionUrl;
}
/**
* @return string
*/
public function getVideoStandardResolutionUrl()
{
return $this->videoStandardResolutionUrl;
}
/**
* @return string
*/
public function getVideoLowBandwidthUrl()
{
return $this->videoLowBandwidthUrl;
}
/**
* @return int
*/
public function getVideoViews()
{
return $this->videoViews;
}
/**
* @return int
*/
public function getOwnerId()
{
return $this->ownerId;
}
/**
* @return int
*/
public function getLikesCount()
{
return $this->likesCount;
}
/**
* @return mixed
*/
public function getLocationId()
{
return $this->locationId;
}
/**
* @return string
*/
public function getLocationName()
{
return $this->locationName;
}
/**
* @return string
*/
public function getCommentsCount()
{
return $this->commentsCount;
}
/**
* @return Comment[]
*/
public function getComments()
{
return $this->comments;
}
/**
* @return bool
*/
public function hasMoreComments()
{
return $this->hasMoreComments;
}
/**
* @return string
*/
public function getCommentsNextPage()
{
return $this->commentsNextPage;
}
/**
* @return Media[]|array
*/
public function getSidecarMedias()
{
return $this->sidecarMedias;
}
/**
* @param $value
* @param $prop
*/
protected function initPropertiesCustom($value, $prop, $arr)
{
switch ($prop) {
case 'id':
$this->id = $value;
break;
case 'type':
$this->type = $value;
break;
case 'created_time':
$this->createdTime = (int)$value;
break;
case 'code':
$this->shortCode = $value;
$this->link = Endpoints::getMediaPageLink($this->shortCode);
break;
case 'link':
$this->link = $value;
break;
case 'comments':
$this->commentsCount = $arr[$prop]['count'];
break;
case 'likes':
$this->likesCount = $arr[$prop]['count'];
break;
case 'display_resources':
foreach ($value as $thumbnail) {
$thumbnailsUrl[] = $thumbnail['src'];
switch ($thumbnail['config_width']) {
case 640:
$this->imageThumbnailUrl = $thumbnail['src'];
break;
case 750:
$this->imageLowResolutionUrl = $thumbnail['src'];
break;
case 1080:
$this->imageStandardResolutionUrl = $thumbnail['src'];
break;
default:
;
}
}
$this->squareThumbnailsUrl = $thumbnailsUrl;
break;
case 'display_url':
$this->imageHighResolutionUrl = $value;
break;
case 'display_src':
$this->imageHighResolutionUrl = $value;
if (!isset($this->type)) {
$this->type = static::TYPE_IMAGE;
}
break;
case 'carousel_media':
$this->type = self::TYPE_CAROUSEL;
$this->carouselMedia = [];
foreach ($arr["carousel_media"] as $carouselArray) {
self::setCarouselMedia($arr, $carouselArray, $this);
}
break;
case 'caption':
$this->caption = $arr[$prop];
break;
case 'video_views':
$this->videoViews = $value;
$this->type = static::TYPE_VIDEO;
break;
case 'videos':
$this->videoLowResolutionUrl = $arr[$prop]['low_resolution']['url'];
$this->videoStandardResolutionUrl = $arr[$prop]['standard_resolution']['url'];
$this->videoLowBandwidthUrl = $arr[$prop]['low_bandwidth']['url'];
break;
case 'video_resources':
foreach ($value as $video) {
if ($video['profile'] == 'MAIN') {
$this->videoStandardResolutionUrl = $video['src'];
} elseif ($video['profile'] == 'BASELINE') {
$this->videoLowResolutionUrl = $video['src'];
$this->videoLowBandwidthUrl = $video['src'];
}
}
break;
case 'location':
$this->locationId = $arr[$prop]['id'];
$this->locationName = $arr[$prop]['name'];
break;
case 'user':
$this->owner = Account::create($arr[$prop]);
break;
case 'is_video':
if ((bool)$value) {
$this->type = static::TYPE_VIDEO;
}
break;
case 'video_url':
$this->videoStandardResolutionUrl = $value;
break;
case 'video_view_count':
$this->videoViews = $value;
break;
case 'caption_is_edited':
$this->isCaptionEdited = $value;
break;
case 'is_ad':
$this->isAd = $value;
break;
case 'taken_at_timestamp':
$this->createdTime = $value;
break;
case 'shortcode':
$this->shortCode = $value;
$this->link = Endpoints::getMediaPageLink($this->shortCode);
break;
case 'edge_media_to_comment':
if (isset($arr[$prop]['count'])) {
$this->commentsCount = (int) $arr[$prop]['count'];
}
if (isset($arr[$prop]['edges']) && is_array($arr[$prop]['edges'])) {
foreach ($arr[$prop]['edges'] as $commentData) {
$this->comments[] = Comment::create($commentData['node']);
}
}
if (isset($arr[$prop]['page_info']['has_next_page'])) {
$this->hasMoreComments = (bool) $arr[$prop]['page_info']['has_next_page'];
}
if (isset($arr[$prop]['page_info']['end_cursor'])) {
$this->commentsNextPage = (string) $arr[$prop]['page_info']['end_cursor'];
}
break;
case 'edge_media_preview_like':
$this->likesCount = $arr[$prop]['count'];
break;
case 'edge_liked_by':
$this->likesCount = $arr[$prop]['count'];
break;
case 'edge_media_to_caption':
if (is_array($arr[$prop]['edges']) && !empty($arr[$prop]['edges'])) {
$first_caption = $arr[$prop]['edges'][0];
if (is_array($first_caption) && isset($first_caption['node'])) {
if (is_array($first_caption['node']) && isset($first_caption['node']['text'])) {
$this->caption = $arr[$prop]['edges'][0]['node']['text'];
}
}
}
break;
case 'edge_sidecar_to_children':
if (!is_array($arr[$prop]['edges'])) {
break;
}
foreach ($arr[$prop]['edges'] as $edge) {
if (!isset($edge['node'])) {
continue;
}
$this->sidecarMedias[] = static::create($edge['node']);
}
break;
case 'owner':
$this->owner = Account::create($arr[$prop]);
break;
case 'date':
$this->createdTime = (int)$value;
break;
case '__typename':
if ($value == 'GraphImage') {
$this->type = static::TYPE_IMAGE;
} else if ($value == 'GraphVideo') {
$this->type = static::TYPE_VIDEO;
} else if ($value == 'GraphSidecar') {
$this->type = static::TYPE_SIDECAR;
}
break;
}
if (!$this->ownerId && !is_null($this->owner)) {
$this->ownerId = $this->getOwner()->getId();
}
}
/**
* @param $mediaArray
* @param $carouselArray
* @param $instance
*
* @return mixed
*/
private static function setCarouselMedia($mediaArray, $carouselArray, $instance)
{
$carouselMedia = new CarouselMedia();
$carouselMedia->setType($carouselArray['type']);
if (isset($carouselArray['images'])) {
$carouselImages = self::getImageUrls($carouselArray['images']['standard_resolution']['url']);
$carouselMedia->setImageLowResolutionUrl($carouselImages['low']);
$carouselMedia->setImageThumbnailUrl($carouselImages['thumbnail']);
$carouselMedia->setImageStandardResolutionUrl($carouselImages['standard']);
$carouselMedia->setImageHighResolutionUrl($carouselImages['high']);
}
if ($carouselMedia->getType() === self::TYPE_VIDEO) {
if (isset($mediaArray['video_views'])) {
$carouselMedia->setVideoViews($carouselArray['video_views']);
}
if (isset($carouselArray['videos'])) {
$carouselMedia->setVideoLowResolutionUrl($carouselArray['videos']['low_resolution']['url']);
$carouselMedia->setVideoStandardResolutionUrl($carouselArray['videos']['standard_resolution']['url']);
$carouselMedia->setVideoLowBandwidthUrl($carouselArray['videos']['low_bandwidth']['url']);
}
}
array_push($instance->carouselMedia, $carouselMedia);
return $mediaArray;
}
/**
* @param string $imageUrl
*
* @return array
*/
private static function getImageUrls($imageUrl)
{
$parts = explode('/', parse_url($imageUrl)['path']);
$imageName = $parts[sizeof($parts) - 1];
$urls = [
'thumbnail' => Endpoints::INSTAGRAM_CDN_URL . 't/s150x150/' . $imageName,
'low' => Endpoints::INSTAGRAM_CDN_URL . 't/s320x320/' . $imageName,
'standard' => Endpoints::INSTAGRAM_CDN_URL . 't/s640x640/' . $imageName,
'high' => Endpoints::INSTAGRAM_CDN_URL . 't/' . $imageName,
];
return $urls;
}
/**
* @return Account
*/
public function getOwner()
{
return $this->owner;
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace InstagramScraper\Model;
/**
* Class Story
* @package InstagramScraper\Model
*/
class Story extends Media
{
private $skip_prop = [
'owner' => true,
];
/***
* We do not need some values - do not parse it for Story,
* for example - we do not need owner object inside story
*
* @param $value
* @param $prop
* @param $arr
*/
protected function initPropertiesCustom($value, $prop, $arr)
{
if (!empty($this->skip_prop[$prop])) {
return;
}
parent::initPropertiesCustom($value, $prop, $arr);
}
}
+55
View File
@@ -0,0 +1,55 @@
<?php
namespace InstagramScraper\Model;
/**
* Class Tag
* @package InstagramScraper\Model
*/
class Tag extends AbstractModel
{
/**
* @var array
*/
protected static $initPropertiesMap = [
'media_count' => 'mediaCount',
'name' => 'name',
'id' => 'initInt',
];
/**
* @var int
*/
protected $mediaCount = 0;
/**
* @var string
*/
protected $name;
/**
* @var int
*/
protected $id;
/**
* @return int
*/
public function getMediaCount()
{
return $this->mediaCount;
}
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
}
@@ -0,0 +1,41 @@
<?php
namespace InstagramScraper\Model;
/**
* Class UserStories
* @package InstagramScraper\Model
*/
class UserStories extends AbstractModel
{
/** @var Account */
protected $owner;
/** @var Story[] */
protected $stories;
public function setOwner($owner)
{
$this->owner = $owner;
}
public function getOwner()
{
return $this->owner;
}
public function addStory($story)
{
$this->stories[] = $story;
}
public function setStories($stories)
{
$this->stories = $stories;
}
public function getStories()
{
return $this->stories;
}
}
@@ -0,0 +1,113 @@
<?php
/**
* File: ArrayLikeTrait.php
* Project: instagram-php-scraper
* User: evgen
* Date: 19.07.17
* Time: 11:50
*/
namespace InstagramScraper\Traits;
/**
* ArrayAccess implementation
*/
trait ArrayLikeTrait
{
/**
* @param mixed $offset
*
* @return bool
*/
public function offsetExists($offset)
{
return $this->isMethod($offset, 'get') || \property_exists($this, $offset);
}
/**
* @param mixed $offset
*
* @return mixed
*/
public function offsetGet($offset)
{
if ($run = $this->isMethod($offset, 'get')) {
return $this->run($run);
} elseif (\property_exists($this, $offset)) {
if (isset($this->{$offset})) {
return $this->{$offset};
} elseif (isset($this::$offset)) {
return $this::$offset;
}
}
return null;
}
/**
* @param mixed $offset
* @param mixed $value
*
* @return void
*/
public function offsetSet($offset, $value)
{
if ($run = $this->isMethod($offset, 'set')) {
$this->run($run);
} else {
$this->{$offset} = $value;
}
}
/**
* @param mixed $offset
*
* @return void
*/
public function offsetUnset($offset)
{
if ($run = $this->isMethod($offset, 'unset')) {
$this->run($run);
} else {
$this->{$offset} = null;
}
}
/**
* @param $method
* @param $case
*
* @return bool|string
*/
protected function isMethod($method, $case)
{
$uMethod = $case . \ucfirst($method);
if (\method_exists($this, $uMethod)) {
return $uMethod;
}
if (\method_exists($this, $method)) {
return $method;
}
return false;
}
/**
* @param $method
*
* @return mixed
*/
protected function run($method)
{
if (\is_array($method)) {
$params = $method;
$method = \array_shift($params);
if ($params) {
return \call_user_func_array([$this, $method], $params);
}
}
return \call_user_func([$this, $method]);
}
}
@@ -0,0 +1,334 @@
<?php
/**
* File: InitializerTrait.php
* Project: instagram-php-scraper
* User: evgen
* Date: 19.07.17
* Time: 11:50
*/
namespace InstagramScraper\Traits;
trait InitializerTrait
{
/**
* @var bool
*/
protected $isNew = true;
/**
* @var bool
*/
protected $isLoaded = false;
/**
* @var bool - init data was empty
*/
protected $isLoadEmpty = true;
/**
* @var bool
*/
protected $isFake = false;
/**
* @var int
*/
protected $isAutoConstruct = false;
/**
* @var int
*/
protected $modified;
/**
* Array of initialization data
*
* @var array
*/
protected $data = [];
/**
* @param array $props
*/
protected function __construct(array $props = null)
{
$this->beforeInit();
$this->modified = \time();
if ($this->isAutoConstruct) {
$this->initAuto();
} elseif (empty($props)) {
$this->initDefaults();
} else {
$this->init($props);
}
$this->afterInit();
}
/**
* @return $this
*/
protected function beforeInit()
{
return $this;
}
/**
* @return $this
*/
final protected function initAuto()
{
foreach ($this as $prop => $value) {
if (isset(static::$initPropertiesMap[$prop]) and $methodOrProp = static::$initPropertiesMap[$prop] and \method_exists($this,
$methodOrProp)
) {
//if there is method then use it firstly
\call_user_func([$this, $methodOrProp], $value, $prop);
}
}
$this->isNew = false;
$this->isLoaded = true;
$this->isLoadEmpty = false;
return $this;
}
/**
* @return $this
*/
protected function initDefaults()
{
return $this;
}
/**
* @param array $props
*
* @return $this
*/
final protected function init(array $props)
{
//?reflection?
foreach ($props as $prop => $value) {
if (\method_exists($this, 'initPropertiesCustom')) {
\call_user_func([$this, 'initPropertiesCustom'], $value, $prop, $props);
} elseif (isset(static::$initPropertiesMap[$prop])) {
$methodOrProp = static::$initPropertiesMap[$prop];
if (\method_exists($this, $methodOrProp)) {
//if there is method then use it firstly
\call_user_func([$this, $methodOrProp], $value, $prop, $props);
} elseif (\property_exists($this, $methodOrProp)) {
//if there is property then it just assign value
$this->{$methodOrProp} = $value;
} else {
//otherwise fill help data array
//for following initialization
$this->data[$methodOrProp] = $value;
$this->data[$prop] = $value;
}
} else {
//otherwise fill help data array
$this->data[$prop] = $value;
}
}
$this->isNew = false;
$this->isLoaded = true;
$this->isLoadEmpty = false;
return $this;
}
/**
* @return $this
*/
protected function afterInit()
{
return $this;
}
/**
* @return $this
*/
public static function fake()
{
return static::create()->setFake(true);
}
/**
* @param bool $value
*
* @return $this
*/
protected function setFake($value = true)
{
$this->isFake = (bool)$value;
return $this;
}
/**
* @param array $params
*
* @return static
*/
public static function create(array $params = null)
{
return new static($params);
}
/**
* @return bool
*/
public function isNotEmpty()
{
return !$this->isLoadEmpty;
}
/**
* @return bool
*/
public function isFake()
{
return $this->isFake;
}
/**
* @return array
*/
public function toArray()
{
$ret = [];
$map = static::$initPropertiesMap;
foreach ($map as $key => $init) {
if (\property_exists($this, $key)) {
//if there is property then it just assign value
$ret[$key] = $this->{$key};
} elseif (isset($this[$key])) {
//probably array access
$ret[$key] = $this[$key];
} else {
$ret[$key] = null;
}
}
return $ret;
}
/**
* @param $datetime
*
* @return $this
*/
protected function initModified($datetime)
{
$this->modified = \strtotime($datetime);
return $this;
}
/**
* @param string $date
* @param string $key
*
* @return $this
*/
protected function initDatetime($date, $key)
{
return $this->initProperty(\strtotime($date), $key);
}
/**
* @param $value
* @param $key
*
* @return $this
*/
protected function initProperty($value, $key)
{
$keys = \func_get_args();
unset($keys[0]); //remove value
if (\count($keys) > 1) {
foreach ($keys as $key) {
if (\property_exists($this, $key)) { //first found set
$this->{$key} = $value;
return $this;
}
}
} elseif (\property_exists($this, $key)) {
$this->{$key} = $value;
}
return $this;
}
/**
* @param mixed $value
* @param string $key
*
* @return $this
*/
protected function initBool($value, $key)
{
return $this->initProperty(!empty($value), "is{$key}", $key);
}
/**
* @param mixed $value
* @param string $key
*
* @return $this
*/
protected function initInt($value, $key)
{
return $this->initProperty((int)$value, $key);
}
/**
* @param mixed $value
* @param string $key
*
* @return $this
*/
protected function initFloat($value, $key)
{
return $this->initProperty((float)$value, $key);
}
/**
* @param string $rawData
* @param string $key
*
* @return $this
*/
protected function initJsonArray($rawData, $key)
{
$value = \json_decode($rawData, true, 512, JSON_BIGINT_AS_STRING);
if (empty($value)) {
//could not resolve -
if ('null' === $rawData or '' === $rawData) {
$value = [];
} else {
$value = (array)$rawData;
}
} else {
$value = (array)$value;
}
return $this->initProperty($value, $key);
}
/**
* @param mixed $value
* @param string $key
*
* @return $this
*/
protected function initExplode($value, $key)
{
return $this->initProperty(\explode(',', $value), "is{$key}", $key);
}
}