關於b站爬蟲的嘗試(二)


前幾天學習了scrapy的框架結構和基本的使用方法,部分內容轉載自:http://blog.csdn.net/qq_30242609/article/details/52810840

scrapy由編寫蜘蛛的spiders文件夾和其他框架自帶的幾個python文件組成

其中

items.py

雙擊打開這個文件,看一下都初始化了什么東西

# -*- coding: urf-8 -*- # Define here the models for your scrapyed items # # See documentation in # http://doc.scrapy.org/en/latest/topics/items.html import scrapy class HeartsongItem(scrapy.Item): # define the fields for your item here like: # # name = scrapy.Filed() pass
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

通過里面的注釋可見,這個文件的作用是定義我們要爬取信息的標准格式,打個比方說,如果我們要爬取一批人的個人信息,包括姓名,性別,生日,那么我們可以這樣來書寫這個文件

import scrapy class HeartsongItem(scrapy.Item): name = scrapy.Filed() sex = scrapy.Filed() birthday = scrapy.Filed()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

易見本文件只是定義了一個類,至於什么時候實例化它,怎么保存它,請繼續了解下面的內容。

settings.py

如其名,這是本項目的配置文件,里面注釋着很多常用的配置項,我們通過在其他文件中引入本文件的方式來使用這些配置項。 
當然,我們可以把這些注釋都刪掉,等需要開啟哪個功能的時候再另行編輯。 
我們此處先看看默認打開的配置項吧

BOT_NAME = 'heartsong' SPIDER_MODULES = ['heartsong.spiders'] NEWSPIDER_MODULE = 'heartsong.spider' # Obey robots.txt rules ROBORSTXT_OBEY = True
  • 1
  • 2
  • 3
  • 4
  • 5

因為我們寫的是定向爬蟲,前面三個按默認即可,我們不去管他。看第四項,注釋里說這個配置項的意思是是否遵守robots.txt,那么robots.txt是個什么東西呢? 
通俗來說,robots.txt是遵循Robot協議的一個文件,它保存在網站的服務器中,它的作用是,告訴搜索引擎爬蟲,本網站哪些目錄下的網頁不希望你進行爬取收錄。在Scrapy啟動后,會在第一時間訪問網站的robots.txt文件,然后決定該網站的爬取范圍。 
當然,我們並不是在做搜索引擎,而且在某些情況下我們想要獲取的內容恰恰是被robots.txt所禁止訪問的。所以,我們就將此配置項設置為False,拒絕遵守Robot協議

pipelines.py

雙擊打開這個文件,看看都初始化了什么東西

# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html class HeartsongPipeline(object): def process_item(self, item, spider): return item 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

從注釋中所能得到的信息微乎其微,只告訴我們要啟用此文件的話必須要在settings.py里配置一下ITEM_PIPELINES,好,那我們就老老實實的去settings.py里配置一下吧,不過注意,此處有坑,在1.0.x版本(極客學院教程中使用),配置項用list格式來書寫,而在最新的1.1.2版本中,需要用dict格式,否則會報錯,無法爬取,配置好后,我們的setting.py如下:

# -*- coding: utf-8 -*- BOT_NAME = 'heartsong' SPIDER_MODULES = ['heartsong.spiders'] NEWSPIDER_MODULE = 'heartsong.spider' ROBORSTXT_OBEY = True ITEM_PIPELINES = { 'heartsong.pipelines.HeartsongPipeline': 300, }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

此處的300表示優先級,因為本項目只用到這一個pipeline,所以隨意取0-1000中的一個數值即可。 
好,鏡頭切回pipelines.py,這個文件到底有什么用呢?當然用處很多啦,本教程中介紹的作用只有兩個: 
* 對爬取到的數據(Item)進行處理,比如存入數據庫 
* 爬蟲結束時產生事件,比如發送一封郵件

爬蟲

在默認生成的spiders目錄下新建heartsong_spider.py,我們的爬蟲就寫在這里面,因為是介紹,那么此處就寫個簡單的下載網站的主頁,讓大家能運行一下,感受一下scrapy。

import scrapy class HeartsongSpider(scrapy.spiders.Spider): name = "heartsong" # 爬蟲的名字,執行時使用 allowed_domains = ["heartsong.top"] # 允許爬取的域名,非此域名的網頁不會爬取 start_urls = [ "http://www.heartsong.top" # 起始url,此例只爬這一個頁面 ] def parse(self, response): # 真正的爬蟲方法 html = response.body # response是獲取到的來自網站的返回 # 以下四行將html存入文件 filename = "index.html" file = open(filename, "w") file.write(html) file.close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

要說明的是,這個類不是隨心所欲來寫的,name,allowed_domains,start_urls,都是類似於”重載”的值。也就是說,scrapy內部會檢測這些變量的值,變量名不可以起成其它的名字,類似的變量之后還會有介紹。至於parse方法,就是重載的父類的方法,我們爬蟲的主體一般就寫在這里面。 
好,現在讓我們來運行它 
在命令行中進入heartsong目錄下,執行命令

scrapy crawl heartsong
  • 1

此處的名字heartsong是與爬蟲類中的name保持一致。   

以上是scrapy的基本架構。

由於遞歸爬取的時候存在超鏈接指向圖片等問題反而增加request工作量,目前主要思考通過首先爬取所有up主信息,再爬取其空間內視頻信息的辦法。但是具體的爬取方案無法確定。如果要采取不遺漏的方法,又只能從視頻方面開始爬取,回到了最初的問題。目前error視頻的數量大概占總數量的一半,問題還不是很大,暫時擱置遞歸爬取的問題。

目前依然采取根據av號枚舉的方式訪問視頻並記錄信息。根據測試程序的反饋,scrapy的爬取效率並不比request的方法高多少。。。可能有部分人認為的效率高主要由於scrapy自帶的多進程爬取的方法。但是當request也采取多進程爬取時,主要耗時依然在於獲取網絡源碼的過程中。這部分的時間目前沒有辦法減少。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import scrapy
import re

class bilibili(scrapy.Spider):
name = "bilibili"
# 允許的域名
allowed_domains = ["bilibili.com"]
start_urls = []
for av in xrange(10000):
start_urls.append("http://www.bilibili.com/video/av"+str(av))

def parse(self, response):
page = response.body
temp = re.search(r'<div class="v-title"><h1 title="(.+?)">', page)
if temp:
title = re.search(r'<div class="v-title"><h1 title="(.+?)">', page).group(1)
authorkit = re.search(r'r-info.+?title="(.+?)"', page)
if authorkit:
author = authorkit.group(1)
aid = re.search(r'aid=(\d+)', page).group(1)
cid = re.search(r'cid=(\d+)', page).group(1)
print cid
print aid
url = 'https://api.bilibili.com/x/web-interface/archive/stat?aid='+str(aid)
return scrapy.http.Request(url=url, callback=self.parse_item_page)

def parse_item_page(self, response):
print response.body


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM