一 . scrapy框架的基本應用
安裝步驟:
Linux: pip3 install scrapy Windows: 1. pip3 install wheel 2. 下載twisted: http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
3. 進入下載twisted目錄,執行 pip3 install Twisted‑17.1.0‑cp35‑cp35m‑win_amd64.whl 4. pip3 install pywin32 5. pip3 install scrapy
建立項目步驟:
1. 隨便建一個文件夾 2. 進入這個文件夾內,shift+右鍵,打開終端(命令行) 3. 建立項目命令: scrapy startproject 項目名稱 4. 到項目下: cd 項目名稱 5. 建立爬蟲文件: scrapy genspider 爬蟲文件名 url(先隨便寫,能夠改) 6. 用pycharm打開這個文件夾,就能夠看到 項目名下的spiders中有爬蟲文件名了
打開爬蟲文件
基於終端存儲
# -*- coding: utf-8 -*-
import time import scrapy # 飄紅不用管
class FirstSpider(scrapy.Spider): # name就是爬蟲文件的名稱
name = 'first'
# 容許的域名,通常都註釋掉,不用限定
# allowed_domains = ['www.xxx.com']
# 起始的url列表,在列表裏的url都會被自動的發送請求,裏面能夠寫多個
start_urls = ['http://pic.netbian.com/4kmeinv/index_2.html'] # 解析數據,有幾個url就會執行幾回這個函數
def parse(self, response): # 拿到相應數據,這個xpath和etree的xpath不太同樣
li_list = response.xpath('//div[@class="slist"]//li') names = [] for li in li_list: time.sleep(0.2) # 別的網站可能不用,這個網址不讓請求頻率過高
# 特性,xpath返回的列表元素必定是selector對象,使用extract方法能夠獲取selector中data中的數據
# author = div.xpath('地址')[0].extract()
src = li.xpath('.//img/@src').extract_first() all_src = 'http://pic.netbian.com' + src # 基於終端指令進行持久化存儲的時候解析內容須要是字典格式或者是None
dic = { 'name': all_src } names.append(dic) # print(src)
return names
執行這個文件
# 這裏執行不用實例化類而後右鍵執行,須要在終端執行 # 執行以前須要在settings.py中修改ROBOTSTXT_OBEY = False,而且USER-AGENT也須要改.
執行命令: scrapy crawl 爬蟲文件名 # 有日誌文件
scrapy crawl 爬蟲文件名 --nolog 通常不用,若是報錯找不到,除非100%沒錯 持久化存儲(基於終端指令,只能存到硬盤上,不能存到數據庫上) scrapy crawl 爬蟲文件名 -o 磁盤文件路徑+名稱.csv 若是不是.csv格式會報錯 # 好比說: scrapy crawl spiderName -o beauty.csv 沒有寫文件路徑直接保存到當前目錄
基於管道存儲
首先到配置文件中把 ITEM_PIPELINES 打開, 後面的數字是權重,數字越小證實權重越大,
這裏面能夠寫多個類,好比存在不一樣地方(本地,數據庫等)
爬蟲文件(xiaohua.py)
# -*- coding: utf-8 -*-
import scrapy from ..items import FirstbloodItem class XiaohuaSpider(scrapy.Spider): name = 'xiaohua'
# allowed_domains = ['www.xxx.com']
start_urls = ['http://www.521609.com/daxuemeinv/'] def parse(self, response): li_list = response.xpath('//*[@id="content"]/div[2]/div[2]//li') for li in li_list: src = li.xpath('.//img/@src').extract_first() if not src: continue all_src = 'http://www.521609.com' + src # 實例化一個item對象
item = FirstbloodItem() # 因爲items中的Field底層是字典類型,因此要[]取值
item['img_url'] = all_src # item提交給管道
yield item
pipelines.py
# 當前類的做用是將解析的數據存儲到某一個平臺中(本地或數據庫)
class FirstbloodPipeline(object): f = None # 因爲傳過來的item對象是循環產生的,因此不能用with
def open_spider(self, spider): # 因爲原方法裏有spider,因此這也要寫
print('開始爬蟲') self.f = open('./xiaohua.txt', 'w', encoding='utf-8') # 做用:實現持久化存儲的操做
# 該方法的item參數就能夠接受爬蟲文件提交過來的item對象
def process_item(self, item, spider): img_url = item.get('img_url') self.f.write('圖片連接->' + img_url + '\n') # 返回值的做用就是將item傳遞給下一個即將被執行的管道類
return item def close_spider(self, spider): print('結束爬蟲') self.f.close()
items.py
import scrapy class FirstbloodItem(scrapy.Item): # define the fields for your item here like:
# name = scrapy.Field()
# 前邊的變量名隨便寫,後邊必須是scrapy.Field(),有幾個參數就寫幾個
img_url = scrapy.Field()
而後在終端執行 scrapy crawl xiaohua 就能夠啦!
二 . 全站數據的請求
好比你想要的數據有不少頁,那麼這幾頁的佈局都是同樣的,只有頁碼不一樣,這時候就能夠把全部頁的數據都爬下來
-- 這裏還對上面那個校花網站進行數據爬取,只不過是全站爬取
xiaohua.py文件(pipelines.py和items.py都不用改) # -*- coding: utf-8 -*-
import scrapy from ..items import FirstbloodItem class XiaohuaSpider(scrapy.Spider): name = 'xiaohua'
# allowed_domains = ['www.xxx.com']
start_urls = ['http://www.521609.com/daxuemeinv/'] # 生成一個通用的url模板
url = 'http://www.521609.com/meinvxiaohua/list%s.html' pageNum = 121
def parse(self, response): li_list = response.xpath('//*[@id="content"]/div[2]/div[2]//li') for li in li_list: src = li.xpath('.//img/@src').extract_first() if not src: continue all_src = 'http://www.521609.com' + src # 實例化一個item對象
item = FirstbloodItem() # 因爲items中的Field底層是字典類型,因此要[]取值
item['img_url'] = all_src # item提交給管道
yield item # 對其餘頁碼的url進行手動請求發送,這裏爬取的是121-125頁的數據
if self.pageNum <= 125: self.pageNum += 1 new_url = format(self.url % self.pageNum) # 其實就是遞歸調用parse函數
yield scrapy.Request(url=new_url, callback=self.parse)
三 . 請求傳參(應用到須要子網頁中的數據)
爬蟲文件(pipelines.py和items.py基本都同樣)
# -*- coding: utf-8 -*-
import scrapy from ..items import MovieproItem class MovieSpider(scrapy.Spider): name = 'movie'
# allowed_domains = ['www.xxx.com']
start_urls = ['https://www.4567tv.tv/index.php/vod/show/id/9.html'] # 接收一個請求傳遞過來的數據
def detail_parse(self, response): item = response.meta['item'] desc = response.xpath('/html/body/div[1]/div/div/div/div[2]/p[5]/span[2]/text()').extract_first() item['desc'] = desc # 在items.py文件中的屬性
yield item def parse(self, response): li_list = response.xpath('//div[@class="stui-pannel_bd"]/ul/li') for li in li_list: name = li.xpath('.//h4[@class="title text-overflow"]/a/text()').extract_first() detail_url = 'https://www.4567tv.tv' + li.xpath( './/h4[@class="title text-overflow"]/a/@href').extract_first() item = MovieproItem() item['name'] = name # items.py中的屬性
# meta是一個字典,字典中全部的鍵值對均可以傳遞給指定好的回調函數
yield scrapy.Request(url=detail_url, callback=self.detail_parse, meta={'item': item}) # 若是有不少層只要一層層把item傳過去就行了,保證用的是同一個item