網路爬蟲c源碼
❶ 求網路爬蟲源代碼VC++編寫的
爬蟲類的程序最好用C#或C++/CLI完全用C++實現的要做大量Http協議和Html解析的東西,使用 .Net類庫的Http下載和正則表達式可以非常方便地做這些東西。
❷ 求C# 爬蟲 完整源碼
可以參考這個
http://tool.sufeinet.com/CodePreview/CodeView.aspx?action=view&file=1-HttpHelper/HttpHelper.cs
❸ 各位好,有誰做過網路蜘蛛(爬蟲)啊可以提供c語言的源代碼給我不啊能幫我解釋一下更好,謝謝!
網上又好多,可以自己下載啊。http://bbs.chinaunix.net/thread-2163118-1-1.html
❹ 網路爬蟲 spider
「網路蜘蛛」或者說「網路爬蟲」,是一種能訪問網站並跟蹤鏈接的程序,通過它,可快速地畫出一個網站所包含的網頁地圖信息。本文主要講述如何使用java編程來構建一個「蜘蛛」,我們會先以一個可復用的蜘蛛類包裝一個基本的「蜘蛛」,並在示常式序中演示如何創建一個特定的「蜘蛛」來掃描相關網站並找出死鏈接。 Java語言在此非常適合構建一個「蜘蛛」程序,其內建了對HTTP協議的支持,通過它可以傳輸大部分的網頁信息;其還內建了一個HTML解析器,正是這兩個原因使Java語言成為本文構建「蜘蛛」程序的首選。 文章後面例1的示常式序,將會掃描一個網站,並尋找死鏈接。使用這個程序時需先輸入一個URL並單擊「Begin」按鈕,程序開始之後,「Begin」按鈕會變成「Cancel」按鈕。在程序掃描網站期間,會在「Cancel」按鈕之下顯示進度,且在檢查當前網頁時,也會顯示相關正常鏈接與死鏈接的數目,死鏈接將顯示在程序底部的滾動文本框中。單擊「Cancel」按鈕會停止掃描過程,之後可以輸入一個新的URL;如果期間沒有單擊「Cancel」,程序將會一直運行直到查找完所有網頁,此後,「Cancel」按鈕會再次變回「Begin」,表示程序已停止。 下面將演示示常式序是如何與可復用「Spider」類交互的,示常式序包含在例1的CheckLinks類中,這個類實現了ISpiderReportable介面,如例2所示,正是通過這個介面,蜘蛛類才能與示常式序相交互。在這個介面中,定義了三個方法:第一個方法是「spiderFoundURL」,它在每次程序定位一個URL時被調用,如果方法返回true,表示程序應繼續執行下去並找出其中的鏈接;第二個方法是「spiderURLError」,它在每次程序檢測URL導致錯誤時被調用(如「404 頁面未找到」);第三個方法是「spiderFoundEMail」,它在每次發現電子郵件地址時被調用。有了這三個方法,Spider類就能把相關信息反饋給創建它的程序了。 在begin方法被調用後,「蜘蛛」就開始工作了;為允許程序重繪其用戶界面,「蜘蛛」是作為一個單獨的線程啟動的。點擊「Begin」按鈕會開始這個後台線程,當後台線程運行之後,又會調用「CheckLinks」類的run方法,而run方法是由Spider對象實例化時啟動的,如下所示: spider = new Spider(this); spider.clear(); base = new URL(url.getText()); spider.addURL(base); spider.begin(); 首先,一個新的Spider對象被實例化,在此,需要傳遞一個「ISpiderReportable」對象給Spider對象的構造函數,因為「CheckLinks」類實現了「ISpiderReportable」介面,只需簡單地把它作為當前對象(可由關鍵字this表示)傳遞給構造函數即可;其次,在程序中維護了一個其訪問過的URL列表,而「clear」方法的調用則是為了確保程序開始時URL列表為空,程序開始運行之前必須添加一個URL到它的待處理列表中,此時用戶輸入的URL則是添加到列表中的第一個,程序就由掃描這個網頁開始,並找到與這個起始URL相鏈接的其他頁面;最後,調用「begin」方法開始運行「蜘蛛」,這個方法直到「蜘蛛」工作完畢或用戶取消才會返回。 當「蜘蛛」運行時,可以調用由「ISpiderReportable」介面實現的三個方法來報告程序當前狀態,程序的大部分工作都是由「spiderFoundURL」方法來完成的,當「蜘蛛」發現一個新的URL時,它首先檢查其是否有效,如果這個URL導致一個錯誤,就會把它當作一個死鏈接;如果鏈接有效,就會繼續檢查它是否在一個不同的伺服器上,如果鏈接在同一伺服器上,「spiderFoundURL」返回true,表示「蜘蛛」應繼續跟蹤這個URL並找出其他鏈接,如果鏈接在另外的伺服器上,就不會掃描是否還有其他鏈接,因為這會導致「蜘蛛」不斷地瀏覽Internet,尋找更多、更多的網站,所以,示常式序只會查找用戶指定網站上的鏈接。 構造Spider類 前面已經講了如何使用Spider類,請看例3中的代碼。使用Spider類及「ISpiderReportable」介面能方便地為某一程序添加「蜘蛛」功能,下面繼續講解Spider類是怎樣工作的。 Spider類必須保持對其訪問過的URL的跟蹤,這樣做的目的是為了確保「蜘蛛」不會訪問同一URL一次以上;進一步來說,「蜘蛛」必須把URL分成三組,第一組存儲在「workloadWaiting」屬性中,包含了一個未處理的URL列表,「蜘蛛」要訪問的第一個URL也存在其中;第二組存儲在「workloadProcessed」中,它是「蜘蛛」已經處理過且無需再次訪問的URL;第三組存儲在「workloadError」中,包含了發生錯誤的URL。 Begin方法包含了Spider類的主循環,其一直重復遍歷「workloadWaiting」,並處理其中的每一個頁面,當然我們也想到了,在這些頁面被處理時,很可能有其他的URL添加到「workloadWaiting」中,所以,begin方法一直繼續此過程,直到調用Spider類的cancel方法,或「workloadWaiting」中已不再剩有URL。這個過程如下: cancel = false; while ( !getWorkloadWaiting().isEmpty() && !cancel ) { Object list[] = getWorkloadWaiting().toArray(); for ( int i=0; (i<list.length)&&!cancel; i++="" )=""> processURL((URL)list[i]); } 當上述代碼遍歷「workloadWaiting」時,它把每個需處理的URL都傳遞給「processURL」方法,而這個方法才是真正讀取並解析URL中HTML信息的。 讀取並解析HTML Java同時支持訪問URL內容及解析HTML,而這正是「processURL」方法要做的。在Java中讀取URL內容相對還比較簡單,下面就是「processURL」方法實現此功能的代碼: URLConnection connection = url.openConnection(); if ( (connection.getContentType()!=null) &&!connection.getContentType().toLowerCase().startsWith("text/") ) { getWorkloadWaiting().remove(url); getWorkloadProcessed().add(url); log("Not processing because content type is: " + connection.getContentType() );
❺ 怎麼在DOS下用C語言寫網路爬蟲
獲取cspider_t。
自定義user agent,cookie,timeout,proxy以及抓取線程和解析線程的最大數量。
添加初始要抓取的url到任務隊列。
編寫解析函數和數據持久化函數。
啟動爬蟲。
- #include<cspider/spider.h>
- /*
- 自定義的解析函數,d為獲取到的html頁面字元串
- */
- void p(cspider_t *cspider, char *d, void *user_data) {
- char *get[100];
- //xpath解析html
- int size = xpath(d, "//body/div[@class='wrap']/div[@class='sort-column area']/div[@class='column-bd cfix']/ul[@class='st-list cfix']/li/strong/a", get, 100);
- int i;
- for (i = 0; i < size; i++) {
- //將獲取到的電影名稱,持久化
- saveString(cspider, get[i]);
- }
- }
- /*
- 數據持久化函數,對上面解析函數中調用的saveString()函數傳入的數據,進行進一步的保存
- */
- void s(void *str, void *user_data) {
- char *get = (char *)str;
- FILE *file = (FILE*)user_data;
- fprintf(file, "%s ", get);
- return;
- }
- int main() {
- //初始化spider
- cspider_t *spider = init_cspider();
- char *agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:42.0) Gecko/20100101 Firefox/42.0";
- //char *cookie = "bid=s3/yuH5Jd/I; ll=108288; viewed=1130500_24708145_6433169_4843567_1767120_5318823_1899158_1271597; __utma=30149280.927537245.1446813674.1446983217.1449139583.4; __utmz=30149280.1449139583.4.4.utmcsr=accounts.douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/login; ps=y; [email protected]; dbcl2=58742090:QgZ2PSLiDLQ; ck=T9Wn; push_noty_num=0; push_doumail_num=7; ap=1; __utmb=30149280.0.10.1449139583; __utmc=30149280";
- //設置要抓取頁面的url
- cs_setopt_url(spider, "so.tv.sohu.com/list_p1100_p20_p3_u5185_u5730_p40_p5_p6_p77_p80_p9_2d1_p101_p11.html");
- //設置user agent
- cs_setopt_useragent(spider, agent);
- //cs_setopt_cookie(spider, cookie);
- //傳入解析函數和數據持久化函數的指針
- cs_setopt_process(spider, p, NULL);
- //s函數的user_data指針指向stdout
- cs_setopt_save(spider, s, stdout);
- //設置線程數量
- cs_setopt_threadnum(spider, DOWNLOAD, 2);
- cs_setopt_threadnum(spider, SAVE, 2);
- //FILE *fp = fopen("log", "wb+");
- //cs_setopt_logfile(spider, fp);
- //開始爬蟲
- return cs_run(spider);
- }
例子
先來看下簡單的爬蟲例子,會在後面詳細講解例子。
❻ 有人有簡單爬蟲源碼可以學習嗎
爬蟲學習之一個簡單的網路爬蟲
概述
這是一個網路爬蟲學習的技術分享,主要通過一些實際的案例對爬蟲的原理進行分析,達到對爬蟲有個基本的認識,並且能夠根據自己的需要爬到想要的數據。有了數據後可以做數據分析或者通過其他方式重新結構化展示。
什麼是網路爬蟲
網路爬蟲(又被稱為網頁蜘蛛,網路機器人,在FOAF社區中間,更經常的稱為網頁追逐者),是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本。另外一些不常使用的名字還有螞蟻、自動索引、模擬程序或者蠕蟲。via網路網路爬蟲
網路蜘蛛(Web spider)也叫網路爬蟲(Web crawler)[1],螞蟻(ant),自動檢索工具(automatic indexer),或者(在FOAF軟體概念中)網路疾走(WEB scutter),是一種「自動化瀏覽網路」的程序,或者說是一種網路機器人。它們被廣泛用於互聯網搜索引擎或其他類似網站,以獲取或更新這些網站的內容和檢索方式。它們可以自動採集所有其能夠訪問到的頁面內容,以供搜索引擎做進一步處理(分檢整理下載的頁面),而使得用戶能更快的檢索到他們需要的信息。via維基網路網路蜘蛛
以上是網路和維基網路對網路爬蟲的定義,簡單來說爬蟲就是抓取目標網站內容的工具,一般是根據定義的行為自動進行抓取,更智能的爬蟲會自動分析目標網站結構類似與搜索引擎的爬蟲,我們這里只討論基本的爬蟲原理。
###爬蟲工作原理
網路爬蟲框架主要由控制器、解析器和索引庫三大部分組成,而爬蟲工作原理主要是解析器這個環節,解析器的主要工作是下載網頁,進行頁面的處理,主要是將一些JS腳本標簽、CSS代碼內容、空格字元、HTML標簽等內容處理掉,爬蟲的基本工作是由解析器完成。所以解析器的具體流程是:
入口訪問->下載內容->分析結構->提取內容
分析爬蟲目標結構
這里我們通過分析一個網站[落網:http://luoo.net] 對網站內容進行提取來進一步了解!
第一步 確定目的
抓取目標網站的某一期所有音樂
第二步 分析頁面結構
訪問落網的某一期刊,通過Chrome的開發者模式查看播放列表中的歌曲,右側用紅色框線圈出來的是一些需要特別注意的語義結構,見下圖所示:
以上紅色框線圈出的地方主要有歌曲名稱,歌曲的編號等,這里並沒有看到歌曲的實際文件地址,所以我們繼續查看,點擊某一個歌曲就會立即在瀏覽器中播放,這時我們可以看到在Chrome的開發者模式的Network中看到實際請求的播放文件,如下圖所示:
根據以上分析我們可以得到播放清單的位置和音樂文件的路徑,接下來我們通過python來實現這個目的。
實現爬蟲
Python環境安裝請自行Google
主要依賴第三方庫
Requests(http://www.python-requests.org) 用來發起請求
BeautifulSoup(bs4) 用來解析HTML結構並提取內容
faker(http://fake-factory.readthedocs.io/en/stable/)用來模擬請求UA(User-Agent)
主要思路是分成兩部分,第一部分用來發起請求分析出播放列表然後丟到隊列中,第二部分在隊列中逐條下載文件到本地,一般分析列錶速度更快,下載速度比較慢可以藉助多線程同時進行下載。
主要代碼如下:
#-*- coding: utf-8 -*-'''by sudo rm -rf http://imchenkun.com'''import osimport requestsfrom bs4 import BeautifulSoupimport randomfrom faker import Factoryimport Queueimport threadingfake = Factory.create()luoo_site = 'http://www.luoo.net/music/'luoo_site_mp3 = 'http://luoo-mp3.kssws.ks-cdn.com/low/luoo/radio%s/%s.mp3'proxy_ips = [ '27.15.236.236' ] # 替換自己的代理IPheaders = { 'Connection': 'keep-alive', 'User-Agent': fake.user_agent() }def random_proxies(): ip_index = random.randint(0, len(proxy_ips)-1) res = { 'http': proxy_ips[ip_index] } return resdef fix_characters(s): for c in ['<', '>', ':', '"', '/', '\\', '|', '?', '*']: s = s.replace(c, '') return sclass LuooSpider(threading.Thread): def __init__(self, url, vols, queue=None): threading.Thread.__init__(self) print '[luoo spider]' print '=' * 20 self.url = url self.queue = queue self.vol = '1' self.vols = vols def run(self): for vol in self.vols: self.spider(vol) print '\ncrawl end\n\n' def spider(self, vol): url = luoo_site + vol print 'crawling: ' + url + '\n' res = requests.get(url, proxies=random_proxies()) soup = BeautifulSoup(res.content, 'html.parser') title = soup.find('span', attrs={'class': 'vol-title'}).text cover = soup.find('img', attrs={'class': 'vol-cover'})['src'] desc = soup.find('div', attrs={'class': 'vol-desc'}) track_names = soup.find_all('a', attrs={'class': 'trackname'}) track_count = len(track_names) tracks = [] for track in track_names: _id = str(int(track.text[:2])) if (int(vol) < 12) else track.text[:2] # 12期前的音樂編號1~9是1位(如:1~9),之後的都是2位 1~9會在左邊墊0(如:01~09) _name = fix_characters(track.text[4:]) tracks.append({'id': _id, 'name': _name}) phases = { 'phase': vol, # 期刊編號 'title': title, # 期刊標題 'cover': cover, # 期刊封面 'desc': desc, # 期刊描述 'track_count': track_count, # 節目數 'tracks': tracks # 節目清單(節目編號,節目名稱) } self.queue.put(phases)class LuooDownloader(threading.Thread): def __init__(self, url, dist, queue=None): threading.Thread.__init__(self) self.url = url self.queue = queue self.dist = dist self.__counter = 0 def run(self): while True: if self.queue.qsize() <= 0: pass else: phases = self.queue.get() self.download(phases) def download(self, phases): for track in phases['tracks']: file_url = self.url % (phases['phase'], track['id']) local_file_dict = '%s/%s' % (self.dist, phases['phase']) if not os.path.exists(local_file_dict): os.makedirs(local_file_dict) local_file = '%s/%s.%s.mp3' % (local_file_dict, track['id'], track['name']) if not os.path.isfile(local_file): print 'downloading: ' + track['name'] res = requests.get(file_url, proxies=random_proxies(), headers=headers) with open(local_file, 'wb') as f: f.write(res.content) f.close() print 'done.\n' else: print 'break: ' + track['name']if __name__ == '__main__': spider_queue = Queue.Queue() luoo = LuooSpider(luoo_site, vols=['680', '721', '725', '720'],queue=spider_queue) luoo.setDaemon(True) luoo.start() downloader_count = 5 for i in range(downloader_count): luoo_download = LuooDownloader(luoo_site_mp3, 'D:/luoo', queue=spider_queue) luoo_download.setDaemon(True) luoo_download.start()
以上代碼執行後結果如下圖所示
Github地址:https://github.com/imchenkun/ick-spider/blob/master/luoospider.py
總結
通過本文我們基本了解了網路爬蟲的知識,對網路爬蟲工作原理認識的同時我們實現了一個真實的案例場景,這里主要是使用一些基礎的第三方Python庫來幫助我們實現爬蟲,基本上演示了網路爬蟲框架中基本的核心概念。通常工作中我們會使用一些比較優秀的爬蟲框架來快速的實現需求,比如scrapy框架,接下來我會通過使用Scrapy這類爬蟲框架來實現一個新的爬蟲來加深對網路爬蟲的理解!
❼ python爬蟲怎麼獲取動態的網頁源碼
一個月前實習導師布置任務說通過網路爬蟲獲取深圳市氣象局發布的降雨數據,網頁如下:
心想,爬蟲不太難的,當年跟zjb爬煎蛋網無(mei)聊(zi)圖的時候,多麼清高。由於接受任務後的一個月考試加作業一大堆,導師也不催,自己也不急。
但是,導師等我一個月都得讓我來寫意味著這東西得有多難吧。。。今天打開一看的確是這樣。網站是基於Ajax寫的,數據動態獲取,所以無法通過下載源代碼然後解析獲得。
從某不良少年寫的抓取淘寶mm的例子中收到啟發,對於這樣的情況,一般可以同構自己搭建瀏覽器實現。phantomJs,CasperJS都是不錯的選擇。
導師的要求是獲取過去一年內深圳每個區每個站點每小時的降雨量,執行該操作需要通過如上圖中的歷史查詢實現,即通過一個時間來查詢,而這個時間存放在一個hidden類型的input標簽里,當然可以通過js語句將其改為text類型,然後執行send_keys之類的操作。然而,我失敗了。時間可以修改設置,可是結果如下圖。
為此,僅抓取實時數據。選取python的selenium,模擬搭建瀏覽器,模擬人為的點擊等操作實現數據生成和獲取。selenium的一大優點就是能獲取網頁渲染後的源代碼,即執行操作後的源代碼。普通的通過 url解析網頁的方式只能獲取給定的數據,不能實現與用戶之間的交互。selenium通過獲取渲染後的網頁源碼,並通過豐富的查找工具,個人認為最好用的就是find_element_by_xpath("xxx"),通過該方式查找到元素後可執行點擊、輸入等事件,進而向伺服器發出請求,獲取所需的數據。
[python]view plain
#coding=utf-8
fromtestStringimport*
fromseleniumimportwebdriver
importstring
importos
fromselenium.webdriver.common.keysimportKeys
importtime
importsys
default_encoding='utf-8'
ifsys.getdefaultencoding()!=default_encoding:
reload(sys)
sys.setdefaultencoding(default_encoding)
district_navs=['nav2','nav1','nav3','nav4','nav5','nav6','nav7','nav8','nav9','nav10']
district_names=['福田區','羅湖區','南山區','鹽田區','寶安區','龍崗區','光明新區','坪山新區','龍華新區','大鵬新區']
flag=1
while(flag>0):
driver=webdriver.Chrome()
driver.get("hianCe/")
#選擇降雨量
driver.find_element_by_xpath("//span[@id='fenqu_H24R']").click()
filename=time.strftime("%Y%m%d%H%M",time.localtime(time.time()))+'.txt'
#創建文件
output_file=open(filename,'w')
#選擇行政區
foriinrange(len(district_navs)):
driver.find_element_by_xpath("//div[@id='"+district_navs[i]+"']").click()
#printdriver.page_source
timeElem=driver.find_element_by_id("time_shikuang")
#輸出時間和站點名
output_file.write(timeElem.text+',')
output_file.write(district_names[i]+',')
elems=driver.find_elements_by_xpath("//span[@onmouseover='javscript:changeTextOver(this)']")
#輸出每個站點的數據,格式為:站點名,一小時降雨量,當日累積降雨量
foreleminelems:
output_file.write(AMonitorRecord(elem.get_attribute("title"))+',')
output_file.write(' ')
output_file.close()
driver.close()
time.sleep(3600)
- 文件中引用的文件testString只是修改輸出格式,提取有效數據。
#Encoding=utf-8
defOnlyCharNum(s,oth=''):
s2=s.lower()
fomart=',.'
forcins2:
ifnotcinfomart:
s=s.replace(c,'')
returns
defAMonitorRecord(str):
str=str.split(":")
returnstr[0]+","+OnlyCharNum(str[1])
- 一小時抓取一次數據,結果如下:
[python]view plain
❽ python怎麼看源碼進行網路爬蟲
在我們日常上網瀏覽網頁的時候,經常會看到一些好看的圖片,我們就希望把這些圖片保存下載,或者用戶用來做桌面壁紙,或者用來做設計的素材。
我們最常規的做法就是通過滑鼠右鍵,選擇另存為。但有些圖片滑鼠右鍵的時候並沒有另存為選項,還有辦法就通過就是通過截圖工具截取下來,但這樣就降低圖片的清晰度。好吧~!其實你很厲害的,右鍵查看頁面源代碼。
我們可以通過python 來實現這樣一個簡單的爬蟲功能,把我們想要的代碼爬取到本地。下面就看看如何使用python來實現這樣一個功能。
一,獲取整個頁面數據
首先我們可以先獲取要下載圖片的整個頁面信息。
getjpg.py
#coding=utf-8
import urllib
def getHtml(url):
page = urllib.urlopen(url)
html = page.read()
return html
html = getHtml("http://tieba..com/p/2738151262")
print html
Urllib 模塊提供了讀取web頁面數據的介面,我們可以像讀取本地文件一樣讀取www和ftp上的數據。首先,我們定義了一個getHtml()函數:
urllib.urlopen()方法用於打開一個URL地址。
read()方法用於讀取URL上的數據,向getHtml()函數傳遞一個網址,並把整個頁面下載下來。執行程序就會把整個網頁列印輸出。
二,篩選頁面中想要的數據
Python 提供了非常強大的正則表達式,我們需要先要了解一點python 正則表達式的知識才行。
http://www.cnblogs.com/fnng/archive/2013/05/20/3089816.html
假如我們網路貼吧找到了幾張漂亮的壁紙,通過到前段查看工具。找到了圖片的地址,如:src=」https://gss0..com/70cFfyinKgQFm2e88IuM_a/forum......jpg」pic_ext=」jpeg」
修改代碼如下:
import re
import urllib
def getHtml(url):
page = urllib.urlopen(url)
html = page.read()
return html
def getImg(html):
reg = r'src="(.+?\.jpg)" pic_ext'
imgre = re.compile(reg)
imglist = re.findall(imgre,html)
return imglist
html = getHtml("http://tieba..com/p/2460150866")
print getImg(html)
我們又創建了getImg()函數,用於在獲取的整個頁面中篩選需要的圖片連接。re模塊主要包含了正則表達式:
re.compile() 可以把正則表達式編譯成一個正則表達式對象.
re.findall() 方法讀取html 中包含 imgre(正則表達式)的數據。
運行腳本將得到整個頁面中包含圖片的URL地址。
三,將頁面篩選的數據保存到本地
把篩選的圖片地址通過for循環遍歷並保存到本地,代碼如下:
#coding=utf-8
import urllib
import re
def getHtml(url):
page = urllib.urlopen(url)
html = page.read()
return html
def getImg(html):
reg = r'src="(.+?\.jpg)" pic_ext'
imgre = re.compile(reg)
imglist = re.findall(imgre,html)
x = 0
for imgurl in imglist:
urllib.urlretrieve(imgurl,'%s.jpg' % x)
x+=1
html = getHtml("http://tieba..com/p/2460150866")
print getImg(html)
這里的核心是用到了urllib.urlretrieve()方法,直接將遠程數據下載到本地。
通過一個for循環對獲取的圖片連接進行遍歷,為了使圖片的文件名看上去更規范,對其進行重命名,命名規則通過x變數加1。保存的位置默認為程序的存放目錄。
程序運行完成,將在目錄下看到下載到本地的文件。
❾ 網路爬蟲論文
1、爬蟲技術概述
網路爬蟲(Web crawler),是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本,它們被廣泛用於互聯網搜索引擎或其他類似網站,可以自動採集所有其能夠訪問到的頁面內容,以獲取或更新這些網站的內容和檢索方式。從功能上來講,爬蟲一般分為數據採集,處理,儲存三個部分。傳統爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足系統的一定停止條件。聚焦爬蟲的工作流程較為復雜,需要根據一定的網頁分析演算法過濾與主題無關的鏈接,保留有用的鏈接並將其放入等待抓取的URL隊列。然後,它將根據一定的搜索策略從隊列中選擇下一步要抓取的網頁URL,並重復上述過程,直到達到系統的某一條件時停止。另外,所有被爬蟲抓取的網頁將會被系統存貯,進行一定的分析、過濾,並建立索引,以便之後的查詢和檢索;對於聚焦爬蟲來說,這一過程所得到的分析結果還可能對以後的抓取過程給出反饋和指導。
相對於通用網路爬蟲,聚焦爬蟲還需要解決三個主要問題:
(1) 對抓取目標的描述或定義;
(2) 對網頁或數據的分析與過濾;
(3) 對URL的搜索策略。
2、爬蟲原理
2.1 網路爬蟲原理
Web網路爬蟲系統的功能是下載網頁數據,為搜索引擎系統提供數據來源。很多大型的網路搜索引擎系統都被稱為基於 Web數據採集的搜索引擎系統,比如 Google、Bai。由此可見Web 網路爬蟲系統在搜索引擎中的重要性。網頁中除了包含供用戶閱讀的文字信息外,還包含一些超鏈接信息。Web網路爬蟲系統正是通過網頁中的超連接信息不斷獲得網路上的其它網頁。正是因為這種採集過程像一個爬蟲或者蜘蛛在網路上漫遊,所以它才被稱為網路爬蟲系統或者網路蜘蛛系統,在英文中稱為Spider或者Crawler。
2.3.2寬度優先遍歷策略
寬度優先遍歷策略的基本思路是,將新下載網頁中發現的鏈接直接插入待抓取URL隊列的末尾。也就是指網路爬蟲會先抓取起始網頁中鏈接的所有網頁,然後再選擇其中的一個鏈接網頁,繼續抓取在此網頁中鏈接的所有網頁。還是以上面的圖為例:
遍歷路徑:A-B-C-D-E-F G H I
2.3.3反向鏈接數策略
反向鏈接數是指一個網頁被其他網頁鏈接指向的數量。反向鏈接數表示的是一個網頁的內容受到其他人的推薦的程度。因此,很多時候搜索引擎的抓取系統會使用這個指標來評價網頁的重要程度,從而決定不同網頁的抓取先後順序。
在真實的網路環境中,由於廣告鏈接、作弊鏈接的存在,反向鏈接數不能完全等他我那個也的重要程度。因此,搜索引擎往往考慮一些可靠的反向鏈接數。
2.3.4Partial PageRank策略
Partial PageRank演算法借鑒了PageRank演算法的思想:對於已經下載的網頁,連同待抓取URL隊列中的URL,形成網頁集合,計算每個頁面的PageRank值,計算完之後,將待抓取URL隊列中的URL按照PageRank值的大小排列,並按照該順序抓取頁面。
如果每次抓取一個頁面,就重新計算PageRank值,一種折中方案是:每抓取K個頁面後,重新計算一次PageRank值。但是這種情況還會有一個問題:對於已經下載下來的頁面中分析出的鏈接,也就是我們之前提到的未知網頁那一部分,暫時是沒有PageRank值的。為了解決這個問題,會給這些頁面一個臨時的PageRank值:將這個網頁所有入鏈傳遞進來的PageRank值進行匯總,這樣就形成了該未知頁面的PageRank值,從而參與排序。下面舉例說明:
2.3.5OPIC策略策略
該演算法實際上也是對頁面進行一個重要性打分。在演算法開始前,給所有頁面一個相同的初始現金(cash)。當下載了某個頁面P之後,將P的現金分攤給所有從P中分析出的鏈接,並且將P的現金清空。對於待抓取URL隊列中的所有頁面按照現金數進行排序。
2.3.6大站優先策略
對於待抓取URL隊列中的所有網頁,根據所屬的網站進行分類。對於待下載頁面數多的網站,優先下載。這個策略也因此叫做大站優先策略。
3、爬蟲分類
開發網路爬蟲應該選擇Nutch、Crawler4j、WebMagic、scrapy、WebCollector還是其他的?上面說的爬蟲,基本可以分3類:
(1)分布式爬蟲:Nutch
(2)JAVA爬蟲:Crawler4j、WebMagic、WebCollector
(3)非JAVA爬蟲:scrapy(基於Python語言開發)
3.1 分布式爬蟲
爬蟲使用分布式,主要是解決兩個問題:
1)海量URL管理
2)網速
現在比較流行的分布式爬蟲,是Apache的Nutch。但是對於大多數用戶來說,Nutch是這幾類爬蟲里,最不好的選擇,理由如下:
1)Nutch是為搜索引擎設計的爬蟲,大多數用戶是需要一個做精準數據爬取(精抽取)的爬蟲。Nutch運行的一套流程里,有三分之二是為了搜索引擎而設計的。對精抽取沒有太大的意義。也就是說,用Nutch做數據抽取,會浪費很多的時間在不必要的計算上。而且如果你試圖通過對Nutch進行二次開發,來使得它適用於精抽取的業務,基本上就要破壞Nutch的框架,把Nutch改的面目全非,有修改Nutch的能力,真的不如自己重新寫一個分布式爬蟲框架了。
2)Nutch依賴hadoop運行,hadoop本身會消耗很多的時間。如果集群機器數量較少,爬取速度反而不如單機爬蟲快。
3)Nutch雖然有一套插件機制,而且作為亮點宣傳。可以看到一些開源的Nutch插件,提供精抽取的功能。但是開發過Nutch插件的人都知道,Nutch的插件系統有多蹩腳。利用反射的機制來載入和調用插件,使得程序的編寫和調試都變得異常困難,更別說在上面開發一套復雜的精抽取系統了。而且Nutch並沒有為精抽取提供相應的插件掛載點。Nutch的插件有隻有五六個掛載點,而這五六個掛載點都是為了搜索引擎服務的,並沒有為精抽取提供掛載點。大多數Nutch的精抽取插件,都是掛載在「頁面解析」(parser)這個掛載點的,這個掛載點其實是為了解析鏈接(為後續爬取提供URL),以及為搜索引擎提供一些易抽取的網頁信息(網頁的meta信息、text文本)。
4)用Nutch進行爬蟲的二次開發,爬蟲的編寫和調試所需的時間,往往是單機爬蟲所需的十倍時間不止。了解Nutch源碼的學習成本很高,何況是要讓一個團隊的人都讀懂Nutch源碼。調試過程中會出現除程序本身之外的各種問題(hadoop的問題、hbase的問題)。
5)很多人說Nutch2有gora,可以持久化數據到avro文件、hbase、mysql等。很多人其實理解錯了,這里說的持久化數據,是指將URL信息(URL管理所需要的數據)存放到avro、hbase、mysql。並不是你要抽取的結構化數據。其實對大多數人來說,URL信息存在哪裡無所謂。
6)Nutch2的版本目前並不適合開發。官方現在穩定的Nutch版本是nutch2.2.1,但是這個版本綁定了gora-0.3。如果想用hbase配合nutch(大多數人用nutch2就是為了用hbase),只能使用0.90版本左右的hbase,相應的就要將hadoop版本降到hadoop 0.2左右。而且nutch2的官方教程比較有誤導作用,Nutch2的教程有兩個,分別是Nutch1.x和Nutch2.x,這個Nutch2.x官網上寫的是可以支持到hbase 0.94。但是實際上,這個Nutch2.x的意思是Nutch2.3之前、Nutch2.2.1之後的一個版本,這個版本在官方的SVN中不斷更新。而且非常不穩定(一直在修改)。
所以,如果你不是要做搜索引擎,盡量不要選擇Nutch作為爬蟲。有些團隊就喜歡跟風,非要選擇Nutch來開發精抽取的爬蟲,其實是沖著Nutch的名氣(Nutch作者是Doug Cutting),當然最後的結果往往是項目延期完成。
如果你是要做搜索引擎,Nutch1.x是一個非常好的選擇。Nutch1.x和solr或者es配合,就可以構成一套非常強大的搜索引擎了。如果非要用Nutch2的話,建議等到Nutch2.3發布再看。目前的Nutch2是一個非常不穩定的版本。
❿ 如何優雅地使用c語言編寫爬蟲
大家在平時或多或少地都會有編寫網路爬蟲的需求。一般來說,編寫爬蟲的首選自然非python莫屬,除此之外,java等語言也是不錯的選擇。選擇上述語言的原因不僅僅在於它們均有非常不錯的網路請求庫和字元串處理庫,還在於基於上述語言的爬蟲框架非常之多和完善。良好的爬蟲框架可以確保爬蟲程序的穩定性,以及編寫程序的便捷性。所以,這個cspider爬蟲庫的使命在於,我們能夠使用c語言,依然能夠優雅地編寫爬蟲程序。
爬蟲的特性
配置方便。使用一句設置函數,即可定義user agent,cookie,timeout,proxy以及抓取線程和解析線程的最大數量。
程序邏輯獨立。用戶可以分別定義爬蟲的解析函數,和數據持久化函數。並且對於解析到的新url,用戶可以使用cspider提供的addUrl函數,將其加入到任務隊列中。
便捷的字元串處理。cspider中提供了基於pcre的簡單的正則表達式函數,基於libxml2的xpath解析函數,以及用於解析json的cJSON庫。
高效的抓取。cspider基於libuv調度抓取線程和解析線程,使用curl作為其網路請求庫。
使用cspider的步驟
獲取cspider_t。
自定義user agent,cookie,timeout,proxy以及抓取線程和解析線程的最大數量。
添加初始要抓取的url到任務隊列。
編寫解析函數和數據持久化函數。
啟動爬蟲。
例子
先來看下簡單的爬蟲例子,會在後面詳細講解例子。
#include<cspider/spider.h>
/*
自定義的解析函數,d為獲取到的html頁面字元串
*/
void p(cspider_t *cspider, char *d, void *user_data) {
char *get[100];
//xpath解析html
int size = xpath(d, "//body/div[@class='wrap']/div[@class='sort-column area']/div[@class='column-bd cfix']/ul[@class='st-list cfix']/li/strong/a", get, 100);
int i;
for (i = 0; i < size; i++) {
//將獲取到的電影名稱,持久化
saveString(cspider, get[i]);
}
}
/*
數據持久化函數,對上面解析函數中調用的saveString()函數傳入的數據,進行進一步的保存
*/
void s(void *str, void *user_data) {
char *get = (char *)str;
FILE *file = (FILE*)user_data;
fprintf(file, "%s\n", get);
return;
}
int main() {
//初始化spider
cspider_t *spider = init_cspider();
char *agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:42.0) Gecko/20100101 Firefox/42.0";
//char *cookie = "bid=s3/yuH5Jd/I; ll=108288; viewed=1130500_24708145_6433169_4843567_1767120_5318823_1899158_1271597; __utma=30149280.927537245.1446813674.1446983217.1449139583.4; __utmz=30149280.1449139583.4.4.utmcsr=accounts.douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/login; ps=y; [email protected]; dbcl2=58742090:QgZ2PSLiDLQ; ck=T9Wn; push_noty_num=0; push_doumail_num=7; ap=1; __utmb=30149280.0.10.1449139583; __utmc=30149280";
//設置要抓取頁面的url
cs_setopt_url(spider, "so.tv.sohu.com/list_p1100_p20_p3_u5185_u5730_p40_p5_p6_p77_p80_p9_2d1_p101_p11.html");
//設置user agent
cs_setopt_useragent(spider, agent);
//cs_setopt_cookie(spider, cookie);
//傳入解析函數和數據持久化函數的指針
cs_setopt_process(spider, p, NULL);
//s函數的user_data指針指向stdout
cs_setopt_save(spider, s, stdout);
//設置線程數量
cs_setopt_threadnum(spider, DOWNLOAD, 2);
cs_setopt_threadnum(spider, SAVE, 2);
//FILE *fp = fopen("log", "wb+");
//cs_setopt_logfile(spider, fp);
//開始爬蟲
return cs_run(spider);
}
例子講解
cspider_t *spider = init_cspider();獲取初始的cspider。cs_setopt_xxx這類函數可以用來進行初始化設置。其中要注意的是: cs_setopt_process(spider,p,NULL);與cs_setopt_save(spider,s,stdout);,它們分別設置了解析函數p和數據持久化函數s,這兩個函數需要用戶自己實現,還有用戶自定義的指向上下文信息user_data的指針。
在解析函數中,用戶要定義解析的規則,並對解析得到的字元串可以調用saveString進行持久化,或者是調用addUrl將url加入到任務隊列中。在saveString中傳入的字元串會在用戶自定義的數據持久函數中得到處理。此時,用戶可以選擇輸出到文件或資料庫等。
最後調用cs_run(spider)即可啟動爬蟲。
具體的API參數可在這里查看