サーバーからWebページをプルするためにcURLを使用しています。それをTidyに渡し、出力をDOMDocumentにスローします。それからトラブルが始まります。
Webページには約3000(yikes)のテーブルタグが含まれており、それらからデータを取得しています。テーブルには2種類あり、1つ以上のタイプBがタイプAの後に続きます。
microtome(true)
呼び出しを使用してスクリプトのプロファイルを作成しました。スクリプトの各段階の前後に電話をかけ、時間を差し引いています。それで、あなたが私のコードを通して私をフォローするなら、私はそれを説明し、プロファイルの結果を共有し、そして問題がどこにあるかを指摘します。多分あなたは私が問題を解決するのを手伝うことさえできます。どうぞ:
まず、2つのファイルを含めます。1つはいくつかの解析を処理し、もう1つは2つの「データ構造」クラスを定義します。
// Imports
include('./course.php');
include('./utils.php');
私の知る限り、インクルードは重要ではないので、cURLのインポートに進みましょう。
// Execute cURL
$response = curl_exec($curl_handle);
タイムアウトしないように、また意味のある応答を取得するために必要なヘッダーデータを投稿するようにcURLを構成しました。次に、データをクリーンアップしてDOMDocument用に準備します。
// Run about 25 str_replace calls here, to clean up
// then run tidy.
$html = $response;
//
// Prepare some config for tidy
//
$config = array(
'indent' => true,
'output-xhtml' => true,
'wrap' => 200);
//
// Tidy up the HTML
//
$tidy = new tidy;
$tidy->parseString($html, $config, 'utf8');
$tidy->cleanRepair();
$html = $tidy;
これまで、コードは約9秒かかりました。これがcronジョブであり、実行頻度が低いことを考えると、私はそれで問題ありません。ただし、コードの次の部分は実際にはバーフです。ここで、HTMLから必要なものを取得し、それをカスタムクラスに追加します。(これもMySQLデータベースに詰め込む予定ですが、これは最初のステップです。)
// Get all of the tables in the page
$tables = $dom->getElementsByTagName('table');
// Create a buffer for the courses
$courses = array();
// Iterate
$numberOfTables = $tables->length;
for ($i=1; $i <$numberOfTables ; $i++) {
$sectionTable = $tables->item($i);
$courseTable = $tables->item($i-1);
// We've found a course table, parse it.
if (elementIsACourseSectionTable($sectionTable)) {
$course = courseFromTable($courseTable);
$course = addSectionsToCourseUsingTable($course, $sectionTable);
$courses[] = $course;
}
}
参考までに、私が呼び出すユーティリティ関数は次のとおりです。
//
// Tell us if a given element is
// a course section table.
//
function elementIsACourseSectionTable(DOMElement $element){
$tableHasClass = $element->hasAttribute('class');
$tableIsCourseTable = $element->getAttribute("class") == "coursetable";
return $tableHasClass && $tableIsCourseTable;
}
//
// Takes a table and parses it into an
// instance of the Course class.
//
function courseFromTable(DOMElement $table){
$secondRow = $table->getElementsByTagName('tr')->item(1);
$cells = $secondRow->getElementsByTagName('td');
$course = new Course;
$course->startDate = valueForElementInList(0, $cells);
$course->endDate = valueForElementInList(1, $cells);
$course->name = valueForElementInList(2, $cells);
$course->description = valueForElementInList(3, $cells);
$course->credits = valueForElementInList(4, $cells);
$course->hours = valueForElementInList(5, $cells);
$course->division = valueForElementInList(6, $cells);
$course->subject = valueForElementInList(7, $cells);
return $course;
}
//
// Takes a table and parses it into an
// instance of the Section class.
//
function sectionFromRow(DOMElement $row){
$cells = $row->getElementsByTagName('td');
//
// Skip any row with a single cell
//
if ($cells->length == 1) {
# code...
return NULL;
}
//
// Skip header rows
//
if (valueForElementInList(0, $cells) == "Section" || valueForElementInList(0, $cells) == "") {
return NULL;
}
$section = new Section;
$section->section = valueForElementInList(0, $cells);
$section->code = valueForElementInList(1, $cells);
$section->openSeats = valueForElementInList(2, $cells);
$section->dayAndTime = valueForElementInList(3, $cells);
$section->instructor = valueForElementInList(4, $cells);
$section->buildingAndRoom = valueForElementInList(5, $cells);
$section->isOnline = valueForElementInList(6, $cells);
return $section;
}
//
// Take a table containing course sections
// and parse it put the results into a
// give course object.
//
function addSectionsToCourseUsingTable(Course $course, DOMElement $table){
$rows = $table->getElementsByTagName('tr');
$numRows = $rows->length;
for ($i=0; $i < $numRows; $i++) {
$section = sectionFromRow($rows->item($i));
// Make sure we have an array to put sections into
if (is_null($course->sections)) {
$course->sections = array();
}
// Skip "meta" rows, since they're not really sections
if (is_null($section)) {
continue;
}
$course->addSection($section);
}
return $course;
}
//
// Returns the text from a cell
// with a
//
function valueForElementInList($index, $list){
$value = $list->item($index)->nodeValue;
$value = trim($value);
return $value;
}
このコードは63秒かかります。PHPスクリプトがWebページからデータをプルするのに1分以上かかります。シーシュ!
メインの作業ループのワークロードを分割するようにアドバイスされましたが、データの均質性を考慮すると、その方法が完全にはわかりません。このコードを改善するための提案は大歓迎です。
コードの実行時間を改善するにはどうすればよいですか?