python爬蟲之scrapy掃盲:搜集美圖信息之多層掃描(2)

終於又回來填坑了,雖然依舊沒有人看,哈哈哈……

為什麼過了這麼久才來填坑呢,因為我的小惡魔出生了,哈哈哈,先讓我笑五分鐘再說。

期間看了很多人發的文章,有技術的,有吐槽的,有些時候,你不被懟一下都不知道自己有多low,但是我就是我,是一樣的煙火。我就不改。

都快忘了之前說的是什麼了,讓我先靜一靜。

之前說到都沒有取下來圖片的鏈接,現在就要把圖片的鏈接取下來,並且通過鏈接訪問其他網頁再取圖片信息。

提取圖片的鏈接地址也十分簡單,根據之前的信息,可以知道,直接使用以下語句就能得到圖片的鏈接:

pageurl = item.xpath(".//a[1]/@href").extract_first()

然後老規矩,保存緩存,然後訪問鏈接地址。

問題來了,怎麼訪問新提取的鏈接呢?簡單粗暴,再寫一個回調函數,是的,你沒有聽錯,就是再寫一個,類似的樣式如下:

yield scrapy.Request(url=pageurl, callback=self.parse_url)

然後定義parse_url函數作為回調函數,分析提取網頁內容。具體的代碼在底下,因為之後沒有什麼新東西了,所以我在每行代碼之前都寫了注釋,你應該能夠理解,如果你沒有辦法理解,請告訴我,我會撿我會的回答你的。

# -*- coding: utf-8 -*-import osimport scrapyclass MtlSpider(scrapy.Spider): name = "mtl" allowed_domains = ["meitulu.com"] def start_requests(self): if os.path.exists(os.path.join(os.getcwd(), "meitulu/target.html")): url = "file:///%s" % os.path.join(os.getcwd(), "meitulu/target.html") else: url = "http://www.meitulu.com/guochan/" yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): # 如果沒有緩存,保存緩存 if not os.path.exists(os.path.join(os.getcwd(), "meitulu/target.html")): with open(os.path.join(os.getcwd(), "meitulu/target.html"), wb) as f: f.write(response.body) # 提取圖片所在區域 imgul = response.xpath("//ul[@class=img]/li[position()<3]") # 進一步提取出相應的信息 for item in imgul: yield { # 圖片url "imgurl": item.xpath("./a/img/@src").extract_first(), # 點攢數 "upvote": item.xpath("./p[1]/span/text()").extract_first(), # "num": item.xpath("./p[1]/string(.)[2]").extract_first(), # 瀏覽數 "num": item.xpath("./p[1]/text()").extract_first(), # 組織名稱 "organization_name": item.xpath(".//p[2]/a/text()").extract_first(), # 組織url "organization_url": item.xpath(".//p[2]/a/@href").extract_first(), # 模特名稱 "model_name": item.xpath("./p[3]/text()").extract_first(), # 整體標籤名稱 "tag_name": item.xpath("./p[4]//a/text()").extract(), # 標籤url "tag_url": item.xpath("./p[4]//a/@href").extract(), # 主題 "title": item.xpath("./p[5]/a/text()").extract_first(), } # 提取圖片鏈接 pageurl = item.xpath(".//a[1]/@href").extract_first() # 根據頁面名進行每一頁緩存的保存,總結文件名即頁面名稱 filename = pageurl.split(/)[-1].strip() # 鏈接如果是「/xxx/xxx.html」這種形式的,完整其url if not pageurl.startswith("http://www.meitulu.com"): pageurl = "http://www.meitulu.com%s" % pageurl # 查看頁面是否緩存,在meitulu目錄下需要新建一個htmlpage文件夾,用來存放網頁緩存 if os.path.exists(os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % filename)): # 構建本地url,進行訪問分析 url = "file:///%s" % os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % filename) yield scrapy.Request(url=url, callback=self.parse_url, dont_filter=True) else: # 直接訪問網路url yield scrapy.Request(url=pageurl, callback=self.parse_url) # 訪問圖片鏈接的回調函數 def parse_url(self, response): # 保存緩存,先確定文件名 filename = response.url.split(/)[-1] # 將頁面進行緩存,需要在meitulu目錄下新建一個htmlpage文件夾,用來存放網頁緩存 if not os.path.exists(os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % filename)): with open(os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % filename), "wb") as f: f.write(response.body) # 最後一個url地址,用來確定爬取的終點 last_url = response.xpath("//div[@id=pages][1]/a[last()-1]/@href").extract_first() # 最後一個url地址的網頁名 last_page = last_url.split(/)[-1] # 提取圖片的地址和圖片的名字 yield { "img_url": response.xpath("//div[@class=content]//img/@src").extract(), "img_name": response.xpath("//div[@class=content]//img/@alt").extract() } # 第一頁的網頁名稱 top_page = response.url.split(/)[-1] # 判斷第一頁是否就是最後一頁,如果是的話就不再進行訪問了 if not last_page == top_page: # 如果不是的話,提取前50個頁面的內容 for pagenum in range(2, 51): # 通過不斷變換網頁數字不斷構造之後的網頁url next_page = top_page.replace(".html", "_%s.html" % pagenum) # 查看頁面是否緩存 if os.path.exists(os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % next_page)): # 構建本地url,進行訪問分析 next_url = "file:///%s" % os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % next_page) yield scrapy.Request(url=next_url, callback=self.parse_img, dont_filter=True) else: # 直接訪問網路url next_url = "http://www.meitulu.com/item/%s" % next_page yield scrapy.Request(url=next_url, callback=self.parse_img) # 如果現在訪問的網頁就是最後一頁則退出循環 if next_page == last_page: break def parse_img(self, response): # 構建緩存名稱 filename = response.url.split(/)[-1] # 保存緩存 if not os.path.exists(os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % filename)): with open(os.path.join(os.getcwd(), "meitulu/htmlpage/%s" % filename), "wb") as f: f.write(response.body) # 提取信息 yield { "img_url": response.xpath("//div[@class=content]//img/@src").extract(), "img_name": response.xpath("//div[@class=content]//img/@alt").extract() }

好了,上面就是所有的程序了。

你是不是看到了不一樣的地方,每次訪問緩存文件調用回調函數的時候,都需要加一個參數,整條語句的樣式是下面醬嬸的:

yield scrapy.Request(url=url, callback=self.parse_url, dont_filter=True)

你注意到了那個「dont_filter」了嗎?

為什麼需要添加一個這個參數呢?還記得上一篇文章中說到了一個坑嗎?

我們在程序的前面定義了允許的域名:

allowed_domains = ["meitulu.com"]

如果不是這個域名的網址就會被拒絕訪問,因此為了訪問不是這個域名的地址,需要添加「dont_filter=True」參數。

好了,同學們,今天的課程就到這裡了,我們下次再見。(感覺好敷衍啊,就這樣吧。)

推薦閱讀:

使用爬蟲自動下載油管上我是歌手單曲視頻
Python爬蟲爬取知乎某一個問題下的圖片
DAY25:10行代碼搞定簡單python爬蟲核心
使用python爬豆瓣書單
誰才是鬥魚一哥?(用Python抓取鬥魚直播間信息)

TAG:爬蟲 | Python入門 |