Scrapy爬取小說簡單邏輯
一 准備工作
1)安裝Python
2)安裝PIP
3)安裝scrapy
4)安裝pywin32
5)安裝VCForPython27.exe
...........
具體安裝步驟,可參考http://www.cnblogs.com/zyj-python/p/7392476.html
二 爬蟲邏輯
1.CMD終端創建爬蟲項目
cd Desktop(返回桌面目錄) #選擇文件保存位置,我放在了桌面 Scrapy startProject BooksSpider #BooksSpider為項目名稱,自己起名 (ps:CMD終端顯示"rou can start your first spider with:"表示項目創建成功)
2.創建爬蟲文件
拖動爬蟲項目文件用Pycharm打開,點擊左下角Terminal打開終端
scrapy genspider books(蜘蛛名,自定義,不能重復,可以修改但不建議修改) www.qisuu.com(網站域名, 這里以奇書網為例)
3.雙擊打開爬蟲文件(蜘蛛文件.py),在Spiders包中引用可能用到的包
import sys reload(sys) sys.setdefaultencoding("utf-8") import scrapy import urlparse from ..items import BooksItem
(ps:文件夾圖標中帶空心圓為包,只有包才能直接引入,帶__init__.py的文件,
沒有則表示文件夾)
以下是創建爬蟲文件自帶:
class BooksSpider(scrapy.Spider): name = 'books' allowed_domains = ['www.qisuu.com'] start_urls = ['http://www.qisuu.com/'] def parse(self, response):
pass
4.明確爬取目標
以奇書網為例:
1)請求導航條上每個按鈕對應頁面
2)分別解析每個頁面的電子書列表(主要獲得電子書詳情URL)
3)請求詳情URL,解析電子書的詳細信息(書名,封面,評分,大小....下載地址)
4)根據下載地址下載電子書到本地
制作爬蟲:
在books.py中
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding("utf-8") import scrapy import urlparse from ..items import BooksItem
class BooksSpider(scrapy.Spider): name = 'books' allowed_domains = ['www.qisuu.com'] start_urls = ['http://www.qisuu.com/']
#獲取首頁導航條的url def parse(self, response): a_list=response.xpath("//div[@class='nav']/a[@target='_blank']") for a in a_list: #分類名稱 category_namme=a.xpath("text()").extract_first("") #拼接完整的分類url category_url=urlparse.urljoin(response.url,a.xpath("@href").extract_first(""))
#yield將結果返回調度器 #將分類地址轉發給downloader下載並將結果傳給parse_books_list #meta:專門用來傳遞參數,類型是字典 yield scrapy.Request( url=category_url, callback=self.parse_books_list, meta={"category_namme":category_namme,} )
#獲取分類頁面的所有url def parse_books_list(self,response): href_list=response.xpath("//div[@class='listBox']/ul/li/a/@href").extract() for href in href_list: list_href=urlparse.urljoin(response.url,href) yield scrapy.Request( url=list_href, callback=self.parse_books_detail, meta=response.meta, # meta={"category_namme": response.meta['category_namme'],} )
#獲取所有頁數,並循環獲得每一頁的url all_pages=response.xpath("//select[@name='select']/option/@value").extract() for page in all_pages: detail_url=urlparse.urljoin(response.url,page) yield scrapy.Request( url=detail_url, callback=self.parse_books_list, meta=response.meta )
#獲取每個小說的詳情 def parse_books_detail(self,response): info_div=response.xpath("//div[@class='detail_right']") title=info_div.xpath("h1/text()").extract_first("") li_list=info_div.xpath("ul/li") size=li_list[2].xpath("text()").extract_first("") size=size.replace(u"文件大小:","").strip() date_time=li_list[4].xpath("text()").extract_first("") date_time=date_time.replace(u"發布日期:","").strip() user=li_list[6].xpath("a/text()").extract_first("") download_times=li_list[1].xpath("text()").extract_first("") download_times = download_times.replace(u"下載次數:", "").strip() book_degree=li_list[7].xpath("em/@class").extract_first("") book_degree = book_degree.replace("lstar","").strip() download_url=response.xpath("//a[@class='downButton']/@href")[1].extract() img_url=response.xpath("//div[@class='detail_pic']/img/@src").extract_first("") img_url=urlparse.urljoin(response.url,img_url) category_namme=response.meta['category_namme'] print title,user,date_time,category_namme item=BooksItem() item['title']=title item['size']=size item['date_time']=date_time item['user']=user item['download_times']=download_times item['book_degree']=book_degree item['download_url'] = [u"%s"%download_url] #當下在路徑有亂碼,加u 小說要以GBK格式存儲,有中文時要進行編碼 item['img_url']=[img_url] item['category_namme']=category_namme yield item
#yield 將結果返回給items.py文件
代碼中的xpath與正則表達式是一樣的,只是用法更加簡單方便, 具體操作可百度, 此處不細說.
在items.py文件中
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # http://doc.scrapy.org/en/latest/topics/items.html import scrapy class BooksspiderItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # pass class BooksItem(scrapy.Item): title = scrapy.Field() size = scrapy.Field() date_time = scrapy.Field() user = scrapy.Field() download_times = scrapy.Field() book_degree = scrapy.Field() download_url = scrapy.Field() img_url = scrapy.Field() category_namme = scrapy.Field()
#自定義一個類,用來接收獲取到的數據
#Field()可以接受任何類型的參數
這時就可以開始爬蟲了, 代碼為:
scrapy crawl books -o book.json -s FEED_EXPORT_ENCODING = utf-8
其中 scrapy crawl books 是運行books爬蟲程序, -o book.json 為以json格式保存, FEED_EXPORT_ENCODING = utf-8 為編碼格式
友情提示: 不要輕易去爬蟲,只有確定自己代碼沒有問題才可以,可以先使用終端測試(cmd),將代碼一行一行依次粘貼運行
scrapy shell http://www.qisuu.com
(ps:利用CMD終端測試,不要輕易去爬蟲,成功末尾顯示IN[1],然后依次在終端復制粘貼進去
相關代碼,包括相關引入import代碼,利用xpath取特定數據可在終端打印查看效果,有時要回
車兩次展示,在目標網站沒有反爬蟲協議或所需數據極少時可考慮在Terminal直接運行)
如果想要下載至本地:
需要修改settings.py文件
ITEM_PIPELINES = { # 'BooksSpider.pipelines.BooksspiderPipeline': 300, "scrapy.pipelines.images.ImagesPipeline":1, "scrapy.pipelines.files.FilesPipeline":2, } IMAGES_URLS_FIELD = "img_url" IMAGES_STORE = "imgs" FILES_URLS_FIELD = "download_url" FILES_STORE = "files"
可能存在的問題,原因及解決方案:
1.網站源代碼結構與請求到的代碼結構可能不一致
(如tbody只在瀏覽器渲染的結構中有而請求出來的沒有)
解決方案:優化xpath寫法,或改用正則表達式
2.請求robots.txt后顯示200意為請求到反爬蟲協議成功會自動停止爬蟲程序
解決方案:設置不遵守robots.txt反爬蟲協議,強行進入
3.在請求到某個url顯示200成功后卻突然自動停止爬蟲(closing spider)
可能原因:若顯示Filtered offsite request則意為scrapy自動過濾該url把它放入了黑名單
解決方案:在該url代碼運行的函數meta字典中加入dont_filter = True默認
True不要過濾,若改為False則是要過濾
以上就是Scrapy爬蟲的基本邏輯!