去哪兒網(wǎng)圖片爬蟲及Scrapy使用詳解

本文分為兩部分,去哪兒網(wǎng)圖片爬蟲和Scrapy使用詳解株依。Scrapy使用詳解基于去哪兒網(wǎng)圖片爬蟲進行解析說明淋叶。

去哪兒網(wǎng)圖片爬蟲

  • 目錄結(jié)構(gòu)
$ scrapy startproject TourLib

Scrapy組件說明

  1. Scrapy Engine(Scrapy引擎)
    Scrapy引擎是用來控制整個系統(tǒng)的數(shù)據(jù)處理流程码俩,并進行事務(wù)處理的觸發(fā)。更多的詳細內(nèi)容可以看下面的數(shù)據(jù)處理流程扬霜。
  2. Scheduler(調(diào)度)
    調(diào)度程序從Scrapy引擎接受請求并排序列入隊列定鸟,并在Scrapy引擎發(fā)出請求后返還給他們。
  3. Downloader(下載器)
    下載器的主要職責(zé)是抓取網(wǎng)頁并將網(wǎng)頁內(nèi)容返還給蜘蛛( Spiders)著瓶。
  4. Spiders(蜘蛛)
    蜘蛛是有Scrapy用戶自己定義用來解析網(wǎng)頁并抓取制定URL返回的內(nèi)容的類联予,是用來定義特定網(wǎng)站的抓取和解析規(guī)則。
    蜘蛛的整個抓取流程(周期)是這樣的:
  • 首先獲取第一個URL的初始請求,當(dāng)請求返回后調(diào)取一個回調(diào)函數(shù)(parse(self, response))躯泰。第一個請求是通過調(diào)用start_requests()方法谭羔。該方法默認從start_urls中的Url中生成請求,并執(zhí)行解析來調(diào)用回調(diào)函數(shù)麦向。
  • 在回調(diào)函數(shù)(parse)中瘟裸,你可以解析網(wǎng)頁響應(yīng)并返回項目對象和請求對象或兩者的迭代。這些請求也將包含一個回調(diào)(scrapy.Request(links, callback=self.parse_item))诵竭,然后被Scrapy下載话告,然后有指定的回調(diào)parse_item
    (self, response)處理。
  • 在回調(diào)函數(shù)parse_item中卵慰,你解析網(wǎng)站的內(nèi)容沙郭,使用的是Xpath選擇器(但是你也可以使用BeautifuSoup, lxml或其他任何你喜歡的程序),并生成解析的數(shù)據(jù)項裳朋。
  • 最后病线,從蜘蛛返回的項目通常會進駐到Item Pipeline(項目管道)。
  1. Item Pipeline(項目管道)
    項目管道的主要責(zé)任是負責(zé)處理有蜘蛛從網(wǎng)頁中抽取的項目鲤嫡,他的主要任務(wù)是清洗送挑、驗證和存儲數(shù)據(jù)。當(dāng)頁面被蜘蛛解析后暖眼,將被發(fā)送到項目管道惕耕,并經(jīng)過幾個特定的次序處理數(shù)據(jù)。每個項目管道的組件都是有一個簡單的方法組成的Python類诫肠。他們獲取了項目并執(zhí)行他們的方法司澎,同時他們還需要確定的是是否需要在項目管道中繼續(xù)執(zhí)行下一步或是直接丟棄掉不處理。
    項目管道通常執(zhí)行的過程有:
  • 清洗HTML數(shù)據(jù)
  • 驗證解析到的數(shù)據(jù)(檢查項目是否包含必要的字段)
  • 檢查是否是重復(fù)數(shù)據(jù)(如果重復(fù)就刪除)
  • 將解析到的數(shù)據(jù)存儲到數(shù)據(jù)庫栋豫,將解析到的圖片存儲到硬盤
    piplines就干了兩件事挤安,每次spider處理好一個頁面,將圖片信息傳給它丧鸯,1.圖片存到硬盤漱受,2.信息存到數(shù)據(jù)庫
  1. Downloader middlewares(下載器中間件)
    下載中間件是位于Scrapy引擎和下載器之間的鉤子框架,主要是處理 Scrapy引擎與下載器之間的請求及響應(yīng)。它提供了一個自定義的代碼的方式來拓展Scrapy的功能。下載中間器是一個處理請求和響應(yīng)的鉤子框架乳幸。他是 輕量級的,對Scrapy盡享全局控制的底層的系統(tǒng)虐先。
  2. Spider middlewares(蜘蛛中間件)
    蜘蛛中間件是介于Scrapy引擎和蜘蛛之間的鉤子框架,主要工作是處理蜘蛛 的響應(yīng)輸入和請求輸出派敷。它提供一個自定義代碼的方式來拓展Scrapy的功能蛹批。蛛中間件是一個掛接到Scrapy的蜘蛛處理機制的框架撰洗,你可以插入自定義 的代碼來處理發(fā)送給蜘蛛的請求和返回蜘蛛獲取的響應(yīng)內(nèi)容和項目。
  3. Scheduler middlewares(調(diào)度中間件)
    調(diào)度中間件是介于Scrapy引擎和調(diào)度之間的中間件腐芍,主要工作是處從Scrapy引擎發(fā)送到調(diào)度的請求和響應(yīng)差导。他提供了一個自定義的代碼來拓展Scrapy的功能。前陣子想爬點二手車數(shù)據(jù)賺錢猪勇,專門搗鼓了一兩個星期的scrapy设褐,雖然最后因為各種原因,賺錢并不如意泣刹,但也學(xué)到了爬蟲的一些基本技術(shù)助析,現(xiàn)在記錄下來,以備后續(xù)使用椅您。

添加mysql支持

  1. settings.py中添加如下配置項
# start MySQL database configure setting
MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'cnblogsdb'
MYSQL_USER = 'root'
MYSQL_PASSWD = 'root'
# end of MySQL database configure setting
  1. 在piplines.py中添加數(shù)據(jù)庫操作如下:
class ImageDownloadPipeline(object):
    def process_item(self, item, spider):
           db = MySQLdb.connect("localhost","root","mypassword","test_db" )  
           cursor = db.cursor()  
           if 'image_urls' in item:
                images = []
                dir_path = '%s/%s/%s' % (settings.IMAGES_STORE,item['place'],item['name'])
                ##item['url'] = <200 www.explame.com>
                urls = str(item['url'])[5:-1]

                if not os.path.exists(dir_path):
                    os.makedirs(dir_path)
                for image_url in item['image_urls']:
                    image_file_name = image_url[-15:]
                    file_path = '%s/%s' % (dir_path, image_file_name)
                    images.append(file_path)
                    if os.path.exists(file_path):
                         continue
                    with open(file_path, 'wb') as handle:
                         response = requests.get(image_url, stream=True)
                         for block in response.iter_content(1024):
                             if not block:
                                 break
                             handle.write(block)

                    sql = "INSERT INTO tour_tbl (tour_title,tour_icourl,local_url) VALUES ( '%s','%s','%s' )" % ( image_file_name,image_url,urls)  
                    try:  
                       # 執(zhí)行sql語句  
                       cursor.execute(sql)  
                       # 提交到數(shù)據(jù)庫執(zhí)行  
                       db.commit()  
                    except:  
                       # 發(fā)生錯誤時回滾  
                       db.rollback()            

                item['images'] = images

            # 關(guān)閉數(shù)據(jù)庫連接  
           db.close()  
           return item
  1. 在settins.py中添加ImageDownloadPipeline
ITEM_PIPELINES = {'qunar.pipelines.ImageDownloadPipeline': 1}

Xpath使用

示例

xpath類似beautifulsoup解析html結(jié)構(gòu)外冀,省去了正則表達式的麻煩

<html>
<head></head>
<body>
<div>
 <p><a > more information </a></p>
</div>
</body>
</html>
  • xpath('//div//a')
    [<a > more information </a>]
  • xpath('//div/*')
    div中所有元素
  • xpath('//div/a/@href')
    [http://www.iana.org]
  • xpath('//div/a/text()').extract()
    'more information'
xpath參考教程

這是個視頻教程,是我學(xué)習(xí)xpath的最好的教程掀泳,看完真的是一下就明白了雪隧。
XPath 與多線程爬蟲
Scrapy定向爬蟲教程(二)——提取網(wǎng)頁內(nèi)容

多頁面爬取

多頁面爬取有兩種形式

1)從某一個或者多個主頁中獲取多個子頁面的url列表,parse()函數(shù)依次爬取列表中的各個子頁面员舵。

#先獲取url list脑沿,然后根據(jù)list爬取各個子頁面內(nèi)容  
fromtutorial.items import DmozItem  
   
classDmozSpider(scrapy.Spider):  
    name = "dmoz"  
    allowed_domains = ["dmoz.org"]  
    start_urls =["http://www.dmoz.org/Computers/Programming/Languages/Python/",]  
   
    def parse(self, response):  
        for href inresponse.css("ul.directory.dir-col > li > a::attr('href')"):  
#獲取當(dāng)前頁面的url:respone.url  
#通過拼接response.url和href.extract(),將相對網(wǎng)址轉(zhuǎn)換為絕對網(wǎng)址  
            url =response.urljoin(response.url, href.extract())  
            yield scrapy.Request(url, callback=self.parse_dir_contents)  
   
         #負責(zé)子頁面內(nèi)容的爬取  
    def parse_dir_contents(self, response):  
        for sel in response.xpath('//ul/li'):  
            item = DmozItem()  
            item['title'] =sel.xpath('a/text()').extract()  
            item['link'] = sel.xpath('a/@href').extract()  
            item['desc'] =sel.xpath('text()').extract()  
            yield item  

2)從遞歸爬取固灵,這個相對簡單。在scrapy中只要定義好初始頁面以及爬蟲規(guī)則rules劫流,就能夠?qū)崿F(xiàn)自動化的遞歸爬取巫玻。

yield和return的區(qū)別
  • yield
    yield是用于生成器。什么是生成器祠汇,你可以通俗的認為仍秤,在一個函數(shù)中,使用了yield來代替return的位置的函數(shù)可很,就是生成器诗力。它不同于函數(shù)的使用方法是:函數(shù)使用return來進行返回值,每調(diào)用一次我抠,返回一個新加工好的數(shù)據(jù)返回給你苇本;yield不同,它會在調(diào)用生成器的時候菜拓,把數(shù)據(jù)生成object瓣窄,然后當(dāng)你需要用的時候,要用next()方法來取纳鼎,同時不可逆俺夕。你可以通俗的叫它"輪轉(zhuǎn)容器"裳凸,可用現(xiàn)實的一種實物來理解:水車,先yield來裝入數(shù)據(jù)劝贸、產(chǎn)出generator object姨谷、使用next()來釋放;好比水車轉(zhuǎn)動后映九,車輪上的水槽裝入水梦湘,隨著輪子轉(zhuǎn)動,被轉(zhuǎn)到下面的水槽就能將水送入水道中流入田里氯迂。
def func3():
    for i in range(1,5):
        yield i#裝入
 
gob = func3()#generator 類型
print next(gob)#1    釋放的第一個裝入的數(shù)據(jù)践叠,(先入先出)
print next(gob)#2
print next(gob)#3
print next(gob)#4
 
print next(gob)#報錯

個人理解,yield在python內(nèi)部是當(dāng)作list處理的:

def func3():
    for i in range(1,5):
        yield i
        
yi = []
yi = func3()
for y in yi:
    print y

輸出:    
1
2
3
4
  • return
    這個大家都知道嚼蚀,return既可以終止函數(shù)的執(zhí)行禁灼,也可以返回函數(shù)加工處理好的數(shù)據(jù)。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末轿曙,一起剝皮案震驚了整個濱河市弄捕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌导帝,老刑警劉巖守谓,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異您单,居然都是意外死亡斋荞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門虐秦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來平酿,“玉大人,你說我怎么就攤上這事悦陋◎诒耍” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵俺驶,是天一觀的道長幸逆。 經(jīng)常有香客問我,道長暮现,這世上最難降的妖魔是什么还绘? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮栖袋,結(jié)果婚禮上蚕甥,老公的妹妹穿的比我還像新娘。我一直安慰自己栋荸,他們只是感情好菇怀,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布凭舶。 她就那樣靜靜地躺著,像睡著了一般爱沟。 火紅的嫁衣襯著肌膚如雪帅霜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天呼伸,我揣著相機與錄音身冀,去河邊找鬼。 笑死括享,一個胖子當(dāng)著我的面吹牛搂根,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铃辖,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼剩愧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了娇斩?” 一聲冷哼從身側(cè)響起仁卷,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎犬第,沒想到半個月后锦积,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡歉嗓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年丰介,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鉴分。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡哮幢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冠场,到底是詐尸還是另有隱情家浇,我是刑警寧澤本砰,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布碴裙,位于F島的核電站,受9級特大地震影響点额,放射性物質(zhì)發(fā)生泄漏舔株。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一还棱、第九天 我趴在偏房一處隱蔽的房頂上張望载慈。 院中可真熱鬧,春花似錦珍手、人聲如沸办铡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寡具。三九已至秤茅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間童叠,已是汗流浹背框喳。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留厦坛,地道東北人五垮。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像杜秸,于是被迫代替她去往敵國和親放仗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容