更新:因豆瓣版本更新轿塔,正文內(nèi)代碼已失效昆淡,修復后的代碼放到了Github刺桃,主要變化:
- 退2保平安匈睁,改用Python 3(free style)
- 加入了隨機生成User Agent(Scrapy的user agent明明白白表示自己是個機器人...這是舊代碼抓不到任何數(shù)據(jù)的原因)
- 更新了rate的xpath
- 現(xiàn)在github repo里共有三個玩具爬蟲卷哩,分別使用beautifulsoup蛋辈、scrapy、selenium
下面是本文初始版将谊,詳述Python 2下的Scrapy方法:
第一次接觸scrapy冷溶,想找個簡單的頁面嘗試下,于是就抓了豆瓣電影TOP250尊浓。沒什么技術(shù)含量逞频,主要收獲是了解了scrapy的基本功能、xpath以及python中Unicode的編碼問題栋齿。
只想看結(jié)果的話請往后翻苗胀。
實現(xiàn)
items.py (scrapy)
import scrapy
class Movie250Item(scrapy.Item):
rank = scrapy.Field()
title = scrapy.Field()
link = scrapy.Field()
star = scrapy.Field()
rate = scrapy.Field()
quote = scrapy.Field()
spider_movie250.py (scrapy)
import scrapy
from movie250.items import Movie250Item
class Movie250Spider(scrapy.Spider):
"""docstring for Movie250Spider"""
name = 'movie250'
allowed_domains = ["douban.com"]
start_urls = [
"http://movie.douban.com/top250/"
]
def parse(self, response):
for info in response.xpath('//div[@class="item"]'):
item = Movie250Item()
item['rank'] = info.xpath('div[@class="pic"]/em/text()').extract()
item['title'] = info.xpath('div[@class="pic"]/a/img/@alt').extract()
item['link'] = info.xpath('div[@class="pic"]/a/@href').extract()
item['star'] = info.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/em/text()').extract()
item['rate'] = info.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/text()').extract()
item['quote'] = info.xpath('div[@class="info"]/div[@class="bd"]/p[@class="quote"]/span/text()').extract()
yield item
# 翻頁
next_page = response.xpath('//span[@class="next"]/a/@href')
if next_page:
url = response.urljoin(next_page[0].extract())
yield scrapy.Request(url, self.parse)
以上代碼寫好后進入在Console里輸入以下命令,以爬取數(shù)據(jù)并存入json文件中:
scrapy crawl movie250 -o items.json
得到的json文件采樣:
[{"star": ["9.6"], "title": ["\u8096\u7533\u514b\u7684\u6551\u8d4e"], "quote": ["\u5e0c\u671b\u8ba9\u4eba\u81ea\u7531\u3002"], "rank": ["1"], "rate": ["628644\u4eba\u8bc4\u4ef7"], "link": ["http://movie.douban.com/subject/1292052/"]},
{"star": ["9.4"], "title": ["\u8fd9\u4e2a\u6740\u624b\u4e0d\u592a\u51b7"], "quote": ["\u602a\u8700\u9ecd\u548c\u5c0f\u841d\u8389\u4e0d\u5f97\u4e0d\u8bf4\u7684\u6545\u4e8b\u3002"], "rank": ["2"], "rate": ["598654\u4eba\u8bc4\u4ef7"], "link": ["http://movie.douban.com/subject/1295644/"]}]
最后自己再寫一個output得到結(jié)果(主要注意編碼問題瓦堵,注釋里已進行解釋基协,print語句有點長Orz):
output.py
import json
def readMovieJson():
inFile = open("D:\Users\Simon\movie250\items.json",'r',0)
text = inFile.read() # text是str
movie_dict = json.loads(text) # movie_dict是list
for movie in movie_dict: # movie是dict
rank = movie["rank"][0] # rank等都是Unicode
title = movie["title"][0]
link = movie["link"][0]
star = movie["star"][0]
rate = movie["rate"][0]
if movie["quote"]:
quote = movie["quote"][0]
else: quote = "暫無".decode("utf-8")
# str和Unicode不能混用,要么將Unicode類型encode為其他編碼菇用,
要么將str類型decode為其他編碼
# python的內(nèi)部使用Unicode澜驮,str如“電影: ”是字節(jié)串,由Unicode
經(jīng)過編碼(encode)后的字節(jié)組成的
# 與下句不同的另一種組合字符串方式:print "電影: " + title.encode("utf-8")
print "top".decode("utf-8") + rank + ".".decode("utf-8") + \
title + " 評分".dec1ode("utf-8") + star + \
'('.decode("utf-8") + rate + ')'.decode("utf-8") + \
"\n鏈接:".decode("utf-8") + link + \
"\n豆瓣評論:".decode("utf-8") + quote + "\n"
結(jié)果
top1.肖申克的救贖 評分9.6(628644人評價)
鏈接:http://movie.douban.com/subject/1292052/
豆瓣評論:希望讓人自由惋鸥。
top2.這個殺手不太冷 評分9.4(598654人評價)
鏈接:http://movie.douban.com/subject/1295644/
豆瓣評論:怪蜀黍和小蘿莉不得不說的故事杂穷。
top3.阿甘正傳 評分9.4(528435人評價)
鏈接:http://movie.douban.com/subject/1292720/
豆瓣評論:一部美國近現(xiàn)代史。
top4.霸王別姬 評分9.4(430468人評價)
鏈接:http://movie.douban.com/subject/1291546/
豆瓣評論:風華絕代卦绣。
top5.美麗人生 評分9.4(291120人評價)
鏈接:http://movie.douban.com/subject/1292063/
豆瓣評論:最美的謊言亭畜。
(下略)