HACK#60 การค้นหาแบบกำหนดช่วงวันที่ (date-range searching) ด้วย Client-Side Application

วิธีการค้นหาข้อมูลที่ Google เพิ่งได้จัดทำอินเด็กซ์ข้อมูลนั้นเสร็จไป โดยจำกัดเฉพาะส่วนของเมื่อวานนี้เท่านั้น

GooFresh ใน Hack #42 เป็นเว็บฟอร์มแบบง่ายๆที่เขียนขึ้นด้วย CGI Script สำหรับการสร้างคำสั่งค้นหาแบบกำหนดช่วงวันที่ (date-range query) ซึ่งการใช้ Web-Based Interface นั้นค่อนข้างดีเมื่อคุณต้องการผลลัพธ์แค่เพียงหนึ่งหรือสองรายการในแต่ละ ครั้ง แต่คุณจะทำอย่างไรถ้าต้องค้นหาสิ่งที่ต้องการหลายๆครั้งหรือเป็นประจำ คำตอบก็คงเป็นการเซฟลงเครื่องคอมพิวเตอร์ของคุณ เพื่อนำมาวิเคราะห์เปรียบเทียบในภายหลัง
แต่มีวิธีที่ดีกว่าก็คือการใช้ Client-Side Application ที่เขียนด้วย Perl Script ซึ่งคุณสามารถรันจากเครื่องของคุณเองได้ โดยแอพพลิเคชันดังกล่าวจะส่งคำสั่งค้นหาที่คุณระบุ (specified query) ไปยัง Google โดยผ่าน Google Web API โดยขอให้จำกัดผลลัพธ์ของการค้นหาให้มีเพียงผลลัพธ์ที่เพิ่งถูกอินเด็กซ์ เมื่อวันวานเท่านั้น จากนั้นผลลัพธ์ที่ได้จากการค้นหา (search result) ในแต่ละครั้งจะถูกบันทึกเก็บไว้ โดยการนำผลลัพธ์ที่ได้เข้าไปต่อท้ายไฟล์ comma-delimited ที่กำหนดเอาไว้เท่านั้น ซึ่งผลที่ได้ก็สามารถ Import มายัง Excel หรือโปรแกรมด้านฐานข้อมูล (database application) อื่นใดก็ได้


Tip : การแฮ็กในหัวข้อนี้จำเป็นต้องมีโมดูล Time::JulianDay (http://search.cpan.org/author/MUIR/) ของ Perl ติดตั้งร่วมด้วย และสคริปต์จะไม่ทำงานเลย หากไม่ได้ติดตั้งโมดูลดังกล่าว

การค้นหา
ขั้น แรกคุณต้องเตรียมคีย์เวิร์ดที่เป็นคำถามเอาไว้สัก 2-3 คำถาม เพื่อทดลองใช้กับสคริปต์ จากนั้นลองใช้คำเหล่านี้ค้นหาใน Google ตามปกติก่อน เพื่อดูผลลัพธ์ที่ได้ให้แน่ใจว่าเป็นเรื่องที่เกี่ยวกับสิ่งคุณสนใจและต้อง การค้นหาจริงๆ ซึ่งคำถามดังกล่าวนี้อาจจะเป็นอะไรก็ได้ที่คุณต้องการจะติดตามเป็นระยะเวลา ยาวนานพอสมควร หรือคุณอาจใช้วิธีนี้ลองค้นหาข้อความบางอย่างอย่าง เช่น ถ้อยคำหรือวลีในบทความบางบท ซึ่งคุณคิดว่าไม่น่าจะ เหมือนกับข้อความในบทความอื่นๆ ซึ่งวิธีการนี้อาจจะทำให้คุณได้พบกับบทความที่มีการแอบคัดลอก หรือขโมยความคิดกันก็ได้
คุณ อาจจะใช้ซินแท็กซ์ที่คุณต้องการได้ ยกเว้นเพียงอย่างเดียวคือซินแท็กซ์ link: ถ้าหากคุณจำได้ถึงเนื้อหาในบทต้นๆที่บอกไปแล้วว่า link: ไม่สามารถใช้ร่วมกันซินแท็กซ์บางตัวอย่างเช่น daterange: ที่ใช้ใน Hack #60 ได้ แต่ถ้าหากคุณอยากทดลองใช้ร่วมกันดู (เช่น link:www.yahoo.com daterange:2452421-2452521 เป็นต้น) Google จะมองเหมือนกับว่าคำว่า link เป็นคำถาม ดังเช่นเดียวกับคุณต้องการค้นหาด้วยคำ 2 คำคือ link และ www.yahoo.com ซึ่งทำให้ผลลัพธ์ที่ได้ไม่ตรงกับความต้องการของคุณเลย
สำหรับการใช้งานสคริปต์ ให้ใส่คำถามที่เตรียมเอาไว้แล้ว โดยเรียงบรรทัดลงไปเรื่อยๆในลักษณะนี้
“digital archives”
intitle:”state library of”
intitle:directory intitle:resources
“now * * time for all good men * come * * aid * * party”
จากนั้นบันทึกเก็บไว้ในเท็กซ์ไฟล์ ซึ่งที่ที่ดีที่สุดในการเก็บไฟล์นี้ไว้ก็คือ ในไดเรกทอรีเดียวกับสคริปต์ของคุณนั่นเอง
โค้ดตัวอย่าง

#!/usr/local/bin/perl -w
# goonow.pl
# feeds queries specified in a text file to Google, querying
# for recent additions to the Google index. The script appends
# to CSV files, one per query, creating them if they don't exist.
# usage: perl goonow.pl [query_filename]

# My Google API developer's key
my $google_key='insert key here';

# Location of the GoogleSearch WSDL file
my $google_wdsl = "./GoogleSearch.wsdl";

use strict;

use SOAP::Lite;
use Time::JulianDay;

$ARGV[0] or die "usage: perl goonow.pl [query_filename]\n";

my $julian_date = int local_julian_day(time) - 2;

my $google_search = SOAP::Lite-&gtservice("file:$google_wdsl");

open QUERIES, $ARGV[0] or die "Couldn't read $ARGV[0]: $!";

while (my $query = &ltQUERIES&gt) {
chomp $query;
warn "Searching Google for $query\n"

$query .= " daterange:$julian_date-$julian_date";
(my $outfile = $query) =~ s/\W/_/g;
open (OUT, "&gt&gt $outfile.csv")
or die "Couldn't open $outfile.csv: $!\n";

my $results = $google_search -&gt
doGoogleSearch(
$google_key, $query, 0, 10, "false", "", "false",
"", "latin1", "latin1"
);
foreach (@{$results-&gt{'resultElements'}}) {
print OUT '"' . join('","', (
map {
s!\n!!g; # drop spurious newlines
s!&lt.+?&gt!!g; # drop all HTML tags
s!"!""!g; # double escape " marks
$_;
} @$_{'title','URL','snippet'}
) ) . "\"\n";
}
}
สังเกต สคริปต์ดู คุณจะเห็นว่า goonow จะระบุวันเป็นเมื่อวันก่อนนี้ แทนที่จะเป็นเมื่อวานนี้ (ดูบรรทัดที่เป็น my $julian_date = int local_julian_day(time) – 2;) เนื่องจาก Google รีอินเด็กซ์เว็บเพจบางหน้าบ่อยมาก ทำให้เว็บเพจหน้าดังกล่าวแสดงออกมาเต็มไปหมดในรายการผลลัพธ์ ดังนั้นถ้าหากคุณระบุเป็นวันวานจริงๆ (ใช้ -1 แทน -2) ผลลัพธ์ที่ได้จะมีเว็บเพจหน้าที่ถูกรีอินเด็กซ์บ่อยๆเต็มไปหมด (มีหลายเหตุผลที่ทำให้ต้องรีอินเด็กซ์เว็บเพจบางหน้าบ่อยๆหรือแทบทุกวัน ซึ่งจะได้อธิบายใ นโอกาสต่อไป) ดังนั้นถ้าหากคุณต้องการค้นหาข้อมูลของวันวานจริงๆ คุณควรจะบวกถอยหลังกลับไปหนึ่งวันเพื่อให้ได้ผลลัพธ์ที่ถูกต้องมากยิ่งขึ้น

Running the Hack
รันสคริปต์ที่ command line ดังนี้
$ perl goonow.pl query_filename

โดย ที่ query_filename จะเป็นชื่อของเท็กซ์ไฟล์ที่เก็บรายการคำถามเอาไว้ เพื่อส่งให้สคริปต์ทำงาน ซึ่งไฟล์นี้อาจจะอยู่ได้ทั้งที่โลคอลไดเรกทอรี (local directory) หรือที่อื่นก็ได้ แต่ถ้าเป็นที่อื่น อย่าลืมระบุพาธให้ถูกต้องด้วย (เช่น /mydocu~1/hacks/queries.txt เป็นต้น)
สำหรับผลลัพธ์ที่ได้จากค้นหาทั้งหมด จะถูกส่งไปยังไฟล์ CSV โดยไม่แสดงออกทางหน้าจอแต่อย่างใด
ผลลัพธ์
ลองดูตัวอย่างของไฟล์ CSV ที่แสดงผลลัพธ์ที่ได้จากการค้นหา


"State Library of Louisiana","http://www.state.lib.la.us/"," ...
Click
here if you have any questions or comments. Copyright &ltC2&gt&ltA9&gt
1998-2001 State Library of Louisiana Last modified: August 07,
2002. "
"STATE LIBRARY OF NEW SOUTH WALES, SYDNEY
AUSTRALIA","http://www.slnsw.gov.au/", " ... State Library of New
South
Wales Macquarie St, Sydney NSW Australia 2000 Phone: +61 2 9273
1414
Fax: +61 2 9273 1255. Your comments You could win a prize! ... "
"State Library of Victoria","http://www.slv.vic.gov.au/"," ...
clicking
on our logo. State Library of Victoria Logo with link to homepage
State
Library of Victoria. A world class cultural resource ... "
...
Hacking the Hack
สคริปต์ จะนำผลลัพธ์ที่ได้ในแต่ละครั้งไปต่อท้ายไฟล์ให้เองโดยอัตโนมัติ และถ้าหากคุณต้องการรีเซตไฟล์ CSV ที่ใช้เก็บผลลัพธ์ดังกล่าว ก็สามารถทำได้โดยเพียงการลบไฟล์นั้นออกไป แล้วสคริปต์จะสร้างไฟล์ขึ้นมาให้ใหม่อีกครั้งหนึ่ง
หรือ ถ้าหากคุณต้องการให้มีการสร้างไฟล์ CSV ขึ้นใหม่ทุกครั้ง สำหรับเก็บผลลัพธ์ในแต่ละครั้งที่ได้มา ก็เพียงแก้ไขสคริปต์เล็กน้อยดังนี้
...
(my $outfile = $query) =~ s/\W/_/g;
open (OUT, "> $outfile.csv")
or die "Couldn't open $outfile.csv: $!\n";
my $results = $google_search ->
doGoogleSearch(
$google_key, $query, 0, 10, "false", "", "false",
"", "latin1", "latin1"
);
...

สังเกต ว่าจะมีการแก้ไขสคริปต์เพียงเล็กน้อย โดยเพียงเอาเครื่องหมาย > ออก ให้เหลือเพียงตัวเดียว คือเปลี่ยนจาก OUT, “>> $outfile.csv” เป็น OUT, “> $outfile.csv” เท่านั้นเอง

โพสต์ยอดนิยมจากบล็อกนี้

I miss you all กับ I miss all of you ต่างกันอย่างไร

ปัญหาและเฉลยวิชาธรรม นักธรรมชั้นตรี สอบในสนามหลวง วันอังคาร ที่ ๒๙ กันยายน พ.ศ.๒๕๕๒

ปัญหาและเฉลยวิชาอนุพุทธประวัติ นักธรรมชั้นโท สอบในสนามหลวง วันอาทิตย์ ที่ ๒๐ พฤศจิกายน พ.ศ. ๒๕๔๘