I am using php DomDocument to scrape multiple tables but i don't understand how to i output multiple tables data as array, like below example.
Example:
[0] =>
[Network] =>
[Technology]=>[GSM / HSPA / LTE]
[...]=>[...],
[...]=>[...]
[1] =>
[...] =>
[...]=>[...],
[...]=>[...],
[...]=>[...]
My code is below:
$doc = new DomDocument();
$doc->preserveWhiteSpace = false;
#$doc->loadHTML($responseBody);
$xpath = new DOMXPath($doc);
$th = $xpath->query('//table//th');
$tdFirst = $xpath->query('//table//td[contains(#class, "ttl")]');
$tdSecond = $xpath->query('//table//td[contains(#class, "nfo")]');
i get output from below code but i don't want this type output. I need to output like my example. I want to display outputted data on my own table design, so i need it.
foreach($th as $rows) {
echo $rows->nodeValue.'<br>';
}
foreach($tdFirst as $rows) {
echo $rows->nodeValue.'<br>';
}
foreach($tdSecond as $rows) {
echo $rows->nodeValue.'<br>';
}
Sorry for not good english. Thanks
I want to scrape data from multiple table like below table (i just copy and pasted first table to many times for understand you, my targeted scraping site tables are look same ):
<table>
<tbody>
<tr>
<th scope="col" colspan="2">Network</th>
</tr>
<tr>
<td class="ttl"><a>Technology</a></td>
<td class="nfo" >GSM / HSPA / LTE</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th scope="col" colspan="2">Network</th>
</tr>
<tr>
<td class="ttl"><a>Technology</a></td>
<td class="nfo" >GSM / HSPA / LTE</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th scope="col" colspan="2">Network</th>
</tr>
<tr>
<td class="ttl"><a>Technology</a></td>
<td class="nfo" >GSM / HSPA / LTE</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th scope="col" colspan="2">Network</th>
</tr>
<tr>
<td class="ttl"><a>Technology</a></td>
<td class="nfo" >GSM / HSPA / LTE</td>
</tr>
</tbody>
</table>
Related
This question already has an answer here:
How can I get two items in a foreach loop in PHP? [duplicate]
(1 answer)
Closed 2 years ago.
I have a table with looping tr tags I am looking to break after every second tr tag.
like
My table looks like this after the for loop.
<table class="table">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>10</td>
<td>11</td>
<td>12</td>
after modulo logic, I want to show'em like this
<table class="table">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</tbody>
</table>
<table class="table">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>10</td>
<td>11</td>
<td>12</td>
</tr>
</tbody>
</table>
And here is my PHP script so far.
I have tried all sort of arrangement b
ut unable to achieve those layout
<?php $num = 1; ?>
<table class="Table">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<?php
for ( $x = 1; $x <= 12; $x++ ) {
if($num%2 == 0) {
?>
<tr>
<td>Cell</td>
<td>Cell</td>
<td>Cell</td>
</tr>
<?php
}
?>
<?php
if($num %2 == 1) {
?>
<table class="Table">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<?php
}
$num++;
}
?>
</tbody>
</table>
I know I am doing a silly mistake but can't figure it out.
I appreciate your help.
Create a function that returns you a table. For every dataset of size 6, call the function and get your table. You can use array_chunk to chunk the datasets into smaller chunks and use heredoc syntax for better readability.
getTable() function:
<?php
function getTable($data){
$table = <<<EOD
<table class="table">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
EOD;
$rows = "";
foreach(array_chunk($data,3) as $values){
$rows .= "<tr>";
foreach($values as $value){
$rows .= "<td>" . $value . "</td>";
}
$rows .= "/<tr>";
}
$table .= $rows;
$table .= <<<EOD
</tbody>
</table>
EOD;
return $table;
}
Driver code:
<?php
$arr = [1,2,3,4,5,6,7,8,9,10,11,12];
foreach(array_chunk($arr,6) as $set_for_table){
echo getTable($set_for_table);
}
for dynamic tables you can iterate your entire table and set the two tr values.
using your example:
<?php $total = 100; ?>
<?php for ($i=0; $i < $total; $i+=6):?>
<table class="table">
<thead>
<tr>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td><?=$i+1?></td>
<td><?=$i+2?></td>
<td><?=$i+3?></td>
</tr>
<tr>
<td><?=$i+4?></td>
<td><?=$i+5?></td>
<td><?=$i+6?></td>
</tr>
</tbody>
</table>
<?php endfor; ?>
will generate $total/6 tables each with two <tr>
I have a question how to underline in the table according the column data. Below is example coding to explain what I am facing the problem:
I want to detect if column underline is 1 the first name data will draw the underline, if 0 the first name data no show the underline. Below the sample is hardcode, if real situation, I have too many row to show the data, I cannot 1 by 1 to add text-decoration: underline; in the td. So that, hope someone can guide me how to solve this problem. I am using the php code to make the variable to define the underline.
<!--Below the php code I just write the logic, because I don't know how to write to detect the column underline value-->
<?php
if ( <th>Underline</th> == 1) {
$add_underline = "text-decoration: underline;";
}
if ( <th>Underline</th> == 0) {
$add_underline = "text-decoration: underline;";
}
?>
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Underline</th>
</tr>
<tr>
<td style="<?php echo $add_underline;?> ">Jill</td>
<td>Smith</td>
<td>1</td>
</tr>
<tr>
<td style="<?php echo $add_underline;?>">Eve</td>
<td>Jackson</td>
<td>0</td>
</tr>
<tr>
<td style="<?php echo $add_underline;?>">John</td>
<td>Doe</td>
<td>1</td>
</tr>
</table>
My output like below the picture:
My expected result like below the picture, Jill and John can underline:
Why not use javascript to achieve this? No matter what the server sends it will evaluate the condition if 1 is set and then underline accordingly... You would have to use classes to get the appropriate table data tags holding the values, I added class='name' to the names <td> tag and class='underline' tot he underline <td> tag.
// get the values of the elements with a class of 'name'
let names = document.getElementsByClassName('name');
// get the values of the elements with a class of 'underline'
let underline = document.getElementsByClassName('underline');
// loop over elements using for and use the keys to get and set values
// `i` will iterate until it reaches the length of the list of elements with class of underline
for(let i = 0; i < underline.length; i++){
// use the key to get the text content and check if 1 is set use Number to change string to number for strict evaluation
if(Number(underline[i].textContent) === 1){
// set values set to 1 to underline in css style
names[i].style.textDecoration = "underline";
}
}
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Underline</th>
</tr>
<tr>
<td class="name">Jill</td>
<td>Smith</td>
<td class='underline'>1</td>
</tr>
<tr>
<td class="name">Eve</td>
<td>Jackson</td>
<td class='underline'>0</td>
</tr>
<tr>
<td class="name">John</td>
<td>Doe</td>
<td class='underline'>1</td>
</tr>
</table>
Or using the td child values...
let tr = document.querySelectorAll("tr");
last = null;
for(let i = 1; i < tr.length; i++){
if(Number(tr[i].lastElementChild.innerHTML) === 1){
tr[i].firstElementChild.style.textDecoration = "underline";
}
}
<table style="width:100%">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Underline</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>1</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>0</td>
</tr>
<tr>
<td>John</td>
<td>Doe</td>
<td>1</td>
</tr>
</table>
I'm having some issues getting all the data I need from two specific html tables. Tables at the bottom of this post.
The code above states html table id "table1". I also need to grab values from a table called "table2" in the exact same format. I have tried this code and can extract the td values but not the few values that are within the span specifiers within the td. I've tried multiple ways to do this but I'm just not getting it. My code looks something like:
$dom = file_get_html("internets.html);
//not sure how to specify the table exactly!? because this code didn't work.
//$tds = $dom->find('table[id=table1]',0)->find('tr');
foreach($dom->find('tr') as $key => $tr)
{
$td = $tr->find('td');
echo $td[0]->innertext . "</br>";
}
Any assistance much appreciated. I have done some searching here and also used the simple php dom manual.
Here is the format of a table:
<table id="table1">
<tbody>
<tr>
<th width="48%" scope="row">
Prev Close:
</th>
<td class="yfnc_tabledata1">
0.02
</td>
</tr>
<tr>
<th width="48%" scope="row">
Open:
</th>
<td class="yfnc_tabledata1">
0.02
</td>
</tr>
<tr>
<th width="48%" scope="row">
Bid:
</th>
<td class="yfnc_tabledata1">
<span id="yfs_b00_pgo.ax">
0.0180
</span>
</td>
</tr>
<tr>
<th width="48%" scope="row"></th>
<td class="yfnc_tabledata1"></td>
</tr>
<tr>
<th width="48%" scope="row">
1y Target Est:
</th>
<td class="yfnc_tabledata1">
N/A
</td>
</tr>
<tr>
<th width="48%" scope="row">
Beta:
</th>
<td class="yfnc_tabledata1">
N/A
</td>
</tr>
<tr>
<th width="54%" scope="row">
Next Earnings Date:
</th>
<td class="yfnc_tabledata1">
N/A
</td>
</tr>
</tbody>
</table>
<?php
$html=<<<XHTML
<table id="table1">
<tbody>
<tr>
<th width="48%" scope="row">
Prev Close:
</th>
<td class="yfnc_tabledata1">
0.02
</td>
</tr>
<tr>
<th width="48%" scope="row">
Open:
</th>
<td class="yfnc_tabledata1">
0.02
</td>
</tr>
<tr>
<th width="48%" scope="row">
Bid:
</th>
<td class="yfnc_tabledata1">
<span id="yfs_b00_pgo.ax">
0.0180
</span>
</td>
</tr>
<tr>
<th width="48%" scope="row"></th>
<td class="yfnc_tabledata1"></td>
</tr>
<tr>
<th width="48%" scope="row">
1y Target Est:
</th>
<td class="yfnc_tabledata1">
N/A
</td>
</tr>
<tr>
<th width="48%" scope="row">
Beta:
</th>
<td class="yfnc_tabledata1">
N/A
</td>
</tr>
<tr>
<th width="54%" scope="row">
Next Earnings Date:
</th>
<td class="yfnc_tabledata1">
N/A
</td>
</tr>
</tbody>
</table>
XHTML;
$dom = new DOMDocument;
$dom->loadHTML($html);
$xp = new DOMXPath($dom);
foreach ($xp->query("/*//table[#id='table1'//*/td") as $i=>$node) {
echo $node->nodeValue;
}
?>
I'm trying to get this output from returned data fetched from mysql:
<table>
<thead>
<tr>
<th></th><th><img src='img1.jpg'></th><th><img src='img2.jpg'></th>
</tr>
</thead>
<tbody>
<tr>
<td colspan='5'>Features</td>
<td>LCD</td><td>Yes</td><td>No</td>
<td>Auto Pilot</td><td>No</td><td>No</td>
<td>Fast Generation</td><td>Yes</td><td>No</td>
<td>Dual Cores</td><td>No</td><td>Yes</td>
</tr>
</tbody>
</table>
But I have trouble getting the following code to achieve that output with one foreach loop. It uses in_array to check whether each value from $featured_tests exists in the returned data.
$featured_tests = array("LCD","Auto Pilot","Fast Generation","Dual Cores");
$table_head ="<table><thead><tr><th></th>";
$table_colspan1 = "</tr></thead><tbody><tr><td colspan='5'>Features</td></tr>";
$table_end ="</tr></tbody></table>";
foreach($rows as $row)
{
$special_features = explode(",",$row->special_features);
$header_image .= "<th><img src='".$row->image_url."'></th>";
foreach($featured_tests as $featured_test)
{
$featured .= "<tr><td>".$featured_test."</td>";
if(in_array($featured_test,$special_features))
{
$featured .= "<td>Yes</td>";
}
else
{
$featured .= "<td>No</td>";
}
}
}
$table_html = $table_head.$header_image.$table_colspan1.$featured.$table_end;
But the result I'm getting is a mess. Each value in $featured_tests is iterating over and over again for each product and thus results in a very long table. Can anyone help me correct my code to get the ideal output?
Here's the result:
<table>
<thead>
<tr>
<th></th><th><img src='img1.jpg'></th><th><img src='img2.jpg'></th>
</tr>
</thead>
<tbody>
<tr>
<td colspan='5'>Features</td>
</tr>
<tr>
<td>LCD</td><td>Yes</td>
</tr>
<tr>
<td>Auto Pilot</td>No<td></td>
</tr>
<tr>
<td>Fast Generation</td><td>Yes</td>
</tr>
<tr>
<td>Dual Cores</td>No<td>
</tr>
<tr>
<td>LCD</td><td>No</td>
</tr>
<tr>
<td>Auto Pilot</td>No<td></td>
</tr>
<tr>
<td>Fast Generation</td><td>No</td>
</tr>
<tr>
<td>Dual Cores</td>Yes<td>
</tr>
</tbody>
</table>
you are creating new rows <tr> inside on most deep foreach...
take this example to make what you want:
<table>
<thead>
<th>Col 1</th><th>Col 2</th>
</thead>
<tbody>
<?php foreach($large_array as $less_array): ?>
<tr>
<?php foreach($less_array as $row): ?>
<!-- <td> contents etc</td>-->
<?php endforeach?>
</tr>
<?php endforeach;?>
</tbody>
</table>
i'm learning Regex but can't figure it out.... i want to get the entire HTML from a DIV, how to procced?
already tried this;
/\< td class=\"desc1\"\>(.+)/i
it returns;
Array
(
[0] => < td class="desc1">
[1] =>
)
the code that i'm matching is this;
<table id="profile" cellpadding="1" cellspacing="1">
<thead>
<tr>
<th colspan="2">Jogador TheInFEcT </th>
</tr>
<tr>
<td>Detalhes</td>
<td>Descrição:</td>
</tr>
</thead><tbody>
<tr>
<td class="empty"></td><td class="empty"></td>
</tr>
<tr>
<td class="details">
<table cellpadding="0" cellspacing="0">
<tbody><tr>
<th>Classificação</th>
<td>11056</td>
</tr>
<tr>
<th>Tribo:</th>
<td>Teutões</td>
</tr>
<tr>
<th>Aliança:</th>
<td>-</td>
</tr>
<tr>
<th>Aldeias:</th>
<td>1</td>
</tr>
<tr>
<th>População:</th>
<td>2</td>
</tr><tr>
<td colspan="2" class="empty"></td>
</tr>
<tr>
<td colspan="2"> » Alterar perfil</td>
</tr>
</tbody></table>
</td>
<td class="desc1">
<div>STATUS: OFNAaaaAA</div>
</td>
</tr>
</tbody>
</table>
i need to get the entire code inside the < td class="desc1">, like that;
<div >STATUS: OFNAaaaAA< /div>
</td>
</tr>
</tbody>
</table>
Could someone help me out?
Thanks in advance.
I usually use
$dom = DOMDocument::load($htmldata);
for converting HTML code to XML DOM. And then you can use
$node = $dom->getElementsById($id);
/* or */
$nodes = $dom->getElementsByTagName($tag);
to get your HTML/XML node.
Now, use
$node->textContent
to get data inside node.
try this, it does not cover all possible cases but it should work:
/<td\s+class=['"]\s*desc1\s*['"]\s*>((.|\n)*)<\/td>/i
tested with: http://www.pagecolumn.com/tool/pregtest.htm
edit: improved solution suggested by Alan Moore
/<td\s+class=['"]\s*desc1\s*['"]\s*>(.*?)<\/td>/s