本文分為兩部分,去哪兒網(wǎng)圖片爬蟲和Scrapy使用詳解株依。Scrapy使用詳解基于去哪兒網(wǎng)圖片爬蟲進行解析說明淋叶。
去哪兒網(wǎng)圖片爬蟲
- 目錄結(jié)構(gòu)
$ scrapy startproject TourLib
Scrapy組件說明
- Scrapy Engine(Scrapy引擎)
Scrapy引擎是用來控制整個系統(tǒng)的數(shù)據(jù)處理流程码俩,并進行事務(wù)處理的觸發(fā)。更多的詳細內(nèi)容可以看下面的數(shù)據(jù)處理流程扬霜。 - Scheduler(調(diào)度)
調(diào)度程序從Scrapy引擎接受請求并排序列入隊列定鸟,并在Scrapy引擎發(fā)出請求后返還給他們。 - Downloader(下載器)
下載器的主要職責(zé)是抓取網(wǎng)頁并將網(wǎng)頁內(nèi)容返還給蜘蛛( Spiders)著瓶。 - Spiders(蜘蛛)
蜘蛛是有Scrapy用戶自己定義用來解析網(wǎng)頁并抓取制定URL返回的內(nèi)容的類联予,是用來定義特定網(wǎng)站的抓取和解析規(guī)則。
蜘蛛的整個抓取流程(周期)是這樣的:
- 首先獲取第一個URL的初始請求,當(dāng)請求返回后調(diào)取一個回調(diào)函數(shù)(parse(self, response))躯泰。第一個請求是通過調(diào)用start_requests()方法谭羔。該方法默認從start_urls中的Url中生成請求,并執(zhí)行解析來調(diào)用回調(diào)函數(shù)麦向。
- 在回調(diào)函數(shù)(parse)中瘟裸,你可以解析網(wǎng)頁響應(yīng)并返回項目對象和請求對象或兩者的迭代。這些請求也將包含一個回調(diào)(scrapy.Request(links, callback=self.parse_item))诵竭,然后被Scrapy下載话告,然后有指定的回調(diào)parse_item
(self, response)處理。 - 在回調(diào)函數(shù)parse_item中卵慰,你解析網(wǎng)站的內(nèi)容沙郭,使用的是Xpath選擇器(但是你也可以使用BeautifuSoup, lxml或其他任何你喜歡的程序),并生成解析的數(shù)據(jù)項裳朋。
- 最后病线,從蜘蛛返回的項目通常會進駐到Item Pipeline(項目管道)。
- Item Pipeline(項目管道)
項目管道的主要責(zé)任是負責(zé)處理有蜘蛛從網(wǎng)頁中抽取的項目鲤嫡,他的主要任務(wù)是清洗送挑、驗證和存儲數(shù)據(jù)。當(dāng)頁面被蜘蛛解析后暖眼,將被發(fā)送到項目管道惕耕,并經(jīng)過幾個特定的次序處理數(shù)據(jù)。每個項目管道的組件都是有一個簡單的方法組成的Python類诫肠。他們獲取了項目并執(zhí)行他們的方法司澎,同時他們還需要確定的是是否需要在項目管道中繼續(xù)執(zhí)行下一步或是直接丟棄掉不處理。
項目管道通常執(zhí)行的過程有:
- 清洗HTML數(shù)據(jù)
- 驗證解析到的數(shù)據(jù)(檢查項目是否包含必要的字段)
- 檢查是否是重復(fù)數(shù)據(jù)(如果重復(fù)就刪除)
- 將解析到的數(shù)據(jù)存儲到數(shù)據(jù)庫栋豫,將解析到的圖片存儲到硬盤
piplines就干了兩件事挤安,每次spider處理好一個頁面,將圖片信息傳給它丧鸯,1.圖片存到硬盤漱受,2.信息存到數(shù)據(jù)庫
- Downloader middlewares(下載器中間件)
下載中間件是位于Scrapy引擎和下載器之間的鉤子框架,主要是處理 Scrapy引擎與下載器之間的請求及響應(yīng)。它提供了一個自定義的代碼的方式來拓展Scrapy的功能。下載中間器是一個處理請求和響應(yīng)的鉤子框架乳幸。他是 輕量級的,對Scrapy盡享全局控制的底層的系統(tǒng)虐先。 - Spider middlewares(蜘蛛中間件)
蜘蛛中間件是介于Scrapy引擎和蜘蛛之間的鉤子框架,主要工作是處理蜘蛛 的響應(yīng)輸入和請求輸出派敷。它提供一個自定義代碼的方式來拓展Scrapy的功能蛹批。蛛中間件是一個掛接到Scrapy的蜘蛛處理機制的框架撰洗,你可以插入自定義 的代碼來處理發(fā)送給蜘蛛的請求和返回蜘蛛獲取的響應(yīng)內(nèi)容和項目。 - Scheduler middlewares(調(diào)度中間件)
調(diào)度中間件是介于Scrapy引擎和調(diào)度之間的中間件腐芍,主要工作是處從Scrapy引擎發(fā)送到調(diào)度的請求和響應(yīng)差导。他提供了一個自定義的代碼來拓展Scrapy的功能。前陣子想爬點二手車數(shù)據(jù)賺錢猪勇,專門搗鼓了一兩個星期的scrapy设褐,雖然最后因為各種原因,賺錢并不如意泣刹,但也學(xué)到了爬蟲的一些基本技術(shù)助析,現(xiàn)在記錄下來,以備后續(xù)使用椅您。
添加mysql支持
- settings.py中添加如下配置項
# start MySQL database configure setting
MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'cnblogsdb'
MYSQL_USER = 'root'
MYSQL_PASSWD = 'root'
# end of MySQL database configure setting
- 在piplines.py中添加數(shù)據(jù)庫操作如下:
class ImageDownloadPipeline(object):
def process_item(self, item, spider):
db = MySQLdb.connect("localhost","root","mypassword","test_db" )
cursor = db.cursor()
if 'image_urls' in item:
images = []
dir_path = '%s/%s/%s' % (settings.IMAGES_STORE,item['place'],item['name'])
##item['url'] = <200 www.explame.com>
urls = str(item['url'])[5:-1]
if not os.path.exists(dir_path):
os.makedirs(dir_path)
for image_url in item['image_urls']:
image_file_name = image_url[-15:]
file_path = '%s/%s' % (dir_path, image_file_name)
images.append(file_path)
if os.path.exists(file_path):
continue
with open(file_path, 'wb') as handle:
response = requests.get(image_url, stream=True)
for block in response.iter_content(1024):
if not block:
break
handle.write(block)
sql = "INSERT INTO tour_tbl (tour_title,tour_icourl,local_url) VALUES ( '%s','%s','%s' )" % ( image_file_name,image_url,urls)
try:
# 執(zhí)行sql語句
cursor.execute(sql)
# 提交到數(shù)據(jù)庫執(zhí)行
db.commit()
except:
# 發(fā)生錯誤時回滾
db.rollback()
item['images'] = images
# 關(guān)閉數(shù)據(jù)庫連接
db.close()
return item
- 在settins.py中添加ImageDownloadPipeline
ITEM_PIPELINES = {'qunar.pipelines.ImageDownloadPipeline': 1}
Xpath使用
示例
xpath類似beautifulsoup解析html結(jié)構(gòu)外冀,省去了正則表達式的麻煩
<html>
<head></head>
<body>
<div>
<p><a > more information </a></p>
</div>
</body>
</html>
- xpath('//div//a')
[<a > more information </a>] - xpath('//div/*')
div中所有元素 - xpath('//div/a/@href')
[http://www.iana.org] - xpath('//div/a/text()').extract()
'more information'
xpath參考教程
這是個視頻教程,是我學(xué)習(xí)xpath的最好的教程掀泳,看完真的是一下就明白了雪隧。
XPath 與多線程爬蟲
Scrapy定向爬蟲教程(二)——提取網(wǎng)頁內(nèi)容
多頁面爬取
多頁面爬取有兩種形式
1)從某一個或者多個主頁中獲取多個子頁面的url列表,parse()函數(shù)依次爬取列表中的各個子頁面员舵。
#先獲取url list脑沿,然后根據(jù)list爬取各個子頁面內(nèi)容
fromtutorial.items import DmozItem
classDmozSpider(scrapy.Spider):
name = "dmoz"
allowed_domains = ["dmoz.org"]
start_urls =["http://www.dmoz.org/Computers/Programming/Languages/Python/",]
def parse(self, response):
for href inresponse.css("ul.directory.dir-col > li > a::attr('href')"):
#獲取當(dāng)前頁面的url:respone.url
#通過拼接response.url和href.extract(),將相對網(wǎng)址轉(zhuǎn)換為絕對網(wǎng)址
url =response.urljoin(response.url, href.extract())
yield scrapy.Request(url, callback=self.parse_dir_contents)
#負責(zé)子頁面內(nèi)容的爬取
def parse_dir_contents(self, response):
for sel in response.xpath('//ul/li'):
item = DmozItem()
item['title'] =sel.xpath('a/text()').extract()
item['link'] = sel.xpath('a/@href').extract()
item['desc'] =sel.xpath('text()').extract()
yield item
2)從遞歸爬取固灵,這個相對簡單。在scrapy中只要定義好初始頁面以及爬蟲規(guī)則rules劫流,就能夠?qū)崿F(xiàn)自動化的遞歸爬取巫玻。
yield和return的區(qū)別
- yield
yield是用于生成器。什么是生成器祠汇,你可以通俗的認為仍秤,在一個函數(shù)中,使用了yield來代替return的位置的函數(shù)可很,就是生成器诗力。它不同于函數(shù)的使用方法是:函數(shù)使用return來進行返回值,每調(diào)用一次我抠,返回一個新加工好的數(shù)據(jù)返回給你苇本;yield不同,它會在調(diào)用生成器的時候菜拓,把數(shù)據(jù)生成object瓣窄,然后當(dāng)你需要用的時候,要用next()方法來取纳鼎,同時不可逆俺夕。你可以通俗的叫它"輪轉(zhuǎn)容器"裳凸,可用現(xiàn)實的一種實物來理解:水車,先yield來裝入數(shù)據(jù)劝贸、產(chǎn)出generator object姨谷、使用next()來釋放;好比水車轉(zhuǎn)動后映九,車輪上的水槽裝入水梦湘,隨著輪子轉(zhuǎn)動,被轉(zhuǎn)到下面的水槽就能將水送入水道中流入田里氯迂。
def func3():
for i in range(1,5):
yield i#裝入
gob = func3()#generator 類型
print next(gob)#1 釋放的第一個裝入的數(shù)據(jù)践叠,(先入先出)
print next(gob)#2
print next(gob)#3
print next(gob)#4
print next(gob)#報錯
個人理解,yield在python內(nèi)部是當(dāng)作list處理的:
def func3():
for i in range(1,5):
yield i
yi = []
yi = func3()
for y in yi:
print y
輸出:
1
2
3
4
- return
這個大家都知道嚼蚀,return既可以終止函數(shù)的執(zhí)行禁灼,也可以返回函數(shù)加工處理好的數(shù)據(jù)。