python爬蟲框架scrapy學習第一課
windows10 scrapy的安裝
1.先安裝python。測試python是否安裝成功或查詢安裝的版本,在命令行下輸入: python --version
2.最初採用網上介紹的一步到位安裝方式,在命令行直接輸入如下命令:
pip install scrapy
執行過程報錯,建議升級pip。按照要求執行如下命令:
python -m pip install --upgrade pip
上述命令執行成功後,繼續執行pip install scrapy仍然報錯,百度後發現需要分步驟進行。
3. 先在命令行下執行如下命令:
pip install wheel
pip install pyOpenSSL
安裝成功,繼續執行
pip install twisted
這裏報錯,問題是缺少對應的安裝文件,下載對應python版本的和操作系統的twisted安裝包。電腦64位,python3.7.0,選擇安裝包版本爲:Twisted-18.9.0-cp37-cp37m-win_amd64.whl。在該文件的存放路徑下,執行
pip install Twisted-18.9.0-cp37-cp37m-win_amd64.whl
安裝成功後,再執行pip install scrapy命令,scrapy即可安裝成功。在命令行輸入如下命令,出現版本號,即表示安裝成功。
scrapy --version
第一個scrapy爬蟲應用
根據scrapy的中文指導手冊,建立第一個scrapy實例。由於對文檔理解不深入,踩了諸多坑,記錄如下。
創建項目
選定一個存儲代碼的目錄,執行如下命令。路徑中會存在一個tutorial文件夾
scrapy startproject tutorial
tutorial文件層次及含義如下:
在tutorial/spiders路徑下執行如下命令,創建一個名爲itcast的爬蟲,並指定爬取域的範圍。
scrapy genspider itcast “itcast.cn”
在文件tutorial\spiders路徑中生成一個itcast.py文件。添加如下代碼
import scrapy
class ItcastSpider(scrapy.Spider):
name = 'itcast'
allowed_domains = ['itcast.com']
start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)
def parse(self, response):
filename = "teacher.html"
with open(filename, 'wb') as f:
f.write(response.body)
要建立一個Spider, 你必須用scrapy.Spider類創建一個子類,並確定了三個強制的屬性 和 一個方法。
1.name = “” :這個爬蟲的識別名稱,必須是唯一的,在不同的爬蟲必須定義不同的名字。
2.allow_domains = [] 是搜索的域名範圍,也就是爬蟲的約束區域,規定爬蟲只爬取這個域名下的網頁,不存在的URL會被忽略。
3.start_urls = () :爬取的URL元祖/列表。爬蟲從這裏開始抓取數據,所以,第一次下載的數據將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成。
4.parse(self, response) :解析的方法,每個初始URL完成下載後將被調用,調用的時候傳入從每一個URL傳回的Response對象來作爲唯一參數,主要作用如下:負責解析返回的網頁數據(response.body),提取結構化數據(生成item)生成需要下一頁的URL請求。
代碼中將爬取到的數據存儲在teacher.html中,在tutorial目錄下執行如下命令:
scrapy crawl itcast
發現報 No module named win32api錯誤,windows系統上出現這個問題的解決辦法是安裝Py32Win模塊,執行如下命令即可安裝成功
pip install pypiwin32
再次執行scrapy crawl itcast,發現數據爬取正常,生成一個html文件,裏面存放了網頁端靜態頁面信息
取數據
由於爬取的是整個頁面的數據,爲了獲取有效信息,需要對獲取的數據進行篩選,選擇我們感興趣的數據源。因此要定義提取數據的item。
定義item
修改原始item.py文件
import scrapy
# class TutorialItem(scrapy.Item):
# # define the fields for your item here like:
# # name = scrapy.Field()
# pass
class ItcastItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
title = scrapy.Field()
info = scrapy.Field()
在itcast.py文件中使用ItcastItem類
# -*- coding: utf-8 -*-
import scrapy
from tutorial.items import ItcastItem
class ItcastSpider(scrapy.Spider):
name = 'itcast'
allowed_domains = ['itcast.com']
start_urls = ("http://www.itcast.cn/channel/teacher.shtml",)
def parse(self, response):
items = []
for each in response.xpath("//div[@class='li_txt']"):
item = ItcastItem()
name = each.xpath("h3/text()").extract()
title = each.xpath("h4/text()").extract()
info = each.xpath("p/text()").extract()
item['name'] = name[0]
item['title'] = title[0]
item['info'] = info[0]
items.append(item)
return items
這裏用到xpath功能:
xpath(): 傳入xpath表達式,返回該表達式所對應的所有節點的selector list列表
extract(): 序列化該節點爲unicode字符串並返回list。
//div[@class=‘li_txt’]:表示獲取的數據中所有div模塊下class等於li_txt的內容。
數據保存爲json文件
命令行執行:
scrapy crawl itcast -o teachers.json
生成json數據,保存的不是中文而是unicode字符,網上推薦的有2種方式。
方式一:修改pipeline.py文件
class JsonWithEncodingPipeline(object):
def __init__(self):
self.file = codecs.open('scraped_data_utf8.json', 'w', encoding='utf-8')
def process_item(self, item, spider):
line = json.dumps(dict(item), ensure_ascii=False) + "\n"
self.file.write(line)
return item
def spider_closed(self, spider):
self.file.close()
結論:本地測試沒有成功,不確定是否是操作有誤導致?
方式二:修改settings.py,在文件中增加一行
FEED_EXPORT_ENCODING = 'utf-8'
結論:測試通過,json文件變爲中文。
數據保存爲csv文件
命令行執行:
scrapy crawl itcast -o teachers.csv
生成csv文件,雙擊直接打開,亂碼。用nodepad++打開,顯示正常。測試網上3種解決辦法,只有一種可以成功。
方式一:修改settings.py,在文件中增加一行
FEED_EXPORT_ENCODING = 'gbk'
結論:本地測試沒有通過。
方式二:用nodepad++打開,修改文件格式爲utf-8,保存後再雙擊打開。
結論:本地測試沒有通過
方式三:用記事本打開,保存文件時,選擇utf-8模式,再次雙擊打開文件。
結論:本次測試通過,csv文件中文顯示正常