第一次使用Scrapy框架遇到不少坑,堅持去搜索,修改代碼就能夠解決問題。此次爬取的是一個鬥圖網站的最新表情圖片www.doutula.com/photo/list,練習使用Scrapy框架而且使用的隨機user agent防止被ban,鬥圖表情包每日更新,一共能夠抓取5萬張左右的表情到硬盤中。爲了節省時間我就抓取了1萬多張。html
Scrapy是一個爲了爬取網站數據,提取結構性數據而編寫的應用框架。 能夠應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。git
使用過程github
- 建立一個Scrapy項目
- 定義提取的Item
- 編寫爬取網站的 spider 並提取 Item
- 編寫 Item Pipeline 來存儲提取到的Item(即數據)
接下來的圖表展示了Scrapy的架構,包括組件及在系統中發生的數據流的概覽(綠色箭頭所示)。 下面對每一個組件都作了簡單介紹,並給出了詳細內容的連接。數據流以下所描述數據庫
組件服務器
Scrapy Engine
引擎負責控制數據流在系統中全部組件中流動,並在相應動做發生時觸發事件。 詳細內容查看下面的數據流(Data Flow)部分。cookie
調度器(Scheduler)
調度器從引擎接受request並將他們入隊,以便以後引擎請求他們時提供給引擎。架構
下載器(Downloader)
下載器負責獲取頁面數據並提供給引擎,然後提供給spider。併發
Spiders
Spider是Scrapy用戶編寫用於分析response並提取item(即獲取到的item)或額外跟進的URL的類。 每一個spider負責處理一個特定(或一些)網站。 更多內容請看 Spiders 。框架
Item Pipeline
Item Pipeline負責處理被spider提取出來的item。典型的處理有清理、 驗證及持久化(例如存取到數據庫中)。 更多內容查看 Item Pipeline 。dom
下載器中間件(Downloader middlewares)
下載器中間件是在引擎及下載器之間的特定鉤子(specific hook),處理Downloader傳遞給引擎的response。 其提供了一個簡便的機制,經過插入自定義代碼來擴展Scrapy功能。更多內容請看 下載器中間件(Downloader Middleware) 。
Spider中間件(Spider middlewares)
Spider中間件是在引擎及Spider之間的特定鉤子(specific hook),處理spider的輸入(response)和輸出(items及requests)。 其提供了一個簡便的機制,經過插入自定義代碼來擴展Scrapy功能。更多內容請看 Spider中間件(Middleware) 。
1.從網站的主頁進入最新鬥圖表情後網址是https://www.doutula.com/photo/list/ ,點擊第二頁後看到網址變成了https://www.doutula.com/photo/list/?page=2 ,那咱們就知道了網址的構成最後的page就是不一樣的頁數。那麼spider中的start_urls開始入口就以下定義,爬取1到20頁的圖片表情。想下載更多表情頁數你能夠再增長。
start_urls = ['https://www.doutula.com/photo/list/?page={}'.format(i) for i in range(1, 20)]
2.進入開發者模式分析網頁結構,能夠看到以下結構。右擊複製一下xpath地址便可獲得所有的表情所在的a標籤內容。a[1]表示第一個a,去掉[1]就是所有的a。
//*[@id="pic-detail"]/div/div[1]/div[2]/a
值得注意的是這裏的表情有兩種:一個jpg,一個gif動圖。若是獲取圖片地址時只抓取a標籤下面第一個img的src就會出錯,因此咱們要抓取img中的含有data-original的值。這裏a標籤下面還一個p標籤是圖片簡介,咱們也抓取下來做爲圖片文件的名稱。
圖片的鏈接是 'http:' + content.xpath('//img/@data-original') 圖片的名稱是 content.xpath('//p/text()')
完整代碼地址 github.com/rieuse/learnPython
1.首先使用命令行工具輸入代碼建立一個新的Scrapy項目,以後建立一個爬蟲。
scrapy startproject ScrapyDoutu cd ScrapyDoutu\ScrapyDoutu\spiders scrapy genspider doutula doutula.com
2.打開Doutu文件夾中的items.py,改成如下代碼,定義咱們爬取的項目。
import scrapy class DoutuItem(scrapy.Item): img_url = scrapy.Field() name = scrapy.Field()
3.打開spiders文件夾中的doutula.py,改成如下代碼,這個是爬蟲主程序。
# -*- coding: utf-8 -*- import os import scrapy import requests from ScrapyDoutu.items import DoutuItems class Doutu(scrapy.Spider): name = "doutu" allowed_domains = ["doutula.com", "sinaimg.cn"] start_urls = ['https://www.doutula.com/photo/list/?page={}'.format(i) for i in range(1, 40)] # 咱們暫且爬取40頁圖片 def parse(self, response): i = 0 for content in response.xpath('//*[@id="pic-detail"]/div/div[1]/div[2]/a'): i += 1 item = DoutuItems() item['img_url'] = 'http:' + content.xpath('//img/@data-original').extract()[i] item['name'] = content.xpath('//p/text()').extract()[i] try: if not os.path.exists('doutu'): os.makedirs('doutu') r = requests.get(item['img_url']) filename = 'doutu\\{}'.format(item['name']) + item['img_url'][-4:] with open(filename, 'wb') as fo: fo.write(r.content) except: print('Error') yield item
3.這裏面有不少值得注意的部分:
content.xpath('//img/@data-original').extract()[i]
中extract()用來返回一個list(就是系統自帶的那個) 裏面是一些你提取的內容,[i]是結合前面的i的循環每次獲取下一個標籤內容,若是不這樣設置,就會把所有的標籤內容放入一個字典的值中。filename = 'doutu\{}'.format(item['name']) + item['img_url'][-4:]
是用來獲取圖片的名稱,最後item['img_url'][-4:]是獲取圖片地址的最後四位這樣就能夠保證不一樣的文件格式使用各自的後綴。4.配置settings.py,若是想抓取快一點CONCURRENT_REQUESTS設置大一些,DOWNLOAD_DELAY設置小一些,或者爲0.
# -*- coding: utf-8 -*- BOT_NAME = 'ScrapyDoutu' SPIDER_MODULES = ['ScrapyDoutu.spiders'] NEWSPIDER_MODULE = 'ScrapyDoutu.spiders' DOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None, 'ScrapyDoutu.middlewares.RotateUserAgentMiddleware': 400, } ROBOTSTXT_OBEY = False # 不遵循網站的robots.txt策略 CONCURRENT_REQUESTS = 16 #Scrapy downloader 併發請求(concurrent requests)的最大值 DOWNLOAD_DELAY = 0.2 # 下載同一個網站頁面前等待的時間,能夠用來限制爬取速度減輕服務器壓力。 COOKIES_ENABLED = False # 關閉cookies
5.配置middleware.py配合settings中的UA設置能夠在下載中隨機選擇UA有必定的反ban效果,在原有代碼基礎上加入下面代碼。這裏的user_agent_list能夠加入更多。
import random from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware class RotateUserAgentMiddleware(UserAgentMiddleware): def __init__(self, user_agent=''): self.user_agent = user_agent def process_request(self, request, spider): ua = random.choice(self.user_agent_list) if ua: print(ua) request.headers.setdefault('User-Agent', ua) user_agent_list = [ "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5", "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3", "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24" ]
6.到如今爲止,代碼都已經完成了。那麼開始執行吧!scrapy crawl doutu
以後能夠看到一邊下載,一邊修改User Agent。
學習使用Scrapy遇到不少坑,可是強大的搜索系統不會讓我感受孤單。因此感受Scrapy仍是很強大的也很意思,後面繼續學習Scrapy的其餘方面內容。源碼加羣
學習過程當中遇到什麼問題或者想獲取學習資源的話,歡迎加入學習交流羣626062078,咱們一塊兒學Python!