網絡爬蟲(又被稱爲網頁蜘蛛,網絡機器人,在FOAF社區中間,更常常的稱爲網頁追逐者),是一種按照必定的規則,自動地抓取萬維網信息的程序或者腳本。另一些不常使用的名字還有螞蟻、自動索引、模擬程序或者蠕蟲。html
Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 其能夠應用在數據挖掘,信息處理或存儲歷史數據等一系列的程序中。python
其最初是爲了頁面抓取 (更確切來講, 網絡抓取 )所設計的, 也能夠應用在獲取API所返回的數據(例如 Amazon Associates Web Services ) 或者通用的網絡爬蟲。Scrapy用途普遍,能夠用於數據挖掘、監測和自動化測試。正則表達式
Scrapy 使用了 Twisted異步網絡庫來處理網絡通信。總體架構大體以下網絡
Scrapy主要包括瞭如下組件:
引擎(Scrapy)
用來處理整個系統的數據流處理, 觸發事務(框架核心)
調度器(Scheduler)
用來接受引擎發過來的請求, 壓入隊列中, 並在引擎再次請求的時候返回. 能夠想像成一個URL(抓取網頁的網址或者說是連接)的優先隊列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址
下載器(Downloader)
用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是創建在twisted這個高效的異步模型上的)
爬蟲(Spiders)
爬蟲是主要幹活的, 用於從特定的網頁中提取本身須要的信息, 即所謂的實體(Item)。用戶也能夠從中提取出連接,讓Scrapy繼續抓取下一個頁面
項目管道(Pipeline)
負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證明體的有效性、清除不須要的信息。當頁面被爬蟲解析後,將被髮送到項目管道,並通過幾個特定的次序處理數據。
下載器中間件(Downloader Middlewares)
位於Scrapy引擎和下載器之間的框架,主要是處理Scrapy引擎與下載器之間的請求及響應。
爬蟲中間件(Spider Middlewares)
介於Scrapy引擎和爬蟲之間的框架,主要工做是處理蜘蛛的響應輸入和請求輸出。
調度中間件(Scheduler Middewares)
介於Scrapy引擎和調度之間的中間件,從Scrapy引擎發送到調度的請求和響應。
Scrapy運行流程大概以下: 架構
1、安裝併發
1 pip install Scrapy
自動建立目錄:框架
project_name/ scrapy.cfg project_name/ __init__.py items.py pipelines.py settings.py spiders/ __init__.py
文件說明:dom
注意:通常建立爬蟲文件時,以網站域名命名異步
二、編寫爬蟲scrapy
在spiders目錄中新建 xiaohuar_spider.py 文件
#!/usr/bin/env python # -*- coding:utf-8 -*- import scrapy class XiaoHuarSpider(scrapy.spiders.Spider): name = "nnnnn" # 命名 # allowed_domains = ["xiaohuar.com"] start_urls = [ # 起始url 內部是for循環 "http://www.xiaohuar.com/hua/", ] #response 裏面封裝着全部返回的數據 def parse(self, response): # 回調函數 # print(response, type(response)) # from scrapy.http.response.html import HtmlResponse # print(response.body_as_unicode()) current_url = response.url # 當前請求的url body = response.body # 當前返回的內容 unicode_body = response.body_as_unicode() # 編碼 print body
三、運行
進入project_name目錄,運行命令
scrapy crawl spider_name --nolog
四、遞歸的訪問
以上的爬蟲僅僅是爬去初始頁,而咱們爬蟲是須要源源不斷的執行下去,直到全部的網頁被執行完畢
#!/usr/bin/env python # -*- coding:utf-8 -*- import scrapy from scrapy.http import Request from scrapy.selector import HtmlXPathSelector import re import urllib import os class XiaoHuarSpider(scrapy.spiders.Spider): name = "xiaohuar" allowed_domains = ["xiaohuar.com"] start_urls = [ "http://www.xiaohuar.com/list-1-1.html", ] def parse(self, response): # 分析頁面 # 找到頁面中符合規則的內容(校花圖片),保存 # 找到全部的a標籤,再訪問其餘a標籤,一層一層的搞下去 hxs = HtmlXPathSelector(response) # 若是url是 http://www.xiaohuar.com/list-1-\d+.html if re.match('http://www.xiaohuar.com/list-1-\d+.html', response.url): items = hxs.select('//div[@class="item_list infinite_scroll"]/div') for i in range(len(items)): src = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/a/img/@src' % i).extract() name = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/span/text()' % i).extract() school = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/div[@class="btns"]/a/text()' % i).extract() if src: ab_src = "http://www.xiaohuar.com" + src[0] file_name = "%s_%s.jpg" % (school[0].encode('utf-8'), name[0].encode('utf-8')) file_path = os.path.join("/Users/wupeiqi/PycharmProjects/beauty/pic", file_name) urllib.urlretrieve(ab_src, file_path) # 獲取全部的url,繼續訪問,並在其中尋找相同的url all_urls = hxs.select('//a/@href').extract() for url in all_urls: if url.startswith('http://www.xiaohuar.com/list-1-'): yield Request(url, callback=self.parse)
以上代碼將符合規則的頁面中的圖片保存在指定目錄,而且在HTML源碼中找到全部的其餘 a 標籤的href屬性,從而「遞歸」的執行下去,直到全部的頁面都被訪問過爲止。以上代碼之因此能夠進行「遞歸」的訪問相關URL,關鍵在於parse方法使用了 yield Request對象。
注:能夠修改settings.py 中的配置文件,以此來指定「遞歸」的層數,如: DEPTH_LIMIT = 1 深度
兩種定義查找的方式:
1, 即將過時的
from scrapy.selector import HtmlXPathSelector hxs = HtmlXPathSelector(response) # 即將過時了 items = hxs.select('//div[@class="item_list infinite_scroll"]/div')
2,建議使用
from scrapy.selector import Selector # 推薦使用這一種 ret = Selector(response=response).xpath('//div[@class="item_listinfinite_scroll"]/div')
3, 選擇器規則
selector: // 子子孫孫 / 孩子 //div[@class='c1'][@id='i1'] 屬性選擇器 //div//img/@src 獲取src屬性 //div//a[1] 索引 第一個 //div//a[1]//text() 內容 ----- obj.extract() 真實的內容 ===== 正則表達式 //.select('div//a[1]').re('暱稱:(\w+)') <li class="item-"><a href="link.html">first item</a></li> <li class="item-0"><a href="link1.html">first item</a></li> <li class="item-1"><a href="link2.html">second item</a></li> '//li[re:test(@class, "item-\d*")]//@href'
重複url 不訪問 url加密 -》 集合set nid 加密值(索引) 原來的的值 new_url ==> 加密 如何遞歸 DEPTH_LIMIT = 1 深度 from scrapy.selector import Selector url_list = Selector(response=response).xpath('//a/#href') for url in url_list: # DEPTH_LIMIT = 1 深度 yield scrapy.Request(url=url,callback=self.parse)
內容格式化
1,yiled request() 交給下載器
#!/usr/bin/python # -*- coding: UTF-8 -*- #!/usr/bin/env python # -*- coding:utf-8 -*- import scrapy import urllib import os class XiaoHuarSpider(scrapy.spiders.Spider): name = "s2" # 命名 # allowed_domains = ["xiaohuar.com"] start_urls = [ # 起始url 內部是for循環 "http://www.xiaohuar.com/hua/", ] def parse(self, response): # 回調函數 current_url = response.url # 當前請求的url body = response.body # 當前返回的內容 unicode_body = response.body_as_unicode() # 編碼 # 去body中獲取全部url from scrapy.selector import Selector url_list = Selector(response=response).xpath('//a/#href') for url in url_list: # DEPTH_LIMIT = 1 深度 yield scrapy.Request(url=url,callback=self.parse)
2, yiled item() 交給 pipeline
#!/usr/bin/env python # -*- coding:utf-8 -*- import scrapy import urllib import os class XiaoHuarSpider(scrapy.spiders.Spider): name = "s2" # 命名 # allowed_domains = ["xiaohuar.com"] start_urls = [ # 起始url 內部是for循環 "http://www.xiaohuar.com/hua/", ] #response 裏面封裝着全部返回的數據 def parse(self, response): # 回調函數 # print(response, type(response)) # from scrapy.http.response.html import HtmlResponse # print(response.body_as_unicode()) current_url = response.url # 當前請求的url from scrapy.selector import HtmlXPathSelector hxs = HtmlXPathSelector(response) # 即將過時了 items = hxs.select('//div[@class="item_list infinite_scroll"]/div') for i in range(len(items)): # extract() 拿裏面真實的東西 srcs = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/a/img/@src' % i).extract() names = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/span/text()' % i).extract() schools = hxs.select('//div[@class="item_list infinite_scroll"]/div[%d]//div[@class="img"]/div[@class="btns"]/a/text()' % i).extract() print names,srcs,schools if srcs and names and schools: print names[0],schools[0],srcs[0] try: from spider1 import items obj = items.Spider1Item() obj['name'] = names[0] obj['src'] = srcs[0] obj['school'] = schools[0] yield obj except Exception as e: print e # ret = [/uhdsjdnsd] # print ret uicod的表示 # print ret[0] 字符串
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # http://doc.scrapy.org/en/latest/topics/items.html import scrapy class Spider1Item(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() name = scrapy.Field() src = scrapy.Field() school = scrapy.Field()
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html class Spider1Pipeline(object): def process_item(self, item, spider): ab_src = "http://www.xiaohuar.com" + item['src'] # 前綴 file_name = item['name'].encode('utf-8') + '.jpg' import os import urllib file_path = os.path.join('D:\\',file_name) # file_name = "%s_%s.jpg" % (schools[0].encode('utf-8'), names[0].encode('utf-8')) # file_path = os.path.join("/Users/wupeiqi/PycharmProjects/beauty/pic", file_name) urllib.urlretrieve(ab_src, file_path) # 保存 地址和 路勁 return item
生命流程圖