引擎首先會將爬蟲文件中的起始url獲取,而且提交到調度器中。若是須要從url中下載數據,則調度器會將url經過引擎提交給下載器, 下載器根據url去下載指定內容(響應體)。下載好的數據會經過引擎移交給爬蟲文件,爬蟲文件能夠將下載的數據進行指定格式的解析。 若是解析出的數據須要進行持久化存儲,則爬蟲文件會將解析好的數據經過引擎移交給管道進行持久化存儲
Linux: pip3 install scrapy Windows: a. pip3 install wheel b. 下載twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted c. 進入下載目錄,執行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl d. pip3 install pywin32 e. pip3 install scrapy
1、建立項目:scrapy startproject 項目名稱 2、目錄文件功能 scrapy.cfg 項目的主配置信息。(真正爬蟲相關的配置信息在settings.py文件中) items.py 設置數據存儲模板,用於結構化數據,如:Django的Model pipelines 數據持久化處理 settings.py 配置文件,如:遞歸的層數、併發數,延遲下載等 middlewares 中間件設置 spiders 爬蟲目錄,如:建立文件,編寫爬蟲解析規則 3、建立爬蟲應用程序 (1)cd project_name(進入項目目錄) (2)scrapy genspider 應用名稱 爬取網頁的起始url (例如:scrapy genspider qiubai www.qiushibaike.com) 自動生成py文件: import scrapy class FirsttestSpider(scrapy.Spider):#爬蟲類是基於Spider這個父類 name = 'firstTest' #爬蟲文件的名稱 #容許的域名: #allowed_domains = ['www.qiushibaike.com'] #起始url列表:當前的爬蟲文件能夠從該列表中存儲的url中爬取數據 start_urls = ['https://www.qiushibaike.com/text/'] #繼承與父類的方法:用於解析請求到的頁面數據 def parse(self, response): print('haha this is hehe') print(response) #xpath函數的返回值是Selector對象(使用xpath表達式解析出來的內容是被存儲在了Selecotr對象中) #title = response.xpath('//*[@id="qiushi_tag_121076506"]/div[1]/a[2]/h2/text()')[0].extract() #extract系列函數的做用是將Selector中的文本數據取出。 #Selector對象能夠直接調用xpath函數。 title = response.xpath('//*[@id="qiushi_tag_121056271"]/div[1]/a[2]/h2/text()').extract_first() title = response.xpath('//*[@id="qiushi_tag_121056271"]/div[1]/a[2]/h2/text()')[0] print(title) (3)scrapy crawl 應用名稱 #執行程序 4、基本配置 settings文件: (1)假裝請求載體身份 USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36' (2)忽略robots協議 ROBOTSTXT_OBEY = False (3)開啓管道(後面數字指定優先級) ITEM_PIPELINES = { 'firstBlood.pipelines.FirstbloodPipeline': 300, } (4)使用代理ip時中間件設置 SPIDER_MIDDLEWARES = { 'firstBlood.middlewares.FirstbloodSpiderMiddleware': 543, } # 把默認的該成本身定義的類名 :FirstbloodSpiderMiddleware 改爲 MyDaili ---------------------------------- 注:在middlewares文件寫入: class MyDaili(object): def process_request(self,request,spider): #在該方法中設置代理ip request.meta['proxy']='http://120.76.231.27:3128'
spiders文件夾(qiutu.py): import scrapy from qiubai_all.items import QiubaiAllItem class QiutuSpider(scrapy.Spider): name = 'qiutu' #allowed_domains = ['www.qiushibaike.com/pic/'] start_urls = ['http://www.qiushibaike.com/pic/'] #指定一個頁碼通用的url url = 'https://www.qiushibaike.com/pic/page/%d/?s=5127014' pageNum = 1 #控制頁碼 def parse(self, response): div_list = response.xpath('//*[@id="content-left"]/div') for div in div_list: item = QiubaiAllItem() #建立item對象 #使用管道進行持久化存儲的流程: #1.使用爬蟲文件得到解析到的數據 #2.將解析到的數據封裝存儲到items對象中 #3.將封裝好的items對象提交給管道文件 #4.在管道文件中編寫持久化存儲的代碼 #5.在settings中開啓管道 item['author']=div.xpath('.//h2/text()').extract_first() item['content']=div.xpath('.//div[@class="content"]/span/text()').extract_first() yield item #想要對應不一樣頁碼的url發起請求 if self.pageNum <= 35: self.pageNum += 1 #從第二頁發起請求 print('開始爬取第%d頁的數據'%self.pageNum) new_url = format(self.url%self.pageNum) #是新頁碼的url #發起請求 #url:請求的url #callback:回調函數(指定解析數據的規則) yield scrapy.Request(url=new_url,callback=self.parse) items文件: import scrapy class QiubaiAllItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() author = scrapy.Field() content = scrapy.Field() pipelines文件: class QiubaiAllPipeline(object): def __init__(self): self.fp = None def open_spider(self,spider): print('開始爬蟲') self.fp = open('./data.txt','w',encoding='utf-8') def process_item(self, item, spider): #1.獲取item中的數據 self.fp.write(item['author']+':'+item['content']+'\n\n') return item def close_spider(self,spider): print('爬蟲結束') self.fp.close()
spiders文件: import scrapy from xiaohuaPro.items import XiaohuaproItem class XiaohuaSpider(scrapy.Spider): name = 'xiaohua' #allowed_domains = ['www.521609.com/daxuemeinv'] start_urls = ['http://www.521609.com/daxuemeinv/'] url = 'http://www.521609.com/daxuemeinv/list8%d.html' page_num = 1 def parse(self, response): li_list = response.xpath('//*[@id="content"]/div[2]/div[2]/ul/li') for li in li_list: item = XiaohuaproItem() item['img_url'] = li.xpath('./a/img/@src').extract_first() #拼接圖片下載的url item['img_url'] = 'http://www.521609.com'+item['img_url'] item['img_name'] = li.xpath('./a/img/@alt').extract_first() yield item if self.page_num <= 23: self.page_num += 1 url = format(self.url%self.page_num) yield scrapy.Request(url=url,callback=self.parse) items文件: import scrapy class XiaohuaproItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() img_url = scrapy.Field() img_name = scrapy.Field() pipelines文件: import json import urllib.request import os class XiaohuaproPipeline(object): def __init__(self): self.fp = None def open_spider(self,spider): print('開始爬蟲') self.fp = open('./data.json','w',encoding='utf-8') def process_item(self, item, spider): img_dic = { 'img_url':item['img_url'], 'img_name':item['img_name'] } #json.dumps 序列化時對中文默認使用的ascii編碼.想輸出真正的中文須要指定ensure_ascii=False json_string = json.dumps(img_dic,ensure_ascii=False) self.fp.write(json_string) #下載圖片操做 if not os.path.exists('xiaohua'): os.mkdir('xiaohua') filePath='xiaohua/'+item['img_name']+'.png' urllib.request.urlretrieve(url=item['img_url'],filename=filePath) print(filePath+ ':下載成功') return item def close_spider(self,spider): self.fp.close() print('爬蟲結束') #urlretrieve(url, filename=None, reporthook=None, data=None) 有四個參數 #前兩個是下載的地址和保存的路徑 #'參數 reporthook 是一個回調函數,當鏈接上服務器、以及相應的數據塊傳輸完畢時會觸發該回調,咱們能夠利用這個回調函數來顯示當前的下載進度。' \ # '參數 data 指 post 到服務器的數據,該方法返回一個包含兩個元素的(filename, headers)元組,filename 表示保存到本地的路徑,header 表示服務器的響應頭。'
spiders文件: import scrapy class PostdemoSpider(scrapy.Spider): name = 'postDemo' allowed_domains = ['https://fanyi.baidu.com/sug'] #start_urls = ['http://https://fanyi.baidu.com/sug/'] #該方法就是對start_urls列表中的url發起請求 #def start_requests(self): #父類對該方法的默認實現 #for url in self.start_urls: #yield scrapy.Request(url=url,callback=parse) #重寫父類的start_requests方法:該方法默認發起的是get請求 def start_requests(self): post_url = 'https://fanyi.baidu.com/sug/' data = { 'kw':'dog' } #FormRequest該函數用來發起post請求 #Request使用用來發起get請求 yield scrapy.FormRequest(url=post_url,formdata=data,callback=self.parse) def parse(self, response): print(response.text) pipeline文件: class PostproPipeline(object): def process_item(self, item, spider): return item
import scrapy from moviePro.items import MovieproItem class MovieSpider(scrapy.Spider): name = 'movie' #allowed_domains = ['www.id97.com'] start_urls = ['http://www.id97.com/'] #該方法是用來指定二級子頁面的解析規則 def secondPageParse(self,response): #接收Request函數傳遞過來的參數(meta對應字典的key值),此時獲得的item對象即便parse函數中的item= MovieproItem() # 再去item文件中加上二級子頁面的兩個屬性(actor,show_time) item = response.meta['item'] item['actor'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[1]/td[2]/a/text()').extract_first() item['show_time'] = response.xpath('/html/body/div[1]/div/div/div[1]/div[1]/div[2]/table/tbody/tr[7]/td[2]/text()').extract_first() #將item提交給管道 yield item def parse(self, response): div_list = response.xpath('/html/body/div[1]/div[2]/div[1]/div/div') for div in div_list: item = MovieproItem() item['name'] = div.xpath('./div/div[@class="meta"]//a/text()').extract_first() item['kind'] = div.xpath('./div/div[@class="meta"]/div[@class="otherinfo"]//text()').extract() item['kind'] = ''.join(item['kind']) item['url'] = div.xpath('./div/div[@class="meta"]//a/@href').extract_first() #meta={'item':item} 該參數是用來給回調函數進行傳值,指定字典的形式,經過key 傳多個值 yield scrapy.Request(url=item['url'],callback=self.secondPageParse,meta={'item':item})