寫在前面
最近在學習Python的語法,刷刷LeetCode什麼的。熟悉之後,就想著寫一個爬蟲實際運用一下。
知乎了一下,然後看了scrapy的文件 ,就開始動手了。
那麼爬什麼呢❓
當時就想著寫一個根據目錄來下載github倉庫檔案的spider。因為以前下載github倉庫的時候要麼只能根據git地址clone整個repo,要麼只能通過octoTree或者insightio下載單個檔案,然而經常會有需要下載單個或者多個目錄的情況,所以就想著寫一個根據目錄來下載github上檔案的爬蟲。
開始
要開始,當然是推薦看官方的入門教程了。
這裡簡單描述下步驟:
##1.建立專案
scrapy startproject scrapy_github_dir
##2.建立爬蟲
scrapy genspider app github.com
##3.寫邏輯或者進行設定等等
##4.執行爬蟲,爬取路徑是github上的目錄或者檔案
scrapy crawl app -a urls = https://github.com/ditclear/BindingListAdapter/tree/917e254f527d101e3f583c38739a61f3bcffbc11/library-kotlin
複製程式碼
主要的程式碼都在app.py裡,當執行scrapy genspider app github.com
時會主動幫你生成它
import scrapy
from ..items import ScrapyGithubDirItem
class AppSpider(scrapy.Spider):
name = 'app'
allowed_domains = ['github.com']
content_domains = 'https://github.com/'
start_urls = []
def __init__(self, urls=None, *args, **kwargs):
super(AppSpider, self).__init__(*args, **kwargs)
self.start_urls = urls.split(',')
//執行scrapy crawl xx 後,處理response
def parse(self, response):
raw_url = response.css('a#raw-url').xpath('@href').extract_first()
if raw_url:
href = self.content_domains+raw_url
print("scrapy from href --> ", href)
yield scrapy.Request(href, callback=self.parse_link)
else:
for link in response.selector.xpath('//a[@class="js-navigation-open"]/@href').extract()[1:]:
href = self.content_domains+link
yield scrapy.Request(href, callback=self.parse)
def parse_link(self, response):
responseStr = str(response).strip()
url = responseStr.strip()[5:len(responseStr)-1]
print('download from url --> ', url)
item = ScrapyGithubDirItem()
item['file_urls'] = [url]
return item
複製程式碼
當執行scrapy crawl xx
後,會在parse(self, response)
方法處理response。
處理response,簡單理解來就是通過css選擇器和xpath來找到你想要的內容,比如text/img/href等等,獲取到想要的內容後,儲存到檔案、資料庫,期間摻雜著一些scarpy的配置。
通過分析網頁原始檔:
可以看到單個檔案的下載連結在id為raw-url的a標籤中,所以我們需要找到這個標籤然後獲取到想要的連結。
raw_url = response.css('a#raw-url').xpath('@href').extract()
複製程式碼
這裡的意思是通過css選擇器找到id為raw-url的a標籤,然後獲取到a標籤的href引數,最後提取出來以列表的形式返回。
如果沒有返回那麼則表示當前request的url不是具體的某個檔案,而是一個目錄。
如果當前url是目錄
分析一下目錄的response的結構,通過css選擇器和xpath繼續找到其下一級的檔案
同樣的,找到這個地址
response.selector.xpath('//a[@class="js-navigation-open"]/@href').extract()
複製程式碼
需要注意的是返回的列表中,第一個索引的值指向的是上一級目錄,所以需要將其排除掉。接著遞迴呼叫當前的parse方法,直到爬取到檔案為止。
if raw_url:
//爬取具體的檔案
yield scrapy.Request(href, callback=self.parse_link)
else:
//如果是目錄,遞迴直到爬取到檔案為止
for link in response.selector.xpath('//a[@class="js-navigation-open"]/@href').extract()[1:]:
yield scrapy.Request(href, callback=self.parse)
複製程式碼
程式碼不多,順利的話半天就能成功。
寫在最後
回顧一下,能發現沒怎麼就已經寫好了。而爬蟲簡單看來就是通過css選擇器、xpath或者正則找到需要的資料,然後進行想要的處理,期間夾雜著遞迴的邏輯和演算法,當然這只是初見scrapy,不過已經能發現Python以及Scrapy的強大了。
github地址:github.com/ditclear/sc…