Scrapy教程——搭建環境、創建項目、爬取內容、保存文件


1、創建項目

        在開始爬取之前,您必須創建一個新的Scrapy項目。進入您打算存儲代碼的目錄中,運行新建命令。

例如,我需要在D:\00Coding\Python\scrapy目錄下存放該項目,打開命令窗口,進入該目錄,執行以下命令:

scrapy startproject  tutorial

PS:tutorial可以替換成任何你喜歡的名稱,最好是英文

      該命令將會創建包含下列內容的 tutorial 目錄:

 

tutorial/
    scrapy.cfg
    tutorial/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...

 

這些文件分別是:

 

scrapy.cfg: 項目的配置文件
tutorial/: 該項目的python模塊。之后您將在此加入代碼。
tutorial/items.py: 項目中的item文件.
tutorial/pipelines.py: 項目中的pipelines文件.
tutorial/settings.py: 項目的設置文件.
tutorial/spiders/: 放置spider代碼的目錄.

 

 

2、定義Item

        Item 是保存爬取到的數據的容器;其使用方法和python字典類似,並且提供了額外保護機制來避免拼寫錯誤導致的未定義字段錯誤。我們需要從想要爬取的網站(這里爬取新浪新聞)中獲取以下屬性:

新聞大類url、新聞大類title;

新聞小類url、新聞小類title;

新聞url、新聞title;

新聞標題、新聞內容;

       對此,在item中定義相應的字段。編輯tutorial目錄中的 items.py 文件:

 

[python]  view plain  copy
 
  1. from scrapy.item import Item, Field  
  2. class TutorialItem(Item):  
  3.     # define the fields for your item here like:  
  4.     # name = scrapy.Field()  
  5.    parent_title = Field()  
  6.    parent_url = Field()  
  7.   
  8.    second_title = Field()  
  9.    second_url = Field()  
  10.    path = Field()  
  11.   
  12.    link_title = Field()  
  13.    link_url = Field()  
  14.    head= Field()  
  15.    content = Field()  
  16.    pass  

 

 

 

3、編寫爬蟲(Spider)

       Spider是用戶編寫用於從單個網站(或者一些網站)爬取數據的類。

       1、sinaSpider.py文件:

       包含了一個用於下載的初始URL,如何跟進網頁中的鏈接以及如何分析頁面中的內容,提取生成 item 的方法。為了創建一個Spider,您必須繼承 scrapy.Spider 類,且定義以下三個屬性:

name:用於區別Spider。該名字必須是唯一的,您不可以為不同的Spider設定相同的名字。

start_urls:包含了Spider在啟動時進行爬取的url列表。因此,第一個被獲取到的頁面將是其中之一。后續的URL則從初始的URL獲取到的數據中提取。

parse() 是spider的一個方法。被調用時,每個初始URL完成下載后生成的Response 對象將會作為唯一的參數傳遞給該函數。該方法負責解析返回的數據(response data),提取數據(生成item)以及生成需要進一步處理的URL的Request 對象。

當我們爬取了大類,然后這時候沒有保存item,而是傳遞item到小類,爬取完小類之后,我們需要去新聞詳情頁爬取新聞的內容和標題:

主要思路是:paser->second_paser->detail_parse

以下是sinaSpider的全部代碼:

 

 

[python]  view plain  copy
 
  1. # -*-coding: utf-8 -*-  
  2. __author__= 'George'  
  3. import sys, os  
  4. reload(sys)  
  5. sys.setdefaultencoding("utf-8")  
  6. from scrapy.spider import Spider  
  7. from scrapy.http import Request  
  8. from scrapy.selector import Selector  
  9. from tutorial.items import TutorialItem  
  10. base ="d:/dataset/" #存放文件分類的目錄  
  11. class SinaSpider(Spider):  
  12.    name= "sina"  
  13.    allowed_domains= ["sina.com.cn"]  
  14.    start_urls= [  
  15.        "http://news.sina.com.cn/guide/"  
  16.    ]#起始urls列表  
  17.   
  18.    def parse(self, response):  
  19.        items= []  
  20.        sel= Selector(response)  
  21.        big_urls=sel.xpath('//div[@id=\"tab01\"]/div/h3/a/@href').extract()#大類的url  
  22.        big_titles=sel.xpath("//div[@id=\"tab01\"]/div/h3/a/text()").extract()  
  23.        second_urls =sel.xpath('//div[@id=\"tab01\"]/div/ul/li/a/@href').extract()#小類的url  
  24.        second_titles=sel.xpath('//div[@id=\"tab01\"]/div/ul/li/a/text()').extract()  
  25.   
  26.        for i in range(1,len(big_titles)-1):#這里不想要第一大類,big_title減去1是因為最后一個大類,沒有跳轉按鈕,也去除  
  27.            file_name = base + big_titles[i]  
  28.            #創建目錄  
  29.            if(not os.path.exists(file_name)):  
  30.                os.makedirs(file_name)  
  31.            for j in range(19,len(second_urls)):  
  32.                item = TutorialItem()  
  33.                item['parent_title'] =big_titles[i]  
  34.                item['parent_url'] =big_urls[i]  
  35.                if_belong =second_urls[j].startswith( item['parent_url'])  
  36.                if(if_belong):  
  37.                    second_file_name =file_name + '/'+ second_titles[j]  
  38.                    if(not os.path.exists(second_file_name)):  
  39.                        os.makedirs(second_file_name)  
  40.                    item['second_url'] = second_urls[j]  
  41.                    item['second_title'] =second_titles[j]  
  42.                    item['path'] =second_file_name  
  43.                    items.append(item)  
  44.        for item in items:  
  45.            yield Request(url=item['second_url'],meta={'item_1': item},callback=self.second_parse)  
  46.   
  47.    #對於返回的小類的url,再進行遞歸請求  
  48.    def second_parse(self, response):  
  49.        sel= Selector(response)  
  50.        item_1= response.meta['item_1']  
  51.        items= []  
  52.        bigUrls= sel.xpath('//a/@href').extract()  
  53.   
  54.        for i in range(0, len(bigUrls)):  
  55.            if_belong =bigUrls[i].endswith('.shtml') and bigUrls[i].startswith(item_1['parent_url'])  
  56.            if(if_belong):  
  57.                item = TutorialItem()  
  58.                item['parent_title'] =item_1['parent_title']  
  59.                item['parent_url'] =item_1['parent_url']  
  60.                item['second_url'] =item_1['second_url']  
  61.                item['second_title'] =item_1['second_title']  
  62.                item['path'] = item_1['path']  
  63.                item['link_url'] = bigUrls[i]  
  64.                items.append(item)  
  65.        for item in items:  
  66.                yield Request(url=item['link_url'], meta={'item_2':item},callback=self.detail_parse)  
  67.   
  68.    def detail_parse(self, response):  
  69.        sel= Selector(response)  
  70.        item= response.meta['item_2']  
  71.        content= ""  
  72.        head=sel.xpath('//h1[@id=\"artibodyTitle\"]/text()').extract()  
  73.        content_list=sel.xpath('//div[@id=\"artibody\"]/p/text()').extract()  
  74.        for content_one in content_list:  
  75.            content += content_one  
  76.        item['head']= head  
  77.        item['content']= content  
  78.        yield item  


         2、pipelines.py

 

     主要是對於抓取數據的保存(txt),這里把文件名命名為鏈接中'/'替換成'_'

 

 

[python]  view plain  copy
 
  1. # -*- coding: utf-8 -*-  
  2.   
  3. # Define your item pipelines here  
  4. #  
  5. # Don't forget to add your pipeline to the ITEM_PIPELINES setting  
  6. # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html  
  7. from scrapy import signals  
  8. import json  
  9. import codecs  
  10. import sys  
  11. reload(sys)  
  12. sys.setdefaultencoding( "utf-8" )  
  13. class SinaPipeline(object):  
  14.     def process_item(self, item, spider):  
  15.         link_url = item['link_url']  
  16.         file_name = link_url[7:-6].replace('/','_')  
  17.         file_name += ".txt"  
  18.         fp = open(item['path']+'/'+file_name, 'w')  
  19.         fp.write(item['content'])  
  20.         fp.close()  
  21.         return item  

3、setting.py

 

    這是設置文件,這里需要設置同時開啟的線程數目、日志打印的級別等

 

 

[python]  view plain  copy
 
  1. # -*- coding: utf-8 -*-  
  2. BOT_NAME = 'tutorial'  
  3.   
  4. SPIDER_MODULES = ['tutorial.spiders']  
  5. NEWSPIDER_MODULE = 'tutorial.spiders'  
  6. ITEM_PIPELINES = {  
  7.     'tutorial.pipelines.SinaPipeline': 300,  
  8. }  
  9. LOG_LEVEL = 'INFO'  
  10. ROBOTSTXT_OBEY = True  


 

 

爬取結果

             這里的文件夾是根據分類,然后創建的;

        這是大類的文件夾,現在我們已經將item都爬下來了,就需要存了,這里只想要存內容,所以直接將item里面的content字段的內容寫入txt。

        這里通過將鏈接進行處理,轉換成文件名,最后保存到所屬的那個類里;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM