1. 程式人生 > >scrapy爬蟲流程

scrapy爬蟲流程

scrapy 爬蟲學習

一、scrapy
Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 其可以應用在數據挖掘,信息處
理或存儲歷史數據等一系列的程序中。其最初是為了頁面抓取 (更確切來說, 網絡抓取 )所設計的, 也
可以應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。
Scrapy用途廣泛,可以用於數據挖掘、監測和自動化測試。

Scrapy 使用了 Twisted異步網絡庫來處理網絡通訊。整體架構大致如下:

技術分享

Scrapy主要包括了以下組件:
    1.引擎(Scrapy)
    用來處理整個系統的數據流處理, 觸發事務(框架核心)
    
    2.調度器(Scheduler)
    用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓
    取網頁的網址或者說是鏈接)的優先隊列, 由它來決定下一個要抓取的網址是什麽, 同時去除重復
    的網址
    
    3.下載器(Downloader)
    用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的異步模型
    上的)
    
    4.爬蟲(Spiders)
    爬蟲是主要幹活的, 用於從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以
    從中提取出鏈接,讓Scrapy繼續抓取下一個頁面
    
    5.項目管道(Pipeline)
    負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的
    信息。當頁面被爬蟲解析後,將被發送到項目管道,並經過幾個特定的次序處理數據
    
    6.下載器中間件(Downloader Middlewares)
    位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應
    
    7.爬蟲中間件(Spider Middlewares)
    介於Scrapy引擎和爬蟲之間的框架,主要工作是處理蜘蛛的響應輸入和請求輸出
    
    8.調度中間件(Scheduler Middewares)
    介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應
    
Scrapy運行流程大概如下:
1.引擎從調度器中取出一個鏈接(URL)用於接下來的抓取
2.引擎把URL封裝成一個請求(Request)傳給下載器
3.下載器把資源下載下來,並封裝成應答包(Response)
4.爬蟲解析Response
5.解析出實體(Item),則交給實體管道進行進一步的處理
6.解析出的是鏈接(URL),則把URL交給調度器等待抓取


二、安裝
1. linux
#pip3 install scrapy

2.windows
a. pip3 install wheel
b. 下載twisted 
c. 進入下載目錄,執行 pip3 install Twisted17.1.0cp35cp35mwin_amd64.whl 
d. pip3 install scrapy
e. 下載並安裝pywin32:



三、基本命令
1. scrapy startproject 項目名稱 
    - 在當前目錄中創建中創建一個項目文件(類似於Django)
 
2.scrapy genspider [-t template] <name> <domain>
    - 創建爬蟲應用
    scrapy gensipider -t basic oldboy oldboy.com
    scrapy gensipider -t xmlfeed autohome autohome.com.cn
    查看所有命令:scrapy gensipider -l
    查看模板命令:scrapy gensipider -d 模板名稱
    
3. scrapy list
    - 展示爬蟲應用列表
    
4. scrapy crawl 爬蟲應用名稱
    - 運行單獨爬蟲應用
    
5.項目結構以及爬蟲應用簡介
project_name/
   scrapy.cfg
   project_name/
       __init__.py
       items.py
       pipelines.py
       settings.py
       spiders/
           __init__.py
           爬蟲1.py
           爬蟲2.py
           爬蟲3.py
           
文件說明:
scrapy.cfg  項目的主配置信息。(真正爬蟲相關的配置信息在settings.py文件中)
items.py    設置數據存儲模板,用於結構化數據,如:Django的Model
pipelines    數據處理行為,如:一般結構化的數據持久化
settings.py 配置文件,如:遞歸的層數、並發數,延遲下載等
spiders      爬蟲目錄,如:創建文件,編寫爬蟲規則

註意:一般創建爬蟲文件時,以網站域名命名
爬蟲文件oldboy.py例子:
import scrapy

class XiaoHuarSpider(scrapy.spiders.Spider):
    name = "xiaohuar"
    allowed_domains = ["xiaohuar.com"]
    start_urls = [
        "http://www.xiaohuar.com/hua/",
    ]

    def parse(self,response):
        print(response.text)
        
註意windows編碼: 
import sys,os
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding=‘gb18030‘)

四、項目示例
import scrapy
from scrapy.selector import HtmlXPathSelector
from scrapy.http.request import Request

class DigSpider(scrapy.Spider):
    name = "dig"

    allowed_domains = ["chouti.com"]
    start_urls = [
        ‘http://dig.chouti.com‘,
    ]

    has_request_set = {}
    def parse(self, response):
        print(response.url)
        hxs = HtmlXPathSelector(response)
        page_list = hxs.select(‘//div[@id="dig_lcpage"]//a[re:test(@href, "/all/hot/recent/\d+")]/@href‘).extract()
        for page in page_list:
            page_url = ‘http://dig.chouti.com{0}‘.format(page)
            key = self.md5(page_url)
            if key in self.has_request_set:
                pass
            else:
                self.has_request_set[key] = page_url
                obj = Request(url=page_url, method=‘GET‘,callback=self.parse)
                yield obj

    @staticmethod
    def md5(val):
        import hashlib
        ha = hashlib.md5()
        ha.update(bytes(val, encoding=‘utf-8‘))
        key = ha.hexdigest()
        return key
        
 執行命令: scrapy crawl dig --nolog
 
 Request是一個封裝用戶請求的類,在回調函數中yield該對象表示繼續訪問
 HtmlXpathSelector用於結構化HTML代碼並提供選擇器功能
 

 登錄知乎:
 import scrapy
from scrapy.selector import HtmlXPathSelector
from scrapy.http.request import Request
from scrapy.http.cookies import CookieJar
from scrapy import FormRequest


class ChouTiSpider(scrapy.Spider):
    # 爬蟲應用的名稱,通過此名稱啟動爬蟲命令
    name = "chouti"
    # 允許的域名
    allowed_domains = ["chouti.com"]

    cookie_dict = {}
    has_request_set = {}

    def start_requests(self):
        url = ‘http://dig.chouti.com/‘
        # return [Request(url=url, callback=self.login)]
        yield Request(url=url, callback=self.login)

    def login(self, response):
        cookie_jar = CookieJar()
        cookie_jar.extract_cookies(response, response.request)
        for k, v in cookie_jar._cookies.items():
            for i, j in v.items():
                for m, n in j.items():
                    self.cookie_dict[m] = n.value

        req = Request(
            url=‘http://dig.chouti.com/login‘,
            method=‘POST‘,
            headers={‘Content-Type‘: ‘application/x-www-form-urlencoded; charset=UTF-8‘},
            body=‘phone=xxxxxxxx&password=xxxxxx&oneMonth=1‘,
            cookies=self.cookie_dict,
            callback=self.check_login
        )
        yield req

    def check_login(self, response):
        req = Request(
            url=‘http://dig.chouti.com/‘,
            method=‘GET‘,
            callback=self.show,
            cookies=self.cookie_dict,
            dont_filter=True
        )
        yield req

    def show(self, response):
        # print(response)
        hxs = HtmlXPathSelector(response)
        news_list = hxs.select(‘//div[@id="content-list"]/div[@class="item"]‘)
        for new in news_list:
            # temp = new.xpath(‘div/div[@class="part2"]/@share-linkid‘).extract()
            link_id = new.xpath(‘*/div[@class="part2"]/@share-linkid‘).extract_first()
            yield Request(
                url=‘http://dig.chouti.com/link/vote?linksId=%s‘ %(link_id,),
                method=‘POST‘,
                cookies=self.cookie_dict,
                callback=self.do_favor
            )

        page_list = hxs.select(‘//div[@id="dig_lcpage"]//a[re:test(@href, "/all/hot/recent/\d+")]/@href‘).extract()
        for page in page_list:

            page_url = ‘http://dig.chouti.com%s‘ % page
            import hashlib
            hash = hashlib.md5()
            hash.update(bytes(page_url,encoding=‘utf-8‘))
            key = hash.hexdigest()
            if key in self.has_request_set:
                pass
            else:
                self.has_request_set[key] = page_url
                yield Request(
                    url=page_url,
                    method=‘GET‘,
                    callback=self.show
                )

    def do_favor(self, response):
        print(response.text) 
        
 註: settings.py中設置DEPTH_LIMIT = 1來指定“遞歸”的層數


本文出自 “linux技術” 博客,請務必保留此出處http://haoyonghui.blog.51cto.com/4278020/1976482

scrapy爬蟲流程