scrapy startproject 項目名css
cd 項目名html
scrapy genspider 爬蟲名 域名python
class YokaSpider(scrapy.Spider): name = 'yoka' allowed_domains = ['www.yoka.com/fashion/'] start_urls = ['http://www.yoka.com/fashion/'] def parse(self,response): pass
建立的Spider類需繼承scrapy.Spidermysql
name:爬蟲名正則表達式
allowed_domains:容許爬取的域名,不在域名下的請求連接會被過濾掉sql
start_urls:Spider啓動時爬取的url列表,初始請求由它來定義數據庫
parse:默認狀況下, start_urls裏的連接請求完成下載後,返回的響應就會做爲惟一的參數傳遞給這個函數。該方法負責解析返回的響應、提取數據、進一步生成要處理的請求json
Item是保存爬取數據的容器,使用方法和字典相似,不過多了額外的保護機制,能夠避免拼寫錯誤和定義字段錯誤api
建立的Item類需繼承scrapy.Item,並定義類型爲scrapy.Field的字段網絡
class YokadapeiItem(scrapy.Item): text= scrapy.Field() tags=scrapy.Field()
①實例化 item=YokadapeiItem()
②賦值item['text']=... item['tags']=...
③yield item
使用scrapy.Request方法
yield scrapy.Request(url=請求鏈接,callback=回調函數)
scrapy crawl 爬蟲名
scrapy crawl 爬蟲名 -o 文件名.後綴名(json、csv、xml等)
Item生成後,會自動被送到Item Pipeline進行處理
Item Pipeline的做用
①清理HTML數據
②驗證爬取數據,檢查爬取字段
③查重並丟棄重複內容
④將爬取結果保存到數據庫
實現Item Pipeline
①定義一個類並實現process_item()方法 ---必須返回包含數據的字典或Item對象,或拋出DropItem異常
該方法有兩個參數,第一個是item,每次Spider生成的Item都會做爲參數傳過來,第二個是spider,就是Spider的實例
接下來,咱們是實現一個Item Pipeline篩調長度大於25的title
from scrapy.exceptions import DropItem class TestSPipeline(object): def __init__(self): self.limit=25 def process_item(self, item, spider): #判斷該字段是否存在 if item['title']: if len(item['title']) > self.limit: item['title']=item['title'][0:self.limit].rstrip() + '...' return item else: return DropItem("Missing title")
②將處理後的item存入MySQL
建立MysqlPipeline類
import pymsql class MysqlPipeline(object): def __init__(self,mysql_host,mysql_port,mysql_db,mysql_user,mysql_password,mysql_table): self.mysql_host=mysql_host self.mysql_port=mysql_port self.mysql_db=mysql_db self.mysql_table=mysql_table self.mysql_user=mysql_user self.mysql_password=mysql_password #類方法,用classmethod標識,經過參數crawler拿到全局配置的每一個配置信息 #再settings中咱們能夠定義MYSQL_HOST和MYSQL_PORT等來指定MySQL鏈接須要的地址和端口等信息 @classmethod def from_crawler(cls,crawler): return cls( mysql_host=crawler.settings.get('MYSQL_HOST'), mysql_port=crawler.settings.get('PORT'), mysql_db=crawler.settings.get('MYSQL_DB'), mysql_user=crawler.settings.get('MYSQL_USER'), mysql_password=crawler.settings.get('MYSQL_PASSWORD'), mysql_table=crawler.settings.get('MYSQL_TABLE'), ) def open_spider(self,spider): self.conn = pymysql.connect(host=self.mysql_host,port=self.mysql_port, user=self.mysql_user,password=self.mysql_password, database=self.mysql_db,charset='utf8') self.cur=self.conn.cursor() def process_item(self,item,spider): dc=dict(item) for v in dc.values(): sql="insert into %s (title) values ('%s')"%(self.mysql_table,v) self.cur.execute(sql) self.conn.commit() return item def close_spider(self,spider): self.conn.close()
在配置文件settings中
#數字越小越先被調用 ITEM_PIPELINES = { 'test_s.pipelines.TestSPipeline': 300, 'test_s.pipelines.MysqlPipeline':400, } MYSQL_HOST='localhost' MYSQL_PORT='3306' MYSQL_DB='scrapy' MYSQL_TABLE='titles' MYSQL_USER='root' MYSQL_PASSWORD='123456'
xpath、css、正則
屬性:
①name:爬蟲名稱
②allowed_domains:容許爬蟲的域名
③start_urls:起始URL列表,當沒有實現start_requests()時,默認會從這個列表開始抓取
③custom_settings:字典,專屬本Spider的配置,覆蓋項目全局的設置。此設置必須在初始化以前被更新,必須定義成類變量
④crawler:由from_crawler()方法設置的,表明本Spider類對應的Crawler對象,利用它能夠獲取項目的一些配置信息
⑤settings;Settings對象,能夠直接獲取項目的全局設置變量
方法:
①start_requests():生成初始請求,必須返回一個可迭代對象。默認使用start_urls裏的URL來構造Request(GET請求方式),
若想以POST方式訪問某個站點,能夠直接重寫該方法,發送POST請求時使用FormRequest
②parse():當Response沒有指定回調函數時,該方法會默認被調用。該方法需返回一個包含Request或Item的可迭代對象
③closed():當Spider關閉時,該方法會被調用
Scrapy內置了許多Downloader Middleware,被定義在DOWNLOADER_MIDDLEWARES_BASE變量中,
能夠在settings修改DOWNLOADER_MIDDLEWARES以及禁用(將該中間件優先級設置爲None)內置的Downloader Middleware
在整個架構中的位置爲:
①在Request執行下載以前對其進行修改
②在生成Response被Spider解析以前對其進行修改
能夠修改User-Agent、處理重定向、設置代理、失敗重試、設置Cookies等
核心方法有三個:process_request(request,spider)、process_response(request,response,spider)、process_exception(request,exception,spider)
實現至少一個方法,就能夠定義一個Downloader Middleware
在Request從隊列裏調度出來到Downloader下載執行以前,均可以用process_request()方法對Request進行處理
參數:①request:Request對象,即被處理的Request
②spider:Spider對象,即此Request對應的Spider
---返回值必須爲None、Response對象、Request對象 之一,或拋出IgnoreRequest異常
①返回None時,不一樣的Downloader Middleware按照設置的優先級順序依次對Request進行修改,最後送至Downloader執行
②返回Response對象時,更低優先級的Downloader Middleware的process_request()和process_exception()不會繼續調用,每一個Downloader Middleware的process_response()依次被調用,調用完畢後,直接將Response對象發送給Spider來處理
③返回Request對象時,更低優先級的Downloader Middleware的process_request()中止執行,該Request會從新放到調度隊列裏,至關於全新的Request
④IgnoreRequest異常拋出,全部的Downloader Middleware的process_exception()依次執行,若沒有一個方法處理該異常,那麼Request的errorback()方法就會回調。若是該異常尚未被處理,那麼它便會被忽略
參數:①request:Request對象,此Response對應的Request
②response:Response對象,此被處理的Response
③spider:Spider對象,此Response對應的Spider
不一樣的返回狀況:
①返回Request對象時,更低優先級的Downloader Middleware的process_response()不會被調用,該Request會從新放到調度隊列裏,至關於全新的Request
②返回Response對象時,更低優先級的Downloader Middleware的process_response()繼續調用,繼續對該Response對象進行處理
③IgnoreRequest異常拋出,則Request的errorback()方法就會回調。若是該異常尚未被處理,那麼它便會被忽略
參數:①request:Request對象,產生異常的Request
②exception:Exception對象,即拋出的異常
③spider:Spider對象,即Request對應的Spider
不一樣的返回狀況:
①返回爲None時,更低優先級的Downloader Middleware的process_exception()會被繼續調用,直到全部的方法都被調度完畢
②返回Response對象時,更低優先級的Downloader Middleware的process_exception()再也不繼續調用,每一個Downloader Middleware的process_response()轉而被依次調用
③返回Request對象時,更低優先級的Downloader Middleware的process_exception()也再也不繼續調用,該Request會從新放到調度隊列裏,至關於全新的Request
在parse()中能夠用 response.request.headers 查看請求頭信息
如 b'User-Agent': [b'Scrapy/1.5.1 (+https://scrapy.org)'], 使用的Use-Agent是Scrapy/1.5.1 (+https://scrapy.org),它是由Scrapy內置的UserAgentMiddleware設置的
from scrapy import signals class UserAgentMiddleware(object): """This middleware allows spiders to override the user_agent""" def __init__(self, user_agent='Scrapy'): self.user_agent = user_agent @classmethod def from_crawler(cls, crawler): o = cls(crawler.settings['USER_AGENT']) crawler.signals.connect(o.spider_opened, signal=signals.spider_opened) return o def spider_opened(self, spider): self.user_agent = getattr(spider, 'user_agent', self.user_agent) def process_request(self, request, spider): if self.user_agent: request.headers.setdefault(b'User-Agent', self.user_agent)
修改User-Agent有兩種方式①直接修改在settings的USER_AGENT變量 ②經過Downloader Middleware的process_request()來修改
如需設置隨機的User-Agent,須要使用第二種方法
class RandomUserAgentMiddleware(object): def __init__(self): self.user_agents = [ "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)", "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)", "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20", "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1", "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11", "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10" ] def process_request(self, request, spider): request.headers['User-Agent']=random.choice(self.user_agents)
Downloader Middleware組件很是重要,是作異常處理和應對反爬處理的核心。後面將用它來處理代理、Cookies等內容
和Downloader Middleware同樣,Scrapy內置了許多Spider Middleware,被定義在SPIDER_MIDDLEWARES_BASE變量中,
能夠在settings修改SPIDER_MIDDLEWARES,會和SPIDER_MIDDLEWARES_BASE定義的Spider Middleware合併
在整個架構中的位置爲:
①在Response發送給Spider以前對Response進行處理
②在Request發送給Scheduler以前對Request進行處理
③在Item發送給Item Pipeline以前對Item進行處理
核心方法有四個:process_spider_input(response,spider)、process_spider_output(response,result,spider)、process_spider_exception(response,exception,spider)、process_start_request(start_request,spider),實現至少一個方法,就能夠定義一個Spider Middleware
當Response被Spider Middleware處理時,process_spider_input()被調用
參數:①response:Response對象,即被處理的Response
②spider:Spider對象,即該Response對應的Spider
不一樣的返回狀況:
①返回None時,Scrapy將會繼續處理該Response,調用全部其餘的Spider Middleware,直到Spider處理該Response
②拋出異常時,Scrapy將不會調用任何其餘的Spider Middleware的process_spider_input(),而調用Request的errback(),errback的輸出將從新輸入到中間件中,使用process_spider_output()來處理,當其拋出異常時則調用process_spider_exception()來處理
當Spider處理Response返回結果時,process_spider_output()被調用
參數:①response:Response對象,即生成該輸出的Response
②result:包含Request或Item對象的可迭代對象,即Spider返回的結果
③spider:Spider對象,即其結果對應的Spider
該方法必須返回包含Request或Item對象的可迭代對象。
當Spider或Spider Middleware的process_spider_input()拋出異常時,process_spider_exception()被調用
參數:①response:Response對象,即異常被拋出時被處理的Response
②exception:Exception對象,即被拋出的異常
③spider:Spider對象,即拋出該異常的Spider
不一樣的返回狀況:
①返回None時,Scrapy將會繼續處理該異常,調用其餘Spider Middleware中的process_spider_exception(),直到全部的Spider Middleware都被調用
②返回包含Request或Item對象的可迭代對象時,則其餘Spider Middleware中的process_spider_output()被調用,其餘的process_spider_exception()不會被調用
該方法以Spider啓動的Request爲參數時被調用,執行過程相似於process_spider_output(),不過沒有相關聯的Response,而且必須返回Request
參數:①start_request:包含Request的可迭代對象,即Start Request
②spider:Spider對象,即Start Request所屬的Spider
該方法必須返回另外一個包含Request對象的可迭代對象
Spider Middleware的使用頻率不如Downloader Middleware高,在必要的狀況下它能夠用來方便數據的處理
當Spider解析完Response以後,Item就會傳遞到Item Pipeline,被定義的Item Pipeline組件會順次調用。
Item Pipeline的做用:
①清理HTML數據
②驗證爬取數據,檢查爬取字段
③查重並丟棄重複內容
④將爬取結果保存到數據庫
核心方法有四個,必需要實現process_item(item,spider),其餘還有幾個比較實用的方法,open_spider(spider)、close_spider(spider)、from_crawler(cls,crawler)
被定義的Item Pipeline會默認調用該方法對Item進行處理
參數:①item:Item對象,即被處理的Item
②spider:Spider對象,即生成該Item的Spider
不一樣的返回狀況:
①返回Item對象時,此Item會被更低優先級的Item Pipeline的process_item()處理,直到全部的方法被調用完畢
②拋出DropItem異常,那麼此Item會被丟棄,再也不進行處理
該方法實在Spider開啓的時候被自動調用的。咱們能夠在這裏作一些初始化操做,如開啓數據庫鏈接等
參數:spider:被開啓的Spider對象
該方法實在Spider關閉的時候被自動調用的。咱們能夠在這裏作一些收尾工做,如關閉數據庫鏈接等
參數:spider:被關閉的Spider對象
類方法,用@classmethod標識,是一種依賴注入的方式。
參數:①crawler:經過crawler對象,咱們能夠拿到Scrapy的全部核心組件,如全局配置的每一個信息,而後建立一個Pipeline實例
②cls:就是Class
最後返回一個Class實例
CrawlSpider繼承Spider類,除了Spider類的全部屬性和方法,還提供了很是重要的屬性和方法
①rules:爬取規則的屬性,包含一個或多個Rule對象的列表。每一個Rule對爬取網站的動做都作了定義,CrawlSpider會讀取rules的每個Rule並進行解析
②parse_start_url():可重寫的方法。當start_urls裏對應的Request獲得Response時,該方法被調用,它會分析Response並返回Item對象或者Request對象
最重要的是Rule的定義:
scrapy.contrib.spiders下的Rule類
class Rule(object): def __init__(self, link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=identity):
參數:
①link_extractor:Link Extractor對象,經過它提取連接並自動生成Request。它又是一個數據結構,經常使用LxmlLinkExtractor對象做爲參數。
scrapy.linkextractors.lxmlhtml下的LxmlLinkExtractor類
class LxmlLinkExtractor(FilteringLinkExtractor): def __init__(self, allow=(), deny=(), allow_domains=(), deny_domains=(), restrict_xpaths=(), tags=('a', 'area'), attrs=('href',), canonicalize=False, unique=True, process_value=None, deny_extensions=None, restrict_css=(), strip=True):
[1]、allow是正則表達式或正則表達式列表,符合的連接才被跟進,deny則相反
[2]、allow_domains是域名白名單,deny_domains則相反
[3]、restrict_xpaths、restrict_css xpath和css表達式或其列表,用xpath或css提取連接
②callback:回調函數,注意,避免使用parse()做爲回調函數
③cb_kwargs:字典,包含傳遞給回調函數的參數
④follow:布爾值,指定根據該規則從response提取的連接是否須要跟進。若callback爲None,follow默認爲True,不然默認爲False
⑤process_links:指定處理函數,從link_extractor中獲取連接列表時,該函數將會調用,主要用於過濾
⑥process_request:一樣指定處理函數,根據該Rule提取到每一個Request時,該函數都會調用,對Request進行處理。該函數必須返回Request或None
Item提供的是保存抓取數據的容器,Item Loader提供的是填充容器的機制。數據的提取會變得更加規則化。
scrapy.loader下的ItemLoader類
class ItemLoader(object): default_item_class = Item default_input_processor = Identity() default_output_processor = Identity() default_selector_class = Selector def __init__(self, item=None, selector=None, response=None, parent=None, **context):
返回一個新的Item Loader來填充給定的Item,若沒有給出Item,則使用中的類自動實例化default_item_class,用selector、response來使用選擇器或響應參數實例化
參數:
①item:Item對象,能夠調用add_xpath()、add_css()、add_value()等方法來填充Item對象
②selector:Selector對象,用來提取填充數據的選擇器
③response:Response對象,用於使用構造選擇器的Response
本文參考文獻:[1]崔慶才.python3網絡爬蟲開發實戰[M].北京:人民郵電出版社,2018:468-541.