去哪兒網圖片爬蟲及Scrapy使用詳解

本文分為兩部分,去哪兒網圖片爬蟲和Scrapy使用詳解。Scrapy使用詳解基于去哪兒網圖片爬蟲進行解析說明。

去哪兒網圖片爬蟲

  • 目錄結構
$ scrapy startproject TourLib

Scrapy組件說明

  1. Scrapy Engine(Scrapy引擎)
    Scrapy引擎是用來控制整個系統(tǒng)的數據處理流程,并進行事務處理的觸發(fā)。更多的詳細內容可以看下面的數據處理流程。
  2. Scheduler(調度)
    調度程序從Scrapy引擎接受請求并排序列入隊列,并在Scrapy引擎發(fā)出請求后返還給他們。
  3. Downloader(下載器)
    下載器的主要職責是抓取網頁并將網頁內容返還給蜘蛛( Spiders)。
  4. Spiders(蜘蛛)
    蜘蛛是有Scrapy用戶自己定義用來解析網頁并抓取制定URL返回的內容的類,是用來定義特定網站的抓取和解析規(guī)則。
    蜘蛛的整個抓取流程(周期)是這樣的:
  • 首先獲取第一個URL的初始請求,當請求返回后調取一個回調函數(parse(self, response))。第一個請求是通過調用start_requests()方法。該方法默認從start_urls中的Url中生成請求,并執(zhí)行解析來調用回調函數。
  • 在回調函數(parse)中,你可以解析網頁響應并返回項目對象和請求對象或兩者的迭代。這些請求也將包含一個回調(scrapy.Request(links, callback=self.parse_item)),然后被Scrapy下載,然后有指定的回調parse_item
    (self, response)處理。
  • 在回調函數parse_item中,你解析網站的內容,使用的是Xpath選擇器(但是你也可以使用BeautifuSoup, lxml或其他任何你喜歡的程序),并生成解析的數據項。
  • 最后,從蜘蛛返回的項目通常會進駐到Item Pipeline(項目管道)。
  1. Item Pipeline(項目管道)
    項目管道的主要責任是負責處理有蜘蛛從網頁中抽取的項目,他的主要任務是清洗、驗證和存儲數據。當頁面被蜘蛛解析后,將被發(fā)送到項目管道,并經過幾個特定的次序處理數據。每個項目管道的組件都是有一個簡單的方法組成的Python類。他們獲取了項目并執(zhí)行他們的方法,同時他們還需要確定的是是否需要在項目管道中繼續(xù)執(zhí)行下一步或是直接丟棄掉不處理。
    項目管道通常執(zhí)行的過程有:
  • 清洗HTML數據
  • 驗證解析到的數據(檢查項目是否包含必要的字段)
  • 檢查是否是重復數據(如果重復就刪除)
  • 將解析到的數據存儲到數據庫,將解析到的圖片存儲到硬盤
    piplines就干了兩件事,每次spider處理好一個頁面,將圖片信息傳給它,1.圖片存到硬盤,2.信息存到數據庫
  1. Downloader middlewares(下載器中間件)
    下載中間件是位于Scrapy引擎和下載器之間的鉤子框架,主要是處理 Scrapy引擎與下載器之間的請求及響應。它提供了一個自定義的代碼的方式來拓展Scrapy的功能。下載中間器是一個處理請求和響應的鉤子框架。他是 輕量級的,對Scrapy盡享全局控制的底層的系統(tǒng)。
  2. Spider middlewares(蜘蛛中間件)
    蜘蛛中間件是介于Scrapy引擎和蜘蛛之間的鉤子框架,主要工作是處理蜘蛛 的響應輸入和請求輸出。它提供一個自定義代碼的方式來拓展Scrapy的功能。蛛中間件是一個掛接到Scrapy的蜘蛛處理機制的框架,你可以插入自定義 的代碼來處理發(fā)送給蜘蛛的請求和返回蜘蛛獲取的響應內容和項目。
  3. Scheduler middlewares(調度中間件)
    調度中間件是介于Scrapy引擎和調度之間的中間件,主要工作是處從Scrapy引擎發(fā)送到調度的請求和響應。他提供了一個自定義的代碼來拓展Scrapy的功能。前陣子想爬點二手車數據賺錢,專門搗鼓了一兩個星期的scrapy,雖然最后因為各種原因,賺錢并不如意,但也學到了爬蟲的一些基本技術,現在記錄下來,以備后續(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中添加數據庫操作如下:
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)  
                       # 提交到數據庫執(zhí)行  
                       db.commit()  
                    except:  
                       # 發(fā)生錯誤時回滾  
                       db.rollback()            

                item['images'] = images

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

Xpath使用

示例

xpath類似beautifulsoup解析html結構,省去了正則表達式的麻煩

<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參考教程

這是個視頻教程,是我學習xpath的最好的教程,看完真的是一下就明白了。
XPath 與多線程爬蟲
Scrapy定向爬蟲教程(二)——提取網頁內容

多頁面爬取

多頁面爬取有兩種形式

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

#先獲取url list,然后根據list爬取各個子頁面內容  
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')"):  
#獲取當前頁面的url:respone.url  
#通過拼接response.url和href.extract(),將相對網址轉換為絕對網址  
            url =response.urljoin(response.url, href.extract())  
            yield scrapy.Request(url, callback=self.parse_dir_contents)  
   
         #負責子頁面內容的爬取  
    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,就能夠實現自動化的遞歸爬取。

yield和return的區(qū)別
  • yield
    yield是用于生成器。什么是生成器,你可以通俗的認為,在一個函數中,使用了yield來代替return的位置的函數,就是生成器。它不同于函數的使用方法是:函數使用return來進行返回值,每調用一次,返回一個新加工好的數據返回給你;yield不同,它會在調用生成器的時候,把數據生成object,然后當你需要用的時候,要用next()方法來取,同時不可逆。你可以通俗的叫它"輪轉容器",可用現實的一種實物來理解:水車,先yield來裝入數據、產出generator object、使用next()來釋放;好比水車轉動后,車輪上的水槽裝入水,隨著輪子轉動,被轉到下面的水槽就能將水送入水道中流入田里。
def func3():
    for i in range(1,5):
        yield i#裝入
 
gob = func3()#generator 類型
print next(gob)#1    釋放的第一個裝入的數據,(先入先出)
print next(gob)#2
print next(gob)#3
print next(gob)#4
 
print next(gob)#報錯

個人理解,yield在python內部是當作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既可以終止函數的執(zhí)行,也可以返回函數加工處理好的數據。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容