Scrapy在window上的安裝教程見下面的鏈接:Scrapy安裝教程
上述安裝教程已實踐,可行。(本來打算在ubuntu上安裝Scrapy的,但是Ubuntu 磁盤空間太少了,還沒擴展磁盤空間,所以沒有在Ubuntu上裝,至於如何在Ubuntu上安裝Scrapy,網上有挺多教程的)
Scrapy的入門教程見下面鏈接:Scrapy入門教程
上面的入門教程是很基礎的,先跟着作者走一遍,要動起來喲,不要只是閱讀上面的那篇入門教程。
下面我簡單總結一下Scrapy爬蟲過程:
1、在Item中定義自己要抓取的數據:
movie_name就像是字典中的“鍵”,爬到的數據就像似字典中的“值”。在繼承了BaseSpider的類中會用到:
第一行就是上面那個圖中的TutorialItem這個類,紅框圈出來的就是上圖中的movie_name這個變量
2、然后在spiders目錄下編輯Spider.py那個文件
按上面【入門教程】來寫就行了,我這邊給個例子,跟我上面的item是匹配的:
【入門教程】你沒有給出start_requests這個方法,稍后我會講到這個方法。另外這里的代碼我都是截圖,后面我會用代碼面板顯示我的代碼,有需要的人可以復制下來玩玩。
3、編輯pipelines.py文件,可以通過它將保存在TutorialItem中的內容寫入到數據庫或者文件中
下面的代碼示例是寫到文件(如果要寫到數據庫中去,這里有個示例代碼)中去:
對json模塊的方法的注釋:dump和dumps(從Python生成JSON),load和loads(解析JSON成Python的數據類型);dump和dumps的唯一區別是dump會生成一個類文件對象,dumps會生成字符串,同理load和loads分別解析類文件對象和字符串格式的JSON。(注釋來於http://www.jb51.net/article/52224.htm )
4、爬蟲開始
上述三個過程后就可以爬蟲了,僅需上述三個過程喲,然后在dos中將目錄切換到tutorial下輸入scrapy crawl douban就可以爬啦:
上面幾個過程只是先理清楚用Scrapy爬蟲的思路,下面的重點戲是第二個過程,我會對這個過程進行較詳細的解釋,並提供代碼。
douban_spider.py這個文件的代碼如下:

1 #coding=utf-8 2 import sys 3 reload(sys) 4 #python默認環境編碼時ascii 5 sys.setdefaultencoding("utf-8") 6 from scrapy.spider import BaseSpider 7 from scrapy.http import Request 8 from scrapy.selector import HtmlXPathSelector 9 from tutorial.items import TutorialItem 10 import re 11 12 class DoubanSpider(BaseSpider): 13 name = "douban" 14 allowed_domains = ["movie.douban.com"] 15 start_urls = [] 16 17 def start_requests(self): 18 file_object = open('movie_name.txt','r') 19 20 try: 21 url_head = "http://movie.douban.com/subject_search?search_text=" 22 for line in file_object: 23 self.start_urls.append(url_head + line) 24 25 for url in self.start_urls: 26 yield self.make_requests_from_url(url) 27 finally: 28 file_object.close() 29 #years_object.close() 30 31 def parse(self, response): 32 #open("test.html",'wb').write(response.body) 33 hxs = HtmlXPathSelector(response) 34 #movie_name = hxs.select('//*[@id="content"]/div/div[1]/div[2]/table[1]/tr/td[1]/a/@title').extract() 35 movie_link = hxs.select('//*[@id="content"]/div/div[1]/div[2]/table[1]/tr/td[1]/a/@href').extract() 36 #movie_desc = hxs.select('//*[@id="content"]/div/div[1]/div[2]/table[1]/tr/td[2]/div/p/text()').extract() 37 38 if movie_link: 39 yield Request(movie_link[0],callback=self.parse_item) 40 41 42 def parse_item(self,response): 43 hxs = HtmlXPathSelector(response) 44 movie_name = hxs.select('//*[@id="content"]/h1/span[1]/text()').extract() 45 movie_director = hxs.select('//*[@id="info"]/span[1]/span[2]/a/text()').extract() 46 movie_writer = hxs.select('//*[@id="info"]/span[2]/span[2]/a/text()').extract() 47 #爬取電影詳情需要在已有對象中繼續爬取 48 movie_description_paths = hxs.select('//*[@id="link-report"]') 49 movie_description = [] 50 for movie_description_path in movie_description_paths: 51 movie_description = movie_description_path.select('.//*[@property="v:summary"]/text()').extract() 52 53 #提取演員需要從已有的xPath對象中繼續爬我要的內容 54 movie_roles_paths = hxs.select('//*[@id="info"]/span[3]/span[2]') 55 movie_roles = [] 56 for movie_roles_path in movie_roles_paths: 57 movie_roles = movie_roles_path.select('.//*[@rel="v:starring"]/text()').extract() 58 59 #獲取電影詳細信息序列 60 movie_detail = hxs.select('//*[@id="info"]').extract() 61 62 item = TutorialItem() 63 item['movie_name'] = ''.join(movie_name).strip().replace(',',';').replace('\'','\\\'').replace('\"','\\\"').replace(':',';') 64 #item['movie_link'] = movie_link[0] 65 item['movie_director'] = movie_director[0].strip().replace(',',';').replace('\'','\\\'').replace('\"','\\\"').replace(':',';') if len(movie_director) > 0 else '' 66 #由於逗號是拿來分割電影所有信息的,所以需要處理逗號;引號也要處理,否則插入數據庫會有問題 67 item['movie_description'] = movie_description[0].strip().replace(',',';').replace('\'','\\\'').replace('\"','\\\"').replace(':',';') if len(movie_description) > 0 else '' 68 item['movie_writer'] = ';'.join(movie_writer).strip().replace(',',';').replace('\'','\\\'').replace('\"','\\\"').replace(':',';') 69 item['movie_roles'] = ';'.join(movie_roles).strip().replace(',',';').replace('\'','\\\'').replace('\"','\\\"').replace(':',';') 70 #item['movie_language'] = movie_language[0].strip() if len(movie_language) > 0 else '' 71 #item['movie_date'] = ''.join(movie_date).strip() 72 #item['movie_long'] = ''.join(movie_long).strip() 73 74 #電影詳情信息字符串 75 movie_detail_str = ''.join(movie_detail).strip() 76 #print movie_detail_str 77 78 movie_language_str = ".*語言:</span> (.+?)<br><span.*".decode("utf8") 79 movie_date_str = ".*上映日期:</span> <span property=\"v:initialReleaseDate\" content=\"(\S+?)\">(\S+?)</span>.*".decode("utf8") 80 movie_long_str = ".*片長:</span> <span property=\"v:runtime\" content=\"(\d+).*".decode("utf8") 81 82 pattern_language =re.compile(movie_language_str,re.S) 83 pattern_date = re.compile(movie_date_str,re.S) 84 pattern_long = re.compile(movie_long_str,re.S) 85 86 87 movie_language = re.search(pattern_language,movie_detail_str) 88 movie_date = re.search(pattern_date,movie_detail_str) 89 movie_long = re.search(pattern_long,movie_detail_str) 90 91 item['movie_language'] = "" 92 if movie_language: 93 item['movie_language'] = movie_language.group(1).strip().replace(',',';').replace('\'','\\\'').replace('\"','\\\"').replace(':',';') 94 #item['movie_detail'] = ''.join(movie_detail).strip() 95 96 item['movie_date'] = "" 97 if movie_date: 98 item['movie_date'] = movie_date.group(1).strip().replace(',',';').replace('\'','\\\'').replace('\"','\\\"').replace(':',';') 99 100 item['movie_long'] = "" 101 if movie_long: 102 item['movie_long'] = movie_long.group(1) 103 104 yield item
代碼有了,我來一步步講解哈。
前言:我要爬的是豆瓣的數據,我有了很多電影的名字,但是我需要電影的詳情,我用了一下豆瓣電影的網站,發現當我在搜索框里輸入“Last Days in Vietnam”時url會變成http://movie.douban.com/subject_search?search_text=Last+Days+in+Vietnam&cat=1002 然后我就試着直接輸入http://movie.douban.com/subject_search?search_text=Last+Days+in+Vietnam這個url,搜索結果是一樣的,很顯然這就是get方式,這樣我們就找到了規律:http://movie.douban.com/subject_search?search_text=后面加上我們的電影名字並用加號分割就行了。
我們的電影名字(大量的電影名字)是存在movie_name.txt這個文件中里面的(一行一個電影名字):
我們可以先用python腳本(shell腳本也行)將電影名之間的空格處理為+,也可以在爬蟲中讀取電影名后進行一次replace處理(我是先處理成+的)。爬蟲讀取電影名字文件,然后構建url,然后就根據得到的網頁找到搜索到的第一個電影的url(其實第一個電影未必一定是我們要的,但是這種情況是少數,我們暫時不理會它),得到第一個電影的url后,再繼續爬,這次爬到的頁面就含有我們想要的電影信息,需要使用XPath來獲得html文件中元素節點,最后將獲得的信息存到TutorialItem中,通過pipelines寫入到data.dat文件中。
XPath的教程在這里:w3school的基礎教程和scrapy官網上的Xpath 這些東西【入門教程】中都有說。
1、start_requests方法:
在【入門教程】那篇文章中沒有用到這個方法,而是直接在start_urls中存入我們要爬蟲的網頁鏈接,但是如果我們要爬蟲的鏈接很多,而且是有一定規律的,我們就需要重寫這個方法了,首先我們看看start_requests這個方法是干嘛的:
可見它就是從start_urls中讀取鏈接,然后使用make_requests_from_url生成Request,
start_requests官方解釋在這里
那么這就意味我們可以在start_requests方法中根據我們自己的需求往start_urls中寫入我們自定義的規律的鏈接:
2、parse方法:
生成了請求后,scrapy會幫我們處理Request請求,然后獲得請求的url的網站的響應response,parse就可以用來處理response的內容。在我們繼承的類中重寫parse方法:
parse_item是我們自定義的方法,用來處理新連接的request后獲得的response:
HtmlXPathSelector的解釋在這里
為了獲得我想要的數據我也是蠻拼的,由於豆瓣電影詳情的節點是沒太大規律了,我后面還用了正則表達式去獲取我要的內容,具體看上面的代碼中parse_item這個方法吧:
好了,結束了,這里還有一篇Scrapy的提高篇,有興趣的去看看吧。
寫寫博客是為了記錄一下自己實踐的過程,也希望能對需要者有用吧!