i am trying to scrape table which is in div inside div and inside span, i am getting data but as whole content and not formatted as table, all i want to get all data in table format like rows and columns, how to get this output in table format? any help will be appreciated.. Thanks in advance.
edit: i have provided html table code which is commented because its not working
<html>
<div class="container">
<div class="table-responsive">
<table class="table table-striped table-condensed">
<thead>
<tr bgcolor='#ddbbff'>
<th>Stations</th>
<th>Day/Date</th>
<th>Arrive</th>
<th>Depart</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<?php
//error_reporting(E_ALL);
//ini_set('display_errors', '1');
$url = "https://www.railmitra.com/train-running-status/12129?day=yesterday";
$class_to_scrape="well well-sm";
$html = file_get_contents($url);
$document = new DOMDocument();
$document->loadHTML($html);
$selector = new DOMXPath($document);
$anchors = $selector->query("/html/body//div[#class='". $class_to_scrape ."']");
echo "ok, no php syntax errors. <br>Lets see what we scraped.<br>";
foreach ($anchors as $node) {
$full_content = innerHTML($node);
echo "<br>".$full_content."<br>" ;
//echo "<tr>";
//echo "<td>" . $stations[] = $cells->item(0)->textContent . "</td>";
//echo "<td>" . $dayDate[] = $cells->item(1)->textContent . "</td>";
//echo "<td>" . $arr[] = $cells->item(2)->textContent . "</td>";
//echo "<td>" . $dep[] = $cells->item(3)->textContent . "</td>";
//echo "<td>" . $status[] = $cells->item(4)->textContent . "</td>";
}
/* this function preserves the inner content of the scraped element.
** http://stackoverflow.com/questions/5349310/how-to-scrape-web-page-data-
without-losing-tags
** So be sure to go and give that post an uptick too:)
**/
function innerHTML(DOMNode $node)
{
$doc = new DOMDocument();
foreach ($node->childNodes as $child) {
$doc->appendChild($doc->importNode($child, true));
}
return $doc->saveHTML();
}
?>
</tbody>
</table>
</div>
</div>
</html>
edit: added html source
<div class="well well-sm">
<div class=row">
<div class="col-7 col-md-4">
<span class="ind-crossed">
<i class="fa fa-check-circle-o aria-hidden="true">
::before
</i>
</span>
" Pune Junction"
</div>
<div class="col-5 col-md-3">
<span> day1 </span>
<span> 09-sep </span>
</div>
<div class="col-2 col-md-1">
<span> 00:00 </span>
<br>
</div>
<div class="col-2 col-md-1">
<span> 18:25 </span>
<br>
</div>
<div class="col-8 col-md-3 text-right">
<span class="tl-msg text-success"> Right Time </span>
</div>
</div>
</div>
<div class="well well-sm">...</div>
Related
My html including a search button, which posts a tag to an API which returns the info that I flood my table with: called aktie.php. I'm sure that I should use some ajax, java, jQuery or w.e. But I'm lost in how to do this. hope you guys have a solution?
<?php
include ('./stock_table.php');
?>
<form class="form-inline my-2 my-lg-0" method="post">
<input class="form-control mr-sm-2" type="text" placeholder="Søg"
action="./baseconfig.php" name="post_tag">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit"
name="post_search">Søg</button>
</form>
</div>
</nav>
<div class="d-flex align-items-start mt-5">
<div class="container-xxl mt-2 d-flex flex-column bd-highlight mb-5" style="overflow-x:auto;">
<?php
echo build_table($data);
?>
</div>
My baseconfig.php file includes a variable that updates when a tag is entered in the search button
$tag = "NVO";
if (isset($_POST['post_search'])) {
$tag = $_POST['post_tag'];
}
I build my table in a php file: stock_table.php
<?php
include('baseconfig.php');
function build_table($data,
$subheadlines4){
// start table
$html = '<div class="container">';
$html .= '<table class="table table-responsive" style="overflow-x:auto;">';
$html .= '<thead class="thead-dark">';
$html .= '<tr>';
$html .= '<th colspan="10" class="text-center"">';
foreach($data[1] as $key=>$value) {
$html .= htmlspecialchars($value) . " ";
}
// finish table and return it
$html .= '</table>';
$html .= '</div>';
return $html;
};
?>
I have a page that runs off a local webserver that is uses SQLite as its database. As its used local I am not worried about listing all results on one page as they load super fast. I am having an issue with it though as after 500 results are displayed from SQLite3 the formatting goes all wonky and starts stacking them on top of each other. Everything before that is fine. Its written in php. Info was entered into the database using htmlspecialchars so I dont believe that is the issue. The code that builds each record in the loop is
$list = '';
while($row = $results->fetchArray()) {
$id = $row["id"];
$MovieTitle = $row["MovieTitle"];
$MovieYear = $row["MovieDate"];
$MovieRes = $row["MovieRes"];
$FileName = $row["FileName"];
$Summary = $row["Summary"];
$Genres = $row["Genres"];
$PictureLocation = $row["PictureLocation"];
$Rating = $row["Rating"];
$ReleaseDate = $row["ReleaseDate"];
$list .= '<div class="box">
<div class="movie">
<div class="movie-image"><span class="play"><span class="name">'.$MovieTitle.'</span></span><img src="'.$ThumbnailPic.'" alt=""></div>
<div class="rating">
<p>RATING: '.$Rating.'</p>
<div class="stars">
<div class="'.$StarGraphic.'"></div>
</div>
<span class="comments"></span></div>
</div>';
}
and i just echo them them in the html as such
<html>
<body>
<div id="main">
<br>
<?php echo $list; ?>
</div>
</body>
</html>
Your HTML is wrong, you did not close <div class="box"> and <span class="play"> tags properly.
Correct HTML is:
<div class="box">
<div class="movie">
<div class="movie-image">
<span class="play">
<a href="movielist.php?movie='.$FileName.'">
<span class="name">'.$MovieTitle.'</span>
<img src="'.$ThumbnailPic.'" alt="">
</a>
</span>
</div>
<div class="rating">
<p>
RATING: '.$Rating.'
</p>
<div class="stars">
<div class="'.$StarGraphic.'"></div>
</div>
<span class="comments"></span>
</div>
</div>
</div>
Aso, you can have some tags or quotes in your database records. So you have to use escaping your variables before output http://php.net/manual/en/function.htmlspecialchars.php
Something like this:
$list = '';
while($row = $results->fetchArray()) {
$id = htmlspecialchars($row["id"]);
$MovieTitle = htmlspecialchars($row["MovieTitle"]);
$MovieYear = htmlspecialchars($row["MovieDate"]);
$MovieRes = htmlspecialchars($row["MovieRes"]);
$FileName = htmlspecialchars($row["FileName"]);
$Summary = htmlspecialchars($row["Summary"]);
$Genres = htmlspecialchars($row["Genres"]);
$PictureLocation = htmlspecialchars($row["PictureLocation"]);
$Rating = htmlspecialchars($row["Rating"]);
$ReleaseDate = htmlspecialchars($row["ReleaseDate"]);
$list .= '<div class="box">
<div class="movie">
<div class="movie-image"><span class="play"><span class="name">'.$MovieTitle.'</span></span><img src="'.$ThumbnailPic.'" alt=""></div>
<div class="rating">
<p>RATING: '.$Rating.'</p>
<div class="stars">
<div class="'.$StarGraphic.'"></div>
</div>
<span class="comments"></span></div>
</div>';
}
I want to build a page where I need to show all the members from a database. But when I print them, it shows them on the same line, no matter how much the members are. And I want to limit the number of members per line to 5. How can I do this?
Thank you in advance!
<table id="members-table">
<tr>
<?php
$queryContent = "SELECT * FROM users WHERE member='yes'";
$result = mysqli_query($db_connection, $queryContent);
while($row = mysqli_fetch_assoc($result)) {
echo '<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>' .$row['ShownName']. '</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</td>';
}
?>
First, you should consider not using table elements to align your content. This is an outdated practice and not recommended. Check out this StackOverflow question for some great advice on the subject. In short, using tables for laying out your page contents comes from the earlier days of the web before we had things like flexbox and grid layouts.
To answer your question, though, you should implement a $loop_count variable, and echo "</tr><tr>" each time $loop_count > 0 AND $loop_count % 5 == 0.
You have to write a <tr> tag on each 5 loops, except for the first loop.
Add $num=0. Then, in the loop, check if $num is greater than 1 (not for the first loop), and the modulo % with five is zero.
<table id="members-table"><tr>
<?php
$queryContent = "SELECT * FROM users WHERE member='yes'";
$result = mysqli_query($db_connection, $queryContent);
$num = 0;
while($row = mysqli_fetch_assoc($result)) {
if ($num++ % 5 == 0 && $num > 1) echo '</tr><tr>'; // Change is here
echo '<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>' .$row['ShownName']. '</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</td>';
}
?></tr></table>
The devil is in the detail on this one. Because you are building a table (which must have an equal number of columns in each row) you need to write conditionals to build a complete structure.
First, a set of conditionals to separate the data into rows of 5 cells
Second, a conditional after the loop to ensure that the final table row contains the correct number of cells.
Code: (Demo)
$resultset=[
['ShownName'=>'A'],
['ShownName'=>'B'],
['ShownName'=>'C'],
['ShownName'=>'D'],
['ShownName'=>'E'],
['ShownName'=>'F'],
['ShownName'=>'G']
];
echo "<table>";
$counter=0;
foreach($resultset as $row){ // you while loop
if($counter%5==0){
if($counter){
echo "</tr>";
}
echo "<tr>"; // start new row
}
echo "<td>";
echo "<div class=\"card\">";
echo "<img src=\"img/img_avatar2.png\" alt=\"Avatar\">";
echo "<div class=\"container\">";
echo "<h4><b>{$row['ShownName']}</b></h4>";
echo "<p style=\"font-family:Roboto;\">Architect & Engineer</p>";
echo "</div>";
echo "</div>";
echo "</td>";
++$counter;
}
if($mod=$counter%5){
$colspan=5-$mod;
echo "<td",($colspan>1?" colspan=\"$colspan\"":""),"></td>"; // complete the row with appropriately sized cell
}
echo "</tr>";
echo "</table>";
Output:
<table>
<tr>
<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>A</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</div>
</td>
<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>B</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</div>
</td>
<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>C</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</div>
</td>
<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>D</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</div>
</td>
<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>E</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</div>
</td>
</tr>
<tr>
<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>F</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</div>
</td>
<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>G</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</div>
</td>
<td colspan="3"></td>
</tr>
</table>
Using the mod operator (%) will do the trick. This will work and not produce extra unnecessary TR's or /TR's (with the exception of a single empty row if the data is blank):
<table id="members-table">
<?php
$queryContent = "SELECT * FROM users WHERE member='yes'";
$result = mysqli_query($db_connection, $queryContent);
$i = 0;
while($row = mysqli_fetch_assoc($result)) {
if ($i % 5 == 0) {
echo "<tr>";
}
echo '<td>
<div class="card">
<img src="img/img_avatar2.png" alt="Avatar">
<div class="container">
<h4><b>' .$row['ShownName']. '</b></h4>
<p style="font-family:Roboto;">Architect & Engineer</p>
</div>
</td>';
if ($i % 5 == 4 || $i - 1 == count($cols)) {
echo "</tr>";
}
$i++;
}
?>
i need a data "2.5 (0.5)" and "3.5"
my pattern is '/class="match_total_goal_div">.+</s'
But it is not working.
Please help.
<div class="match_total_goal_div">
2.5 (0.5) </div>
<div class="match_half_goal_div hide" ">
</div>
</td>
<td class="text-center corner_goal_range">
<div>
<span class="newlabel">N.A.</span>
</div>
.
.
.
<div class="match_total_goal_div">
3.5 </div>
.
.
.
First, you need to add brackets around your .+ to capture the desired data. By the way you need a question mark: .+?.
Hope this can help you
$str = '<div class="match_total_goal_div">
2.5 (0.5) </div>
<div class="match_total_goal_div">
3.5 </div>';
$pattern = '/class="match_total_goal_div">(.+?)</s';
preg_match_all($pattern, $str, $matches);
var_dump($matches);
Check this code to accomplish your goal
<?php
$html = '<div class="match_total_goal_div">
2.5 (0.5) </div>
<div class="match_half_goal_div hide">
</div>
<td class="text-center corner_goal_range"></td>
<div>
<span class="newlabel">N.A.</span>
</div>
<div class="match_total_goal_div">
3.5 </div>';
$DOM = new DOMDocument();
$DOM->loadHTML($html);
$finder = new DomXPath($DOM);
$classname = 'match_total_goal_div';
$nodes = $finder->query("//*[contains(#class, '$classname')]");
foreach ($nodes as $node) {
echo $node->nodeValue."\n";
}
?>
Live demo : http://sandbox.onlinephpfunctions.com/code/b3e645ac56b9f7bf57d4519abd6b1be90ed87945
I have tree divs inside a father div called results_all as you can see below:
<div id="results_all">
<div class="result_information">
</div>
<div class="result_information">
</div>
<div class="result_information">
</div>
</div>
all I want to do is involve all divs whose class is called result_information, with the following code <tr><th>.
so that the final results to be:
<tr><th>
<div class="result_information">
</div>
</th></tr>
<tr><th>
<div class="result_information">
</div>
</th></tr>
<tr><th>
<div class="result_information">
</div>
</th></tr>
How I can do this kind of thing using DomDocument with PHP?
This will match the class using DOMXPath, it's then just a case of outputting the matched content with the appropriate tags when you loop over the results.
$html = '<div id="results_all">
<div class="result_information">
test3
</div>
<div class="result_information">
test2
</div>
<div class="result_information">
test
</div>
</div>
';
$classname = 'result_information';
$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$results = $xpath->query("//*[contains(#class, '$classname')]");
for($i = 0; $i < $results->length; $i++ ){
print '<tr><th><div class="result_information">' . $results->item($i)->nodeValue . '</div></tr></th>';
}