SHELL网络爬虫实例剖析--转载
? ? ? ?前天簡單分享了用?shell 寫網(wǎng)絡爬蟲的一些見解,今天特地把代碼發(fā)出來與51博友分享,還是那句話,愛技術、愛開源、愛linux。
? ? ? ?針對腳本的注解和整體構思,我會放到腳本之后為大家詳解。
#!/bin/bash # # This script is used to grab the data on the specified industry websites # Written by sunsky # Mail : 274546888@qq.com # Date : 2014-09-14 3:06:00 #if [ `echo $UID` != 0 ];thenecho 'Please use the root to execute the script!' fi if [ ! -f /dataimg/years ];thenecho 'Please give date file, the file path for/dataimg/years .' fi if [ ! -d $TMP_DIR ];thenmkdir -p $TMP_DIR fi if [ ! -d $URL_MD5_DIR ];thenmkdir -p $URL_MD5_DIR fi if [ ! -d $HTML_DIR ];thenmkdir -p $HTML_DIR fiROOT_DIR="/dataimg" # 指定腳本運行根目錄 TMP_DIR="$ROOT_DIR/tmp" # 生成商品詳細頁url之前的臨時數(shù)據(jù)存放目錄 URL_MD5_DIR="$ROOT_DIR/url_md5" # 記錄商品詳細頁url的MD5值的目錄 HTML_DIR="$ROOT_DIR/html" # 存放下載下來的商品詳細頁目錄 URL_MD5="$URL_MD5_DIR/md5.$year" # 負責記錄商品詳細頁url的md5值 WEB_URL="https://www.redhat.sx/" # 所爬網(wǎng)站的主頁url REPORT="$ROOT_DIR/report" # 負責記錄采集的url綜合信息 CURL="curl -A 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.102 Safari/537.36' --referer http://www.redhat.sx" OPT0="/dataimg/years" # 年份信息 OPT1="$TMP_DIR/${X1_MD5}" # 品牌信息 OPT2="$TMP_DIR/${X1_MD5}_${X2_MD5}" # 車型信息 OPT3="$TMP_DIR/${X1_MD5}_${X2_MD5}_${X3_MD5}" # 裝飾信息 OPT4="$TMP_DIR/${X1_MD5}_${X2_MD5}_${X3_MD5}_${X4_MD5}" # 部位分類信息 OPT5="$TMP_DIR/${X1_MD5}_${X2_MD5}_${X3_MD5}_${X4_MD5}_${URL_LIST_MD5}" # 商品詳情頁url信息FIFO_FILE="/tmp/$$.fifo" mkfifo $FIFO_FILE exec 9<>$FIFO_FILE rm -f $FIFO_FILEnum=10 for ((i=0;i<$num;i++));do echo done >&9while read X1;do {URL1="${WEB_URL}/model/YMMTSelects.cfc?method=getMakes&PassYear=$X1"X1_MD5=`echo $URL1|cksum|cut -d' ' -f1`if ! ls $OPT1 >&/dev/null;then$CURL -s $URL1|awk 'BEGIN{RS="<"}{print $0}'|awk -F'>' '{print $2}'|sed '1,9d'|sed '$d'|grep -v '^$' > $OPT1fiwhile read X2;doX2=`echo $X2|sed 's# #%20#g'`URL2="${URL1}&PassMakeName=$X2"#X2_MD5=`echo $URL|cksum|cut -d' ' -f1`if ! ls $OPT2 >&/dev/null;then$CURL -s $URL2|awk 'BEGIN{RS="<"}{print $0}'|awk -F'>' '{print $2}'|sed '1,6d'|sed '$d'|grep -v '^$' > $OPT2fiwhile read X3;doX3=`echo $X3|sed 's#[[:space:]]#%20#g'`URL3="${URL2}&PassModel=$X3"X3_MD5=`echo $URL3|cksum|cut -d' ' -f1`if ! ls $OPT3 >&/dev/null;then$CURL -s $URL3|sed 's#[[:space:]]##g'|awk 'BEGIN{RS="<|=|>"}{print $0}'|egrep '^[0-9]+$' > $OPT3fiwhile read X4;doX4=`echo $X4|sed 's# #%20#g'`URL4="${URL3}&PassVehicleID=$X4"X4_MD5=`echo $URL4|cksum|cut -d' ' -f1`if ! ls "${OPT4}" >&/dev/null;then$CURL -s $URL4|awk 'BEGIN{RS="<"}{print $0}'|awk -F'[>;]' '{print $2}'|sed -e '1,3d' -e '$d' -e '/^$/d' > $OPT4fiwhile read X5;doX5=`echo $X5|sed 's# #%20#g'`URL_LIST="${WEB_URL}index.cfm?fuseaction=store.sectionSearch&YMMTyears=$X1&YMMTmakenames=$X2&YMMTmodelnames=$X3&YMMTtrimnames=$X4&YMMTsectionnames=$X5"URL_LIST_MD5=`echo "$URL_LIST"|md5sum|awk '{print $1}'`if ! grep -q $URL_LIST_MD5 "$URL_MD5" ;then$CURL -s "$URL_LIST" > "$URL_MD5_DIR/$URL_LIST_MD5"NUM=`grep 'View page' "$URL_MD5_DIR/$URL_LIST_MD5"|wc -l`NUM2=$(($NUM/2))echo > $OPT5grep 'a href="index.cfm?fuseaction=store.PartInfo&PartNumbe' "$URL_MD5_DIR/$URL_LIST_MD5"|cut -d'"' -f2 > $OPT5while [ $NUM2 -ge 2 ];doURL_LIST=`grep "View page $NUM2" "$URL_MD5_DIR/$URL_LIST_MD5"|awk -F'[" ]' '{a[$9]=$9}END{for(i in a)print a[i]}'`$CURL -s "$URL_LIST"|grep 'a href="index.cfm?fuseaction=store.PartInfo&PartNumbe'|cut -d'"' -f2 >> $OPT5NUM2=$(($NUM2-1))doneecho $URL_LIST_MD5 >> "$URL_MD5"fiwhile read X6;doURL_DETAIL="${WEB_URL}${X6}"URL_DETAIL_MD=`echo $URL_DETAIL|md5sum|awk '{print $1}'`if ! grep -q $URL_DETAIL_MD "$URL_MD5" >&/dev/null;then # 該判斷以商品列表詳細頁URL的md5值為基準,負責URL的重復項判定$CURL -s "$URL_DETAIL" > "$HTML_DIR/$URL_DETAIL_MD"LABEL=`grep 'diagram-label' "$HTML_DIR/$URL_DETAIL_MD"|awk -F'[<>]' '{print $5}'` # 商品標簽GIF_URL=`grep -B 10 partInfo "$HTML_DIR/$URL_DETAIL_MD"|grep -o "https.*gif"|awk '{a=$0}END{print a}'` # 產(chǎn)品對應的圖片URLPRODUCT_ID=`grep 'productID' "$HTML_DIR/$URL_DETAIL_MD"|awk -F'[<>]' '{print $3}'` # 產(chǎn)品零件號碼GIFILE=${GIF_URL#*/} # 去除了https:/后的圖片URL信息,as:/a/b.gifGIF_IMG="${ROOT_DIR}${GIFILE}" # 圖片存到本地后的絕對路徑,as:/dataimg/a/b.gifU4=`grep -B 10 '<!-- start opentop -->' "$HTML_DIR/$URL_DETAIL_MD"|grep javascript|awk -F'[<>]' '{print $3}'`! ls $GIF_IMG >& /dev/null && wget -q -m -k -P "$ROOT_DIR" "$GIF_URL"echo $URL_DETAIL_MD >> "$URL_MD5"echo "$(date +%m%d%T)+++$X1+++$X2+++$X3+++$U4+++$X5+++$URL_DETAIL+++$URL_DETAIL_MD+++$LABEL+++$PRODUCT_ID+++$GIF_IMG+++$URL_LIST" >> "$REPORT"fidone < $OPT5 # 傳入商品詳細列表url信息,進行循環(huán)done < $OPT4 # 傳入產(chǎn)品部位分類信息,進行循環(huán)done < $OPT3 # 傳入裝飾信息,進行循環(huán)done < $OPT2 # 傳入車型信息,進行循環(huán)done < $OPT1 # 傳入品牌信息,進行循環(huán)echo >&9 }& done < $OPT0 # 傳入年份信息,進行循環(huán)waitexec 9<&-OK!
? ? ? ?以上就是腳本的全部內容,整體腳本主要包含了組合目標URL和抓取目標URL兩個大方向,圍繞這兩個大方向,主要是使用 curl 來做數(shù)據(jù)抓取,是用sed、awk、grep、cut來做興趣數(shù)據(jù)的抽取。
? ? ? ?由于所要抓取的目標URL必須經(jīng)過幾個選項匹配,最終才能得到想要結果,因此我們在抓取目標URL之前添加了組合目標URL這一操作。整體這2個方向,我通過多層的while循環(huán)嵌套,來實現(xiàn)對參數(shù)的復用和一層一層的輸入挖掘。
? ? ? ?為了優(yōu)化速度以及控制速度,采用了 shell 的多進程和數(shù)據(jù)智能判重的方式。
? ? ? ?采用 shell 的多進程目的是為了增大操作數(shù)來縮短整體完成時間,提高抓取效率。
? ? ? ?shell 多進程主要依托 循環(huán) + { } + & 來實現(xiàn)。如果多進程的進程數(shù)量有指定數(shù)值,那么我們可以使用for和while都而已,如果多進程的進程數(shù)量沒有指定數(shù)值,那么我們最好使用while循環(huán)語句。通過將 { }& 嵌套在循環(huán)中實現(xiàn)將 {}內的命令群組放到后臺去自動執(zhí)行,然后完成本次 { }& 操作,使得循環(huán)可以進入下一次。
? ? ? ?以上并未實現(xiàn)該shell 在后臺開啟進程數(shù)的控制,假設你的需要執(zhí)行一萬次,如果你未控制速度,就可能會導致直接觸發(fā)著一萬次操作,同時放到后臺執(zhí)行,這樣對系統(tǒng)是致命的傷害。另一方面,作為爬蟲,你對目標網(wǎng)站的并發(fā)量也不能太大。出于這兩方面的考慮,我們需要控制 shell 多進程每次放入后臺執(zhí)行的數(shù)量。針對這一行為,我們主要通過文件描述符來實現(xiàn)。通過新建一臨時管道文件,然后為該文件打開一個文件描述符,并為其傳遞指定數(shù)量的空行(本文傳遞了10個空行),這樣做的目的是為了實現(xiàn)對進程并發(fā)量的控制。接著,在下面循環(huán)中, { }&操作的前面使用read -u9(這里9為本文使用的文件描述符)來從9這個文件描述符中獲取一行,如果獲取到就能繼續(xù)往下執(zhí)行,如果獲取不到就在這里等待。
? ? ? ?通過以上的2者結合,就能實現(xiàn)對 shell 多進程的智能管控。
? ? ? ?采用數(shù)據(jù)智能判重的目的在于,在腳本調試中發(fā)現(xiàn)速度的執(zhí)行瓶頸在于curl的速度,即網(wǎng)絡速度,因此一旦腳本異常中斷后,恢復之后,又要重復進行curl操作,這樣就極大增加了腳本執(zhí)行時間。因此通過智能判重,完美實現(xiàn)了curl時間消耗過久的以及數(shù)據(jù)重復采集的問題。以下是數(shù)據(jù)只能判重的邏輯圖:
? ? ? 針對腳本中變量的取值意義,我已經(jīng)在上面的腳本中進行了詳細的注釋,這里不在復述。
? ? ? 其它細枝末節(jié)的一些使用方法和技巧,這里不再一一解釋。對 shell 感興趣的朋友可以和我一起交流,一起進步。
?
本文出自 “Not Only Linux” 博客,請務必保留此出處http://nolinux.blog.51cto.com/4824967/1552472
轉載于:https://www.cnblogs.com/davidwang456/p/4001320.html
總結
以上是生活随笔為你收集整理的SHELL网络爬虫实例剖析--转载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Httpwatch分析响应时间--转
- 下一篇: cache 的设计与实现--转载