Using DOM to get HTML code. - php

I am collecting username, title, video count and comment count from html source. Consider this link
Here is my code to get it:
function getParameter($url)
{
$html = file_get_html($url);
if($html)
{
$containers1 = $html->find('div.v div.v-link v-meta-entry');
foreach($containers1 as $container)
{
$plays = $container->find('v-num'); // get nos of time video played
$item = new stdClass();
foreach($plays as $play)
{
$nos = $play->plaintext;
}
//echo $address;
}
$containers2 = $html->find('div.v div.v-link v-meta va a'); //get user name
foreach($containers2 as $username)
{
$user = $username->plaintext;
}
$containers3 = $html->find('div.v div.v-link a'); //get video title
foreach($containers3 as $title)
{
$title = $title->plaintext;
}
$commentcontainers = $html->find('div.ico-statcomment span'); //get nos of comments
foreach($commentcontainer as $cont)
{
$comments = $cont->plaintext;
}
return $data;
}
}
But it gives this error:
Warning: Invalid argument supplied for foreach() in /var/www/html/scrap/yelp/yoku.php on line 41
any hints for this?
Here is the source code snippet:
<div class="v" >
<div class="v-thumb">
<img src="http://r1.ykimg.com/0515000052B7B3D46714C0318106EA36" alt="和小姚晨约会激动抽筋" />
<div class="v-thumb-tagrb"><span class="v-time">08:56</span></div>
</div>
<div class="v-link">
</div>
<div class="v-meta va">
<div class="v-meta-neck">
<a class="v-useravatar" href="http://i.youku.com/u/UMTQxNDg3NzA4" target="_blank"><img title="嘻哈四重奏" src="http://g3.ykimg.com/0130391F455211D40E180C021BBB97D37C4057-26F4-2F53-A8CD-4A4139415701"></a>
<span class="v-status"> </span>
<a class="v-username" href="http://i.youku.com/u/UMTQxNDg3NzA4" target="_blank">嘻哈四重奏</a>
</div>
<div class="v-meta-title">和小姚晨约会激动抽筋</div>
<div class="v-meta-entry">
<i class="ico-statplay" title="播放"></i><span class="v-num">588万</span> <i title="评论" class="ico-statcomment"></i><span class="v-num">1,290</span> </div>
<div class="v-meta-overlay"></div>
</div>
</div>

Check selectors, documentation here simplehtmldom. For example, I did some changes in selectors.
function getParameter($url)
{
$html = file_get_html($url);
if($html)
{
//we iterate all 'div.v' and select data from every 'div.v' separately
$containersDiv = $html->find('div.v');
foreach($containersDiv as $div)
{
$containers1 = $div->find('div[class=v-meta va] div.v-meta-entry');
foreach($containers1 as $container)
{
$plays = $container->find('.v-num'); // get nos of time video played
$item = new stdClass();
foreach($plays as $play)
{
$nos = $play->plaintext;
}
//echo $address;
}
$containers2 = $div->find('div[class=v-meta va] a'); //get user name
foreach($containers2 as $username)
{
$user = $username->plaintext;
}
$containers3 = $div->find('div.v-link a'); //get video title
foreach($containers3 as $title)
{
$title = $title->plaintext;
}
$commentcontainers = $div->find('div[class=v-meta va] div.v-meta-entry span'); //get nos of comments changed
foreach($commentcontainer as $cont)
{
$comments = $cont->plaintext;
}
}
return $data;
}
}

Related

PHP error code: Notice: Trying to get property ... of non-object in C:\xampp\htdocs\testing\index3.php on line 95

I tried to work on the following script;
<?php
if ($result = $mysqli->query($query)) {
while ($row = $result->fetch_assoc()) {
$id = $row["id"];
$fullname = $row["fullname"];
$biography = $row["biography"];
$email = $row["email"];
$facebook = $row["facebook"];
$twitter = $row["twitter"];
$gplus = $row["gplus"];
$linkedin = $row["linkedin"];
echo '<div id="tabs-'.$row['id'].'" aria-labelledby="ui-id-'.$row['id'].'" role="tabpanel" class="ui-tabs-panel ui-corner-bottom ui-widget-content" aria-hidden="true" style="display: none;"><p>'.$row['biography'].'</p>
<div class="icon-bar">
<p>';
if ($view->$linkedin=='') {
# code...
$view = '';
}else{
$view = '<i class="fa fa-linkedin"></i>';
}
echo
'
</p>
</div>
</div>';
}
}
?>
but got the following error:
Notice: Trying to get property 'https://www.linkedin.com/in/data-analyst-project-management-cloud-expert-bigdata/' of non-object in C:\xampp\htdocs\testing\index3.php on line 95...
Can someone please help me out.
I don't see any view object that you have defined.
If you have defined view object then also you code must be
if($view->linkedin == ''){
//code
}
Or if you have not defined view object the code code may be
if($linkedin == ''){
//code
}
I have been able to resolve the issue using
if ($linkedin=='') {
# code...
$view = '';
}else{
echo '<i class="fa fa-linkedin"></i>';
}
Thanks to #catcon,#Suresh Chand

Problems to iterate objects in array

I have this method below which is responsible for bringing me an array of objects (blog).
public function getListaBlogsById($id) {
$result = array();
try {
$statement = $this->getDb()->prepare('SELECT * FROM Blog WHERE categoria_id = :id');
$statement->bindParam(':id', $id);
$statement->execute();
$result = $statement->fetchAll();
} catch (Exception $ex) {
$ex->getTrace();
}
return $result;
}
And I know that the array is not null. What I want to do is to iterate the objects inside the array in this way:
<?php foreach ($blog_category as $item): ?>
<h2>
<?php echo $item->getTitle(); ?>
</h2>
<p class="lead">
by <?php echo $item->getAuthor(); ?>
</p>
<p><i class="fa fa-clock-o"></i> Postado em
<?php $date = strtotime($item->getDate());
$br_format = date("d/m/Y g:i A", $date);
echo $br_format;
?></p>
<hr>
<a href="<?php echo Utils::createLink('detail-post', array('id' => $item->getId())); ?>">
<img class="img-responsive img-hover" src="../web/img/1850_james_ancestry.JPG" alt=""/>
</a>
<hr>
<p><?php echo $item->getPre(); ?></p>
<a class="btn btn-primary" href="<?php echo Utils::createLink('detail-post', array('id' => $item->getId())); ?>">Leia mais <i class="fa fa-angle-right"></i></a>
<hr>
<?php endforeach; ?>
But the page renders nothing.
Any light will be appreciated.
The object that is used will have been created from strClass() and therefore does not have any get methods associated with it.
So change your script like so in order to access the properties of these objects directly rather than expecting them to have an associated ->getxxx() method.
<a href="<?php echo Utils::createLink('detail-post', array('id' => $item->id)); ?>">
<?php echo $item->title; ?>
</a>
The actual names of the properties will depend on the column names ( and column name case) you have on the table you queried.
You may also need to change this line in your getListaBlogsById($id) funtion to ensure that the data is returned as an object and not an array
From
$result = $statement->fetchAll();
To
$result = $statement->fetchAll(PDO::FETCH_CLASS);
Thanks #RiggsFolly for your help. I solve my problem making some modification as fallows:
public function getListaBlogsById($id) {
try {
$result = array();
$blog = new Blog();
$statement = $this->getDb()->prepare('SELECT * FROM Blog WHERE categoria_id = :id');
$statement->bindParam(':id', $id);
if ($statement->execute()) {
while ($row = $statement->fetch()) {
BlogMapper::map($blog, $row);
$result[$blog->getId()] = $blog;
}
}
} catch (Exception $ex) {
$ex->getTrace();
}
return $result;
}
and
public static function map(Blog $blog, array $properties) {
if (array_key_exists('id', $properties)) {
$blog->setId($properties['id']);
}
if (array_key_exists('blog_author', $properties)) {
$blog->setAuthor($properties['blog_author']);
}
if (array_key_exists('blog_article_title', $properties)) {
$blog->setTitle($properties['blog_article_title']);
}
if (array_key_exists('blog_date_creation', $properties)) {
$blog->setDate($properties['blog_date_creation']);
}
if (array_key_exists('blog_article_pre', $properties)) {
$blog->setPre($properties['blog_article_pre']);
}
if (array_key_exists('blog_article', $properties)) {
$blog->setArticle($properties['blog_article']);
}
if (array_key_exists('categoria_id', $properties)) {
$blog->setCategoria_id($properties['categoria_id']);
}
}

How do I retrieve youtube videos from a channel without timing out?

I have this program that retrieves videos from a channel and shuffles them, as you can see, the program gets the channel's name from the variable $playlistId
<?php
session_start();
class PlayList {
public function __construct($id) {
$this->id = $id;
$this->videos = [];
$this->currentVideo = 0;
$this->addVideos('https://gdata.youtube.com/feeds/api/users/' . $this->id . '/uploads?v=2&alt=json');
shuffle($this->videos);
}
public function addVideos($url) {
$cont = json_decode(file_get_contents($url));
foreach ($cont->feed->entry as $entry) {
$video = [];
$video['title'] = $entry->title->{'$t'};
$video['desc'] = $entry->{'media$group'}->{'media$description'}->{'$t'};
$video['id'] = $entry->{'media$group'}->{'yt$videoid'}->{'$t'};
$this->videos[] = $video;
}
foreach ($cont->feed->link as $link) {
if ($link->rel === 'next') {
$this->addVideos($link->href);
break;
}
}
}
public function getId() {
return $this->id;
}
public function nextVideo() {
if ($this->currentVideo < count($this->videos) - 1) {
$this->currentVideo += 1;
} else {
$this->currentVideo = 0;
}
}
public function getVideoTitle() {
return $this->videos[$this->currentVideo]['title'];
}
public function getVideoDesc() {
return $this->videos[$this->currentVideo]['desc'];
}
public function getVideoSrc() {
return "http://www.youtube.com/embed/" . $this->videos[$this->currentVideo]['id'];
}
public function printList() {
foreach ($this->videos as $video) {
echo $video['title'] . '<br>';
}
}
}
?>
<?php
$playlistId = "NAKCollection";
if (!isset($_SESSION['playlist']) || $_SESSION['playlist']->getId() != $playlistId) {
$_SESSION['playlist'] = new PlayList($playlistId);
} else {
$_SESSION['playlist']->nextVideo();
}
?>
<html>
<head>
<title>Video Shuffle</title>
</head>
<body>
<div style="float: right;">
<?php
$_SESSION['playlist']->printList();
?>
</div>
<div>
<?php echo $_SESSION['playlist']->getVideoTitle(); ?>
</div>
<div>
<iframe type="text/html" src="<?php echo $_SESSION['playlist']->getVideoSrc(); ?>" allowfullscreen></iframe>
</div>
</body>
</html>
If the channel has like 300 videos the page times out, how can I retrieve 50 videos at a time like a batch and then another 50 when the first group is done?
I know I can alter php.ini but I don't want to do that now
This is using the deprecated GData API, if you use the new Data API v3, while retrieving channel's uploaded videos, you can set maxresults and get your results with paging, so you can iterate through pages.

save ajax guestbook to file

I have tried with fuction fopen, fwrite but I still can't make the it possible
I want to save my ajax guest book into txt file, please help me.
This is the index.php
<?php
error_reporting(E_ALL^E_NOTICE);
include "comment.class.php";
$comments = array();
foreach($comments as $c){
echo $c->markup();
}
?>
and it is the comment.class.php
<?php
class Comment
{
private $data = array();
public function __construct($row)
{
/*
/ konstruktor
*/
$this->data = $row;
}
public function markup()
{
/*
/ method untuk comment
*/
//alias untuk &$this->data
$d = &$this->data;
$link_open = '';
$link_close = '';
if($d['url']){
$link_open = '<a href="'.$d['url'].'">';
$link_close = '</a>';
}
$d['dt'] = strtotime($d['dt']);
$url = 'http://'.dirname($_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]).'/img/default_avatar.gif';
return '
<div class="comment">
<div class="avatar">
'.$link_open.'
'.$link_close.'
</div>
<div class="name">'.$link_open.$d['name'].$link_close.'</div>
<div class="date" title="Added at '.date('H:i \o\n d M Y',$d['dt']).'">'.date('d M Y',$d['dt']).'</div>
<p>'.$d['body'].'</p>
</div>
';
}
I want to save the comment body into chat.txt
The following snippet will append the comments into the file instead of echoing them. See file_put_contents manual for details.
foreach($comments as $c){
file_put_contents( 'chat.txt', $c->markup(), FILE_APPEND );
}

Html/Markup format using Picasa PHP FOREACH

Hi guys im trying to format an html output based on this picasa script using foreach, this way:
<? foreach($albums as $photo) {?>
<span><img src="<? echo $photo[1]; ?>" border=0></a><p><?=$photo[0]; ?></p></span>
<? } ?>
The output is:
<span><img src="foto1.jpg" border=0></a><p>This is pict 1 Album 1</p></span>
<span><img src="foto2.jpg" border=0></a><p>This is pict 2 Album 1</p></span>
<span><img src="foto3.jpg" border=0></a><p>This is pict 3 Album 1</p></span>
<span><img src="foto4.jpg" border=0></a><p>This is pict 4 Album 2</p></span>
But i need this:
<div>
<h1>Album 1</h1>
<span><img src="foto1.jpg" border=0></a><p>This is pict 1 Album 1</p></span>
<span><img src="foto2.jpg" border=0></a><p>This is pict 2 Album 1</p></span>
<span><img src="foto3.jpg" border=0></a><p>This is pict 3 Album 1</p></span>
</div>
<div>
<h1>Album 2</h1>
<span><img src="foto4.jpg" border=0></a><p>This is pict 4 Album 2</p></span>
</div>
The idea is bring all the album in my picasa account with their pictures inside, example:
album 1 has:
foto1.jpg
foto2.jpg
foto3.jpg
album 2 has:
foto4.jpg
So on ... That's it i hope someone could help me and understand better my really bad english :)
FULL SOURCE:
<?php
$userid = "cramosb"; // Your Google user name
$target = "PicasaBox.php/?album="; //URL to pass the name of the album to for the links
$imgmax = "512";
/*------------------------------------------------------------------------------
| USER CONFIGURATION END
------------------------------------------------------------------------------*/
// *** Only modify past this point if you know what you're doing ***
$insideentry = false;
$tag = "";
$title = "";
$url = "";
// function to parse the start of an XML element
function startElement($parser, $name, $attrs) {
global $insideentry, $tag, $title, $url;
if ($insideentry) {
$tag = $name;
if ($name == "MEDIA:CONTENT"){
$url = $attrs["URL"];
}
} elseif ($name == "ENTRY") {
$insideentry = true;
}
}
// function to parse the end of an XML element
function endElement($parser, $name) {
global $insideentry, $tag, $title, $url, $albums;
if ($name == "ENTRY") {
$albums[] = array($title, $url);
//echo $title . ' ' . $url;
$title = "";
$url = "";
$insideentry = false;
}
}
// function to parse the contents of an XML element
function characterData($parser, $data) {
global $insideentry, $tag, $title, $url;
if ($insideentry) {
if ($tag == "TITLE") {
$title .= $data;
}
}
}
// Lets get started...
// Create an XML parser, using the functions above
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
// The URL of the album feed I CHANGE THIS: $feed = "http://picasaweb.google.com/data/feed/api/user/" . $userid . "?kind=album"; TO:
$feed = "http://picasaweb.google.com/data/feed/api/user/" . $userid . "?kind=photo";
// Open the feed
$fp = fopen($feed,"r")
or die("Error reading RSS data.");
// Parse the feed
while ($data = fread($fp, 4096))
xml_parse($xml_parser, $data, feof($fp))
or die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
// Close the feed
fclose($fp);
xml_parser_free($xml_parser);
foreach($albums as $album)
{
$htmlout .= '<span><img src="' . $album[1] . '" border=0><p>' . $album[0] . '</p></span>';
}
print $htmlout;
exit;
?>
If you wish to split the output into 'albums' you need to know how to split the array of photos based on which album they should belong to. How are you populating $photo? Is each 'album' going to have only 3 photos in?
here, your homework done for you
<div>
<h1>Album 1</h1>
<? foreach($albums as $photo) {?>
<span><img src="<? echo $photo[1]; ?>" border=0></a><p><?=$photo[0]; ?></p></span>
<? } exit;?>
</div>
<div>
<h1>Album 2</h1>
<span><img src="foto4.jpg" border=0></a><p>This is pict 4 Album 2</p></span>
</div>
note the other answer as well. splitting out which "foto" goes into which album requires more information, this is just an example with html markup so you can understand how the php is fitting in the mix

Categories