I have following HTML
<table class="profile-stats">
<tr>
<td class="stat">
<div class="statnum">8</div>
<div class="statlabel"> Tweets </div>
</td>
<td class="stat">
<a href="/THEDJMHA/following">
<div class="statnum">13</div>
<div class="statlabel"> Following </div>
</a>
</td>
<td class="stat stat-last">
<a href="/THEDJMHA/followers">
<div class="statnum">22</div>
<div class="statlabel"> Followers </div>
</a>
</td>
</tr>
</table>
I want to get value from <td class="stat stat-last"> => <div class="statnum"> = 22.
I have tried the follow regex but does not any found match.
/<div\sclass="statnum">^(.)\?<\/div>/ig
Here's a way to accomplish this using a parser.
<?php
$html = '<table class="profile-stats">
<tr>
<td class="stat">
<div class="statnum">8</div>
<div class="statlabel"> Tweets </div>
</td>
<td class="stat">
<a href="/THEDJMHA/following">
<div class="statnum">13</div>
<div class="statlabel"> Following </div>
</a>
</td>
<td class="stat stat-last">
<a href="/THEDJMHA/followers">
<div class="statnum">22</div>
<div class="statlabel"> Followers </div>
</a>
</td>
</tr>
</table>';
$doc = new DOMDocument(); //make a dom object
$doc->loadHTML($html);
$tds = $doc->getElementsByTagName('td');
foreach ($tds as $cell) { //loop through all Cells
if(strpos($cell->getAttribute('class'), 'stat-last')){
$divs = $cell->getElementsByTagName('div');
foreach($divs as $div) { // loop through all divs of the cell
if($div->getAttribute('class') == 'statnum'){
echo $div->nodeValue;
}
}
}
}
Output:
22
...or using an xpath...
$doc = new DOMDocument(); //make a dom object
$doc->loadHTML($html);
$xpath = new DOMXpath($doc);
$statnums = $xpath->query("//td[#class='stat stat-last']/a/div[#class='statnum']");
foreach($statnums as $statnum) {
echo $statnum->nodeValue;
}
Output:
22
or if you realllly wanted to regex it...
<?php
$html = '<table class="profile-stats">
<tr>
<td class="stat">
<div class="statnum">8</div>
<div class="statlabel"> Tweets </div>
</td>
<td class="stat">
<a href="/THEDJMHA/following">
<div class="statnum">13</div>
<div class="statlabel"> Following </div>
</a>
</td>
<td class="stat stat-last">
<a href="/THEDJMHA/followers">
<div class="statnum">22</div>
<div class="statlabel"> Followers </div>
</a>
</td>
</tr>
</table>';
preg_match('~td class=".*?stat-last">.*?<div class="statnum">(.*?)<~s', $html, $num);
echo $num[1];
Output:
22
Regex demo: https://regex101.com/r/kM6kI2/1
I think it would be better if you use an XML parser for that instead of regex. SimpleXML can do the job for you: http://php.net/manual/en/book.simplexml.php
/<td class="stat stat-last">.*?<div class="statnum">(\d+)/si
Your match is in the first capture group. Notice the use of the s option at the end. Makes '.' match new line characters.
You can edit your pattern like that:
/<div\sclass="statnum">(.*?)<\/div>/ig
Related
I'm trying to create a dynamic content field where each data is in a separate accordion and am having a bit of trouble.
Result is the first accordion only works even i am having different id's for each accordion.
Can anyone help me on this
while ($row = mysqli_fetch_assoc($sql_result))
{
$i=1;
?>
<div class="container-fluid border">
<table width=100%>
<tr>
<td><img src="/images/vehicles/<?php echo strtolower($row['vtype']); ?>.jpg" width="75" heigth="75" alt=""></td>
<td align="center"><b><?php echo $row['vtype']; ?> A/C </b> - <?php echo $row['nos']; ?> Seater<br>
<b>₹ <?php if($duration=='8hrs') { $basefare=$row['8hrs']; } elseif($duration=='10hrs') { $basefare=$row['10hrs']; } else { $basefare=$row['12hrs']; } $base=$basefare+($basefare*5/100); echo number_format($base,2,".",","); ?> </b></td>
<td align="right">Book</td>
</tr>
</table>
</div>
<div id="accordionfare<?php echo $i; ?>">
<div class="card">
<div class="card-header" align="right">
<a class="card-link" data-toggle="collapse" href="#collapsefare<?php echo $i; ?>">Fare Details</a>
</div>
<div id="collapsefare<?php echo $i; ?>" class="collapse" data-parent="#accordionfare<?php echo $i; ?>">
<div class="card-body">
<p align="center"><b>Fare Details: </b>Base Fare: ₹ <?php echo number_format($basefare,2,".",","); ?> | GST # 5%: ₹ <?php echo number_format(round($base*5/100),2,".",","); ?> | Extra Hr Fare: ₹ <?php echo number_format($row['extrahr'],2,".",","); ?>/Hr | Extra Km Fare: ₹ <?php echo number_format($row['extrakm'],2,".",","); ?>/Km</p>
<?php $i++; ?>
</div>
</div>
</div>
</div><br>
<?php
}
?>
I've tested your code replacing your data and it works as expected. Check you PHP error log in case there are errors which might brake the loop in some way.
Here is a sandbox where you can Execute my test code and check the HTML result
P.S. You must have accordions with different ids in order to open each one separately.
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>
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>';
}
I can not figure out how to make one row of my table display on another page. What I want to do make each individual row printable. Here is a screen shot.
Here is the php used to display the table (coupon_index.php):
<?php include template("header");?>
<div id="bdw" class="bdw">
<div id="bd" class="cf">
<div id="coupons">
<div class="dashboard" id="dashboard">
<ul><?php echo current_account('/coupon/index.php'); ?></ul>
</div>
<div id="content" class="coupons-box clear">
<div class="box clear">
<div class="box-top"></div>
<div class="box-content">
<div class="head">
<h2>My <?php echo $INI['system']['couponname']; ?></h2>
<ul class="filter">
<li class="label">Category: </li>
<?php echo current_coupon_sub('index'); ?>
</ul>
</div>
<div class="sect">
<?php if($selector=='index'&&!$coupons){?>
<div class="notice">There is no usable <?php echo $INI['system']['couponname']; ?></div>
<?php }?>
<table id="orders-list" cellspacing="0" cellpadding="0" border="0" class="coupons-table">
<tr><th width="300">Deal Item</th><th width="100" nowrap>Voucher's Number</th><th width="60" nowrap>Voucher's Password</th><th width="100" nowrap>Valid Till</th><th width="40">Email Voucher</th></tr>
<?php if(is_array($coupons)){foreach($coupons AS $index=>$one) { ?>
<tr <?php echo $index%2?'':'class="alt"'; ?>>
<td><a class="deal-title" href="/team.php?id=<?php echo $one['team_id']; ?>" target="_blank"><?php echo $teams[$one['team_id']]['title']; ?></a></td>
<td><?php echo $two['id']; ?></td>
<td><?php echo $two['secret']; ?></td>
<td><?php echo date('Y-m-d', $two['expire_time']); ?></td>
<td>Send</td>
</tr>
<?php }}?>
<tr><td colspan="5"><?php echo $pagestring; ?></td></tr>
</table>
</div>
</div>
<div class="box-bottom"></div>
</div>
</div>
<div id="sidebar">
</div>
</div>
</div> <!-- bd end -->
</div> <!-- bdw end -->
<?php include template("footer");?>
and more (index.php):
<?php
require_once(dirname(dirname(__FILE__)) . '/app.php');
need_login();
$daytime = strtotime(date('Y-m-d'));
$condition = array(
'user_id' => $login_user_id,
'consume' => 'N',
"expire_time >= {$daytime}",
);
$count = Table::Count('coupon', $condition);
list($pagesize, $offset, $pagestring) = pagestring($count, 10);
$coupons = DB::LimitQuery('coupon', array(
'condition' => $condition,
'coupon' => 'ORDER BY create_time DESC',
'size' => $pagesize,
'offset' => $offset,
));
$team_ids = Utility::GetColumn($coupons, 'team_id');
$teams = Table::Fetch('team', $team_ids);
include template('coupon_index');
Here is the html(coupon_index.html):
<!--{include header}-->
<div id="bdw" class="bdw">
<div id="bd" class="cf">
<div id="coupons">
<div class="dashboard" id="dashboard">
<ul>${current_account('/coupon/index.php')}</ul>
</div>
<div id="content" class="coupons-box clear">
<div class="box clear">
<div class="box-top"></div>
<div class="box-content">
<div class="head">
<h2>My {$INI['system']['couponname']}</h2>
<ul class="filter">
<li class="label">Category: </li>
${current_coupon_sub('index')}
</ul>
</div>
<div class="sect">
<!--{if $selector=='index'&&!$coupons}-->
<div class="notice">There is no usable {$INI['system']['couponname']}</div>
<!--{/if}-->
<table id="orders-list" cellspacing="0" cellpadding="0" border="0" class="coupons-table">
<tr><th width="300">Deal Item</th><th width="100" nowrap>Voucher's Number</th><th width="60" nowrap>Voucher's Password</th><th width="100" nowrap>Valid Till</th><th width="40">Print Voucher</th></tr>
<!--{loop $coupons $index $one}-->
<tr ${$index%2?'':'class="alt"'}>
<td><a class="deal-title" href="/team.php?id={$one['team_id']}" target="_blank">{$teams[$one['team_id']]['title']}</a></td>
<td>{$one['id']}</td>
<td>{$one['secret']}</td>
<td>${date('Y-m-d', $one['expire_time'])}</td>
<td></td>
</tr>
<!--{/loop}-->
<tr><td colspan="5">{$pagestring}</td></tr>
</table>
</div>
</div>
<div class="box-bottom"></div>
</div>
</div>
<div id="sidebar">
</div>
</div>
</div> <!-- bd end -->
</div> <!-- bdw end -->
<!--{include footer}-->
The simplest solution to output a row per page when printing is simply to use page-break-before or page-break-after CSS properties. That said, you'll need to supress these on either the first or last tr depending on which route you choose.
e.g.:
<style>
#media print {
table tr {page-break-after:always}
}
</style>
you need to pass the database rowID of the coupon in question, or some variation thereof. I would use some hash of it, maybe the MD5 of it, along with a check on the far side that the session person is the owner of that coupon and the coupon is valid...
so your print link would be:
<td>Send</td>
in coupon_index.php i cant understand what $two refers to.
you probably need to better name and indent that piece of code, find a suitable id for the row you want to display, passing this information to the appropriate controller which will load only the relevant row.