介: Request類是一個http請求的類,對于爬蟲而言是一個很重要的類。通常在Spider中創建這樣的一個請求,在Downloader中執行這樣的一個請求。同時也有一個子類FormRequest繼承于它,用于post請求。
Request類是一個http請求的類,對于爬蟲而言是一個很重要的類。通常在Spider中創建這樣的一個請求,在Downloader中執行這樣的一個請求。同時也有一個子類FormRequest繼承于它,用于post請求。
在Spider中通常用法:
yield scrapy. Request (url='zarten.com' )
類屬性和方法有:
url method headers body meta copy() replace([url, method, headers, body, cookies, meta, encoding, dont_filter, callback, errback]) Request class scrapy.http.
Request
(url[, callback, method='GET' , headers, body, cookies, meta, encoding='utf-8' , priority=0 , dont_filter=False , errback, flags])
url 請求的url
callback 回調函數,用于接收請求后的返回信息,若沒指定,則默認為parse()函數
method http請求的方式,默認為GET請求,一般不需要指定。若需要POST請求,用FormRequest即可
headers 請求頭信息,一般在settings中設置即可,也可在middlewares中設置
body str類型,為請求體,一般不需要設置(get和post其實都可以通過body來傳遞參數,不過一般不用)
cookies dict或list類型,請求的cookie dict方式(name和value的鍵值對):
cookies={ 'name1' : 'value1' , 'name2' : 'value2' }
list方式:
cookies=[ { 'name' : 'Zarten' , 'value' : 'my name is Zarten' , 'domain' : 'example.com' , 'path' : '/currency' } ]
encoding 請求的編碼方式,默認為'utf-8'
priority int類型,指定請求的優先級,數字越大優先級越高,可以為負數,默認為0
dont_filter 默認為False,若設置為True,這次請求將不會過濾(不會加入到去重隊列中),可以多次執行相同的請求
errback 拋出錯誤的回調函數,錯誤包括404,超時,DNS錯誤等,第一個參數為Twisted Failure實例
from scrapy.spidermiddlewares.httperror import HttpError from twisted.internet.error import DNSLookupError from twisted.internet.error import TimeoutError , TCPTimedOutError class ToScrapeCSSSpider (scrapy. Spider ): name="toscrape-css" # start_urls=[ # 'http://quotes.toscrape.com/', # ] start_urls=[ "http://www.httpbin.org/" , # HTTP 200 expected "http://www.httpbin.org/status/404" , # Not found error "http://www.httpbin.org/status/500" , # server issue "http://www.httpbin.org:12345/" , # non-responding host, timeout expected "http://www.httphttpbinbin.org/" , # DNS error expected ] def start_requests( self ): for u in self .start_urls: yield scrapy. Request (u, callback=self .parse_httpbin, errback=self .errback_httpbin, dont_filter=True ) def parse_httpbin( self , response): self .logger.info( 'Got successful response from {}' .format(response.url)) # do something useful here... def errback_httpbin( self , failure): # log all failures self .logger.info(repr(failure)) # in case you want to do something special for some errors, # you may need the failure's type: if failure.check( HttpError ): # these exceptions come from HttpError spider middleware # you can get the non-200 response response=failure.value.response self .logger.info( 'HttpError錯誤 on %s' , response.url) elif failure.check( DNSLookupError ): # this is the original request request=failure.request self .logger.info( 'DNSLookupError錯誤 on %s' , request.url) elif failure.check( TimeoutError , TCPTimedOutError ): request=failure.request self .logger.info( 'TimeoutError錯誤 on %s' , request.url)
flags list類型,一般不會用到,發送請求的標志,一般用于日志記錄
meta 可用戶自定義從Request到Response傳遞參數,這個參數一般也可在middlewares中處理
yield scrapy. Request (url='zarten.com' , meta={ 'name' : 'Zarten' })
在Response中:
my_name=response.meta[ 'name' ]
不過也有scrapy內置的特殊key,也非常有用,它們如下:
proxy 設置代理,一般在middlewares中設置
可以設置http或https代理
request.meta[ 'proxy' ]='https://' + 'ip:port'
downloadtimeout 設置請求超時等待時間(秒),通常在settings中設置DOWNLOADTIMEOUT,默認是180秒(3分鐘)
maxretrytimes 最大重試次數(除去第一次下載),默認為2次,通常在settings中 RETRY_TIMES設置
dont_redirect 設為True后,Request將不會重定向
dont_retry 設為True后,對于http鏈接錯誤或超時的請求將不再重試請求
handlehttpstatuslist http返回碼200-300之間都是成功的返回,超出這個范圍的都是失敗返回,scrapy默認是過濾了這些返回,不會接收這些錯誤的返回進行處理。不過可以自定義處理哪些錯誤返回:
yield scrapy. Request (url='https://httpbin.org/get/zarten' , meta={ 'handle_httpstatus_list' : [ 404 ]})
在parse函數中可以看到處理404錯誤:
def parse( self , response): print ( '返回信息為:' ,response.text)
handlehttpstatusall 設為True后,Response將接收處理任意狀態碼的返回信息
dontmergecookies scrapy會自動保存返回的cookies,用于它的下次請求,當我們指定了自定義cookies時,如果我們不需要合并返回的cookies而使用自己指定的cookies,可以設為True
cookiejar 可以在單個spider中追蹤多個cookie,它不是粘性的,需要在每次請求時都帶上
def start_requests( self ): urls=[ 'http://quotes.toscrape.com/page/1' , 'http://quotes.toscrape.com/page/3' , 'http://quotes.toscrape.com/page/5' , ] for i ,url in enumerate(urls): yield scrapy. Request (url=url, meta={ 'cookiejar' : i}) def parse( self , response): next_page_url=response.css( "li.next > a::attr(href)" ).extract_first() if next_page_url is not None : yield scrapy. Request (response.urljoin(next_page_url), meta={ 'cookiejar' : response.meta[ 'cookiejar' ]}, callback=self .parse_next) def parse_next( self , response): print ( 'cookiejar:' , response.meta[ 'cookiejar' ])
dont_cache 設為True后,不會緩存
redirect_urls 暫時還不清楚具體的作用,知道的小伙伴們歡迎在評論留言
bindaddress 綁定輸出IP
dontobeyrobotstxt 設為True,不遵守robots協議,通常在settings中設置
downloadmaxsize 設置下載器最大下載的大小(字節),通常在settings中設置DOWNLOADMAXSIZE,默認為1073741824 (1024MB=1G),若不設置最大的下載限制,設為0
download_latency 只讀屬性,獲取請求的響應時間(秒)
def start_requests( self ): headers={ 'user-agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36' } yield scrapy. Request (url='https://www.amazon.com' , headers=headers) def parse( self , response): print ( '響應時間為:' , response.meta[ 'download_latency' ])
downloadfailon_dataloss 很少用到,詳情看這里
referrer_policy 設置Referrer Policy
FormRequest
FormRequest 類為Request的子類,用于POST請求
這個類新增了一個參數 formdata,其他參數與Request一樣,詳細可參考上面的講述
yield scrapy. FormRequest (url="http://www.example.com/post/action" , formdata={ 'name' : 'Zarten' , 'age' : '27' }, callback=self .after_post)
點擊“了解更多”看源代碼,建議收藏
得十多年前,自己還是個高中生的時候,所謂的智能手機還完全沒有普及,如果想在學校里面大量閱讀電子書的話,基本上靠的就是有閱讀 功能的MP3或者MP4了。而電子書的來源呢?在無法隨時隨地接觸網絡的情況下,有時靠的就是笨辦法:將一些小說網站上的內容一頁頁的粘貼復制下來。而那些動輒幾百章節的網絡小說,靠這樣的手工操作,確實讓人非常頭疼。那時候是多么希望有一個工具能幫我自動完成這些吃力的手工活啊?。。?/p>
好吧,言歸正傳,最近在研究怎么使用爬蟲框架Scrapy。先說說想要學習Scrapy的初衷吧。
Scrapy是Python開發的一個快速、高層次的屏幕抓取和web抓取框架,用于抓取web站點并從頁面中提取結構化的數據。Scrapy用途廣泛,可以用于數據挖掘、監測和自動化測試(百度百科上的介紹)。
經過幾天的學習,Scrapy的初步使用,首先需要了解的就是如下幾個概念了:
所以,你需要做得就是寫好上面提到的四個類,剩下的只要交給Scrapy框架就可以了。
可以先創建一個scrapy項目:
scrapy startproject getMyFavoritePages
文件spiderForShortPageMsg.py里面就是我們要寫的 Spiders子類了。
舉例:現在我想要將網站https://lobste.rs/中所有文章的標題和文章的地址抓取下來。
第一步:寫一個繼承自 Spiders的類
Scrapy框架會自動調用該類的方法parse(),在這里parse()最后調用了自定義的方法parse_lobste_com()來解析具體的html頁面,并從中找到我想要的數據,然后保存于一個 Items的數據類對象當中。
不要被下面的這行代碼嚇到:
response.xpath("http://div/div[2]/span[1]/a[@class='u-url']"
它就是之前提到的 Selectors。這就是用來定位你想要查找的html標簽的方法。有倆種 Selectors, 分別是 XPath Selectors 和 CSS Selectors,上面都有用到。
這是我的Item數據類(即上面的pageItem)。
第二步:在Item Pipeline中定義你想要對數據類Item進行的所有操作。
現在想要的數據已經在Item對象當中了??紤]到自己的最終目的,最好的選擇當然是把所有的數據都保存在數據庫當中了。
而說到數據庫的操作,就不得不提Django中的models類了,通過幾步簡單的設置,你可以直接調用Django中的models類,進而省去復雜了數據庫操作,簡直不要太省心了。誰用誰知道啊!!
代碼寫好,程序開始運行...
注意!只有當調度器中不存在任何request了,整個程序才會停止,(也就是說,對于下載失敗的URL,Scrapy也會重新下載。)
制作 Scrapy 爬蟲 一共需要4步:
Scrapy框架官方網址:http://doc.scrapy.org/en/latest
Scrapy中文維護站點:http://scrapy-chs.readthedocs.io/zh_CN/latest/index.html
安裝后,只要在命令終端輸入 scrapy,提示類似以下結果,代表已經安裝成功
具體Scrapy安裝流程參考:http://doc.scrapy.org/en/latest/intro/install.html#intro-install-platform-notes 里面有各個平臺的安裝方法
scrapy startproject mySpider
下面來簡單介紹一下各個主要文件的作用:
scrapy.cfg :項目的配置文件
mySpider/ :項目的Python模塊,將會從這里引用代碼
mySpider/items.py :項目的目標文件
mySpider/pipelines.py :項目的管道文件
mySpider/settings.py :項目的設置文件
mySpider/spiders/ :存儲爬蟲代碼目錄
我們打算抓?。篽ttp://www.itcast.cn/channel/teacher.shtml 網站里的所有講師的姓名、職稱和個人信息。
import scrapy
class ItcastItem(scrapy.Item):
name=scrapy.Field()
level=scrapy.Field()
info=scrapy.Field()
爬蟲功能要分兩步:
scrapy genspider itcast "itcast.cn"
import scrapy
class ItcastSpider(scrapy.Spider):
name="itcast"
allowed_domains=["itcast.cn"]
start_urls=(
'http://www.itcast.cn/',
)
def parse(self, response):
pass
其實也可以由我們自行創建itcast.py并編寫上面的代碼,只不過使用命令可以免去編寫固定代碼的麻煩
要建立一個Spider, 你必須用scrapy.Spider類創建一個子類,并確定了三個強制的屬性 和 一個方法。
將start_urls的值修改為需要爬取的第一個url
start_urls=("http://www.itcast.cn/channel/teacher.shtml",)
修改parse()方法
def parse(self, response):
with open("teacher.html", "w") as f:
f.write(response.text)
然后運行一下看看,在mySpider目錄下執行:
scrapy crawl itcast
是的,就是 itcast,看上面代碼,它是 ItcastSpider 類的 name 屬性,也就是使用 scrapy genspider命令的爬蟲名。
一個Scrapy爬蟲項目里,可以存在多個爬蟲。各個爬蟲在執行時,就是按照 name 屬性來區分。
運行之后,如果打印的日志出現 [scrapy] INFO: Spider closed (finished),代表執行完成。 之后當前文件夾中就出現了一個 teacher.html 文件,里面就是我們剛剛要爬取的網頁的全部源代碼信息。
# 注意,Python2.x默認編碼環境是ASCII,當和取回的數據編碼格式不一致時,可能會造成亂碼;
# 我們可以指定保存內容的編碼格式,一般情況下,我們可以在代碼最上方添加:
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
# 這三行代碼是Python2.x里解決中文編碼的萬能鑰匙,經過這么多年的吐槽后Python3學乖了,默認編碼是Unicode了...(祝大家早日擁抱Python3)
<div class="li_txt">
<h3> xxx </h3>
<h4> xxxxx </h4>
<p> xxxxxxxx </p>
是不是一目了然?直接上XPath開始提取數據吧。
from mySpider.items import ItcastItem
from mySpider.items import ItcastItem
def parse(self, response):
#open("teacher.html","wb").write(response.body).close()
# 存放老師信息的集合
items=[]
for each in response.xpath("//div[@class='li_txt']"):
# 將我們得到的數據封裝到一個 `ItcastItem` 對象
item=ItcastItem()
#extract()方法返回的都是unicode字符串
name=each.xpath("h3/text()").extract()
title=each.xpath("h4/text()").extract()
info=each.xpath("p/text()").extract()
#xpath返回的是包含一個元素的列表
item['name']=name[0]
item['title']=title[0]
item['info']=info[0]
items.append(item)
# 直接返回最后數據
return items
# json格式,默認為Unicode編碼
scrapy crawl itcast -o teachers.json
# json lines格式,默認為Unicode編碼
scrapy crawl itcast -o teachers.jsonl
# csv 逗號表達式,可用Excel打開
scrapy crawl itcast -o teachers.csv
# xml格式
scrapy crawl itcast -o teachers.xml
*請認真填寫需求信息,我們會在24小時內與您取得聯系。