接著之前的文章(http://blog.csdn.net/androidworkor/article/details/51171098)來(lái)分析Scrapy的目錄結(jié)構(gòu)
項(xiàng)目目錄結(jié)構(gòu)
打開(kāi)之前的指定的文件目錄(F:\WorkSpace\python\Hello)完整的目錄結(jié)構(gòu)如下:
Hello/
scrapy.cfg
Hello/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...
這些文件分別是:
- scrapy.cfg: 項(xiàng)目的配置文件
- Hello/: 該項(xiàng)目的python模塊早芭。之后您將在此加入代碼署隘。
- Hello/items.py: 項(xiàng)目中的item文件.
- Hello/pipelines.py: 項(xiàng)目中的pipelines文件.
- Hello/settings.py: 項(xiàng)目的設(shè)置文件.
- Hello/spiders/: 放置spider代碼的目錄.
定義Item
Item 是保存爬取到的數(shù)據(jù)的容器;其使用方法和python字典類似宋欺, 并且提供了額外保護(hù)機(jī)制來(lái)避免拼寫(xiě)錯(cuò)誤導(dǎo)致的未定義字段錯(cuò)誤胸墙。我們來(lái)看一個(gè)例子
這里就有用戶圖標(biāo)寸痢、用戶名稱囊榜、內(nèi)容书闸、好笑和評(píng)論這5個(gè)屬性那么item就可以這么定義了尼变,打開(kāi)items.py文件
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class HelloItem(scrapy.Item):
# define the fields for your item here like:
userIcon = scrapy.Field()
userName = scrapy.Field()
content = scrapy.Field()
like = scrapy.Field()
comment = scrapy.Field()
編寫(xiě)第一個(gè)爬蟲(chóng)(Spider)
Spider是用戶編寫(xiě)用于從單個(gè)網(wǎng)站(或者一些網(wǎng)站)爬取數(shù)據(jù)的類。
其包含了一個(gè)用于下載的初始URL浆劲,如何跟進(jìn)網(wǎng)頁(yè)中的鏈接以及如何分析頁(yè)面中的內(nèi)容嫌术, 提取生成 item 的方法。
為了創(chuàng)建一個(gè)Spider牌借,您必須繼承 scrapy.Spider 類度气, 且定義以下三個(gè)屬性:
name: 用于區(qū)別Spider。 該名字必須是唯一的膨报,您不可以為不同的Spider設(shè)定相同的名字磷籍。
start_urls: 包含了Spider在啟動(dòng)時(shí)進(jìn)行爬取的url列表。 因此丙躏,第一個(gè)被獲取到的頁(yè)面將是其中之一择示。 后續(xù)的URL則從初始的URL獲取到的數(shù)據(jù)中提取。
parse() 是spider的一個(gè)方法晒旅。 被調(diào)用時(shí)栅盲,每個(gè)初始URL完成下載后生成的 Response 對(duì)象將會(huì)作為唯一的參數(shù)傳遞給該函數(shù)。 該方法負(fù)責(zé)解析返回的數(shù)據(jù)(response data)废恋,提取數(shù)據(jù)(生成item)以及生成需要進(jìn)一步處理的URL的 Request 對(duì)象谈秫。
以下為我們的第一個(gè)Spider代碼,保存在 Hello/spiders 目錄下的 spider_qiushibaike.py 文件中:
# -*- coding: utf-8 -*-
import scrapy
from Hello.items import HelloItem
class Spider_qiushibaike(scrapy.Spider):
name = "qiubai"
start_urls = [
'http://www.qiushibaike.com'
]
def parse(self, response):
for item in response.xpath('//div[@id="content-left"]/div[@class="article block untagged mb15"]'):
qiubai = HelloItem()
icon = item.xpath('./div[@class="author clearfix"]/a[1]/img/@src').extract()
if icon:
icon = icon[0]
qiubai['userIcon'] = icon
userName = item.xpath('./div[@class="author clearfix"]/a[2]/h2/text()').extract()
if userName:
userName = userName[0]
qiubai['userName'] = userName
content = item.xpath('./div[@class="content"]/descendant::text()').extract()
if content:
con = ''
for str in content:
con += str
qiubai['content'] = con
like = item.xpath('./div[@class="stats"]/span[@class="stats-vote"]/i/text()').extract()
if like:
like = like[0]
qiubai['like'] = like
comment = item.xpath('./div[@class="stats"]/span[@class="stats-comments"]/a/i/text()').extract()
if comment:
comment = comment[0]
qiubai['comment'] = comment
yield qiubai
爬取
進(jìn)入項(xiàng)目的根目錄鱼鼓,執(zhí)行下列命令啟動(dòng)spider:
scrapy crawl qiubai
crawl qiubai 啟動(dòng)用于爬取 http://www.qiushibaike.com 的spider拟烫,您將得到類似的輸出:
當(dāng)然你想保存到文件也是可以的,執(zhí)行下列命令啟動(dòng)spider:
scrapy crawl qiubai -o items.json
這里保存為json格式迄本,當(dāng)然你也可以保存成其他格式硕淑。執(zhí)行的結(jié)果:
解析
# -*- coding: utf-8 -*-
這個(gè)是指定文件為utf-8格式
import scrapy
from Hello.items import HelloItem
這個(gè)是導(dǎo)包
class Spider_qiushibaike(scrapy.Spider):
這個(gè)是定義一個(gè)類并繼承自scrapy.Spider
name = "qiubai"
這個(gè)是指定spider的名稱,該名字必須是唯一的嘉赎,以區(qū)別不同的spider
start_urls = [
'http://www.qiushibaike.com'
]
這個(gè)是指定要爬的網(wǎng)站
def parse(self, response):
這個(gè)是默認(rèn)執(zhí)行的方法置媳,只要打開(kāi)了上面設(shè)置的start_urls的網(wǎng)站就會(huì)調(diào)用這個(gè)方法,在這個(gè)方法中就可以解析數(shù)據(jù)了公条,其中response是抓取的網(wǎng)站的整個(gè)html內(nèi)容拇囊。
for item in response.xpath('//div[@id="content-left"]/div[@class="article block untagged mb15"]'):
這句話就是遍歷每項(xiàng)的內(nèi)容,如下圖所示:
至于如何查看頁(yè)面的源碼就是在瀏覽器中按f12靶橱,就可以看到如上圖所示的效果了寥袭。
qiubai = HelloItem()
定義一個(gè)item并初始化路捧,這個(gè)就是之前定義的item,注: 所有之前必須先導(dǎo)入這個(gè)類
from Hello.items import HelloItem
icon = item.xpath('./div[@class="author clearfix"]/a[1]/img/@src').extract()
if icon:
icon = icon[0]
qiubai['userIcon'] = icon
這幾行代碼就是獲取用戶的圖像传黄,xpath的規(guī)則和寫(xiě)法可以參考http://scrapy-chs.readthedocs.org/zh_CN/latest/topics/selectors.html#topics-selectors-relative-xpaths大家一看就了解杰扫。
userName = item.xpath('./div[@class="author clearfix"]/a[2]/h2/text()').extract()
if userName:
userName = userName[0]
qiubai['userName'] = userName
這幾行是獲取用戶名稱
注意
如果執(zhí)行spider沒(méi)結(jié)果并出現(xiàn)如下圖所示的提示:
一般是因?yàn)槟銢](méi)設(shè)定USER_AGENT,你可以打開(kāi)文件目錄中的settings.py添加一行代碼
USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0'
至于值你可以設(shè)置成其他的尝江。
如果獲取的文字內(nèi)容不全涉波,如下如所示:
在頁(yè)面文字中含有其他標(biāo)簽的,直接這樣寫(xiě)
content = item.xpath('./div[@class="content"]/text()').extract()
這樣獲取到的文字只能獲取前面一半的文字(在公園玩手機(jī)炭序,看到一個(gè)車禍視頻,我連忙拍著胸口說(shuō): 嚇?biāo)缹殞毩瞬匀铡#┠憧梢愿某桑?/p>
content = item.xpath('./div[@class="content"]/descendant::text()').extract()
這樣獲取到全部的文字信息了惭聂。