Scrapy實戰4:初識爬蟲框架Scrapy
Scrapy實戰3:URL去重策略
Scrapy實戰2:爬蟲深度&&廣度優先算法
Scrapy實戰1| 正則表達式
今天給大家分享的是,如何在cmd和pycharm中啟動自己的spider以及Xpath的基本介紹,並利用Xpath抓取伯樂在線單篇文章基本信息。
XPath即為XML路徑語言(XML Path Language),它是一種用來確定XML文檔中某部分位置的語言。
XPath基於XML的樹狀結構,提供在數據結構樹中找尋節點的能力。起初XPath的提出的初衷是將其作
為一個通用的、介於XPointer與XSL間的語法模型。但是XPath很快的被開發者採用來當作小型查詢
語言。
1. Xpath使用路徑表達式在xml和html中進行導航(據說訪問速度、效率比bs4快)
2. Xpath包含標準函數庫
3. Xpah是一個W3c的標準
(1)快速進入虛擬環境(設置方法見上一篇)
C:\Users\82055\Desktop>workon spiderenv
(2)進入到項目目錄
(spiderenv) C:\Users\82055\Desktop>H:
(spiderenv) H:\env\spiderenv>cd H:\spider_project\spider_bole_blog\spider_bole_blog
(3)輸入spider命令(格式:scrapy crawl 子項的name)
(spiderenv) H:\spider_project\spider_bole_blog\spider_bole_blog>scrapy crawl jobbole
(4)如果是win系統,可能會出現下面錯誤
<module>
from twisted.internet import _win32stdio
File "h:\env\spiderenv\lib\site-packages\twisted\internet\_win32stdio.py", line 9, in <module>
import win32api
ModuleNotFoundError: No module named 'win32api'
(5)解決方法:安裝 pypiwin32模塊(採用豆瓣源安裝)
pip install -i https://pypi.douban.com/simple pypiwin32
(6)再次執行spider命令
(spiderenv) H:\spider_project\spider_bole_blog\spider_bole_blog>scrapy crawl jobbole
2018-08-23 23:42:01 [scrapy.utils.log] INFO: Scrapy 1.5.1 started (bot: spider_bole_blog)
···
2018-08-23 23:42:04 [scrapy.core.engine] INFO: Closing spider (finished)
2018-08-23 23:42:04 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 440,
'downloader/request_count': 2,
'downloader/request_method_count/GET': 2,
'downloader/response_bytes': 21919,
'downloader/response_count': 2,
'downloader/response_status_count/200': 2,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2018, 8, 23, 15, 42, 4, 695188),
'log_count/DEBUG': 3,
'log_count/INFO': 7,
'response_received_count': 2,
'scheduler/dequeued': 1,
'scheduler/dequeued/memory': 1,
'scheduler/enqueued': 1,
'scheduler/enqueued/memory': 1,
'start_time': datetime.datetime(2018, 8, 23, 15, 42, 2, 770906)}
2018-08-23 23:42:04 [scrapy.core.engine] INFO: Spider closed (finished)
(1)打開項目,在項目根目錄下新建一個main.py,用於調試代碼。
(2)在main.py中輸入下面內容
'''
author : 極簡XksA
data : 2018.8.22
goal : 調試模塊
'''
import sys
import os
from scrapy.cmdline import execute
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(['scrapy','crawl','jobbole'])
(3)修改setting.py文件設置,將ROBOTSTXT_OBEY值改為False,默認為True或者被注釋掉了,文件中注釋解釋內容:Obey robots.txt rules,表示我們的spider的網址必須要遵循robots協議,不然會直接被過濾掉,所以這個變量的屬性值必須設置為Fal0se哦!
ROBOTSTXT_OBEY = False
(4)直接運行測試文件main.py,運行結果和上面在cmd是一樣的。
(5)在jobbole.py中的的parse函數中加一個斷點,然後Debug模式運行測試文件main.py
斷點設置:
(1)為了簡單起見,我隨便選取了一篇文章《Linux 內核 Git 歷史記錄中,最大最奇怪的提交信息是這樣的》。
(2)把start_urls的屬性值改為http://blog.jobbole.com/114256/,使spider從當前文章開始爬起來。
start_urls = ['http://blog.jobbole.com/114256/']
(3)網頁中分析並獲取文章標題Xpath路徑
/html/body/div[1]/div[3]/div[1]/div[1]/h1
是不是感覺到很複雜,哈哈哈,不用灰心,其實分析起來挺簡單的,另外我們還有更簡單的方法獲取Xpath,當我們在查看器重找到我們要的內容後,直接右鍵,即可複製我們想要的內容的Xpath路徑了。
def parse(self, response):
re01_selector = response.xpath('/html/body/div[1]/div[3]/div[1]/div[1]/h1/text()')
re02_selector = response.xpath('//*[@id="post-114256"]/div[1]/h1/text()')
re01_title = re01_selector.extract()
re02_title = re02_selector.extract()
print('xpath返回內容:'+str(re01_selector))
print('firefox返回文章標題為:' + re01_title)
print('chrome返回文章標題為:' + re02_title)
運行結果:
xpath返回內容:[<Selector xpath='/html/body/div[1]/div[3]/div[1]/div[1]/h1/text()'
data='Linux 內核 Git 歷史記錄中,最大最奇怪的提交信息是這樣的'>]
firefox返回文章標題為:Linux 內核 Git 歷史記錄中,最大最奇怪的提交信息是這樣的
chrome返回文章標題為:Linux 內核 Git 歷史記錄中,最大最奇怪的提交信息是這樣的
從上面可以看出,FireFox和Chorme獲取到的Xpath是不一樣的,but實際返回的東西是一樣的,只是用了不同的語法,我這裡說明的意思是想告訴大家:Xpath的表達方式不止一種,可能某個內容的Xpath有兩種或者更多,大家覺得怎麼好理解就使用哪一個。
(5)我們繼續獲取其他數據(複習鞏固一下Xpath的用法)
為了快速、有效率的調式數據,給大家推薦一種方法:
scrapy shell http://blog.jobbole.com/114256/
這樣在cmd中就能保存我們的訪問內容,可以直接在cmd下進行調試,不用在pycharm中每調試一個數據,就運行一次,訪問一次頁面,這樣效率是非常低的。
>>> data_r = response.xpath('//p[@class="entry-meta-hide-on-mobile"]/text()')
>>> data_r.extract()
['\r\n\r\n 2018/08/08 · ', '\r\n \r\n \r\n\r\n \r\n · ', ', ', '\r\n \r\n']
>>> data_r.extract()[0].strip()
'2018/08/08 ·'
>>> data_str = data_r.extract()[0].strip()
>>> data_str.strip()
'2018/08/08 ·'
>>> data_str.replace('·','').strip()
'2018/08/08'
>>> praise_number = response.xpath('//h10[@id="114256votetotal"]/text()')
>>> praise_number
[<Selector xpath='//h10[@id="114256votetotal"]/text()' data='1'>]
>>> praise_number = int(praise_number.extract()[0])
>>> praise_number
1
>>> collection_number = response.xpath('//span[@data-book-type="1"]/text()')
>>> collection_number
[<Selector xpath='//span[@data-book-type="1"]/text()' data=' 1 收藏'>]
>>> collection_number.extract()
[' 1 收藏']
>>> collection_word = collection_number.extract()[0]
>>> import re
>>> reg_str = '.*(\d+).*'
>>> re.findall(reg_str,collection_word)
['1']
>>> collection_number = int(re.findall(reg_str,collection_word)[0])
>>> collection_number
1
>>> comment_number = response.xpath('//span[@class="btn-bluet-bigger href-style hide-on-480"]/text()')
>>> comment_number
[<Selector xpath='//span[@class="btn-bluet-bigger href-style hide-on-480"]/text()' data=' 評論'>]
>>> comment_number.extract()[0]
' 評論'
上是在cmd中的測試過程,可以看出來,我基本上都是用的都是//span[@data-book-type="1"]這種格式的Xpath,而非像FireFox瀏覽器上複製的Xpath,原因有兩點:
1.從外形來看,顯然我使用的這種Xpath要更好,至少長度上少很多(特別對於比較深的數據,如果像
`FireFox`這種,可能長度大於100也不奇怪)
2.從性能上來看,我是用的這種形式匹配更加準確,如果莫個頁面包含js加載的數據(也包含div,p,a
等標籤),如果我們直接分析`FireFox`這種Xpath,可能會出錯。
建議:
(1)決心想學好的,把本文二中的Xpath語法好好記一下,練習一下;
(2)爬取網頁抓取數據儘量用谷歌瀏覽器。
代碼:
import scrapy
import re
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['blog.jobbole.com']
start_urls = ['http://blog.jobbole.com/114256/']
def parse(self, response):
re01_seletor = response.xpath('//*[@id="post-114256"]/div[1]/h1/text()')
re01_title = re01_seletor.extract()
data_selector = response.xpath('//p[@class="entry-meta-hide-on-mobile"]/text()')
data_str = data_selector.extract()[0].strip()
data_time = data_str.replace('·','').strip()
praise_number = int(response.xpath('//h10[@id="114256votetotal"]/text()').extract()[0])
collection_str = response.xpath('//span[@data-book-type="1"]/text()').extract()[0]
reg_str = '.*(\d+).*'
collection_number = int(re.findall(reg_str,collection_str)[0])
print("文章標題:"+re01_title[0])
print("發布日期:"+data_time)
print("點讚數:"+str(praise_number))
print("收藏數:"+str(collection_number))
運行結果:
文章標題:Linux 內核 Git 歷史記錄中,最大最奇怪的提交信息是這樣的
發布日期:2018/08/08
點讚數:1
收藏數:2
學完這一期,大家應該能感受到爬蟲的誘惑了哈,雖然現在我們還只是爬取的一個頁面的文章標題等基本數據,最重要的是學會如何在cmd和pycharm中啟動我們的爬蟲項目和Xpath的學習,下一期,我將帶大家使用CSS選擇器,看看那個更好用,哈哈哈!