【scrapy爬蟲】結合正則表達式爬取糗事百科段子首頁步驟詳解

手動反爬蟲:原博地址

 知識梳理不易,請尊重勞動成果,文章僅發佈在CSDN網站上,在其他網站看到該博文均屬於未經作者授權的惡意爬取信息

如若轉載,請標明出處,謝謝!

1. 前提說明

前面的item內容字段數據的爬取採用了xpath語法和css語法,那麼這一部分就嘗試着使用re正則表達式來進行,關於基礎scrapy知識可以參看Scrapy安裝、詳細指令參數講解及第一個項目實例

2. 創建項目

在一個指定的文件路徑下,打開cmd,輸入創建爬蟲項目的指令,文件夾創建完成後,並進入提示路徑

scrapy startproject qsbk

→ 輸出的結果爲:(創建文件夾成功後,注意進入這個指定的文件夾下)
在這裏插入圖片描述

3. 創建爬蟲模板

這裏選擇的是basic模板,創建的指令如下

scrapy genspider -t basic jokes qiushibaike.com/text

→ 輸出的結果爲:(會在spiders文件夾下多出一個jokes.py文件)
在這裏插入圖片描述

4. items.py文件修改

根據要爬取的網站的內容,如下,可以確定要爬取的字段數據,共五個字段,分別爲:作者,鏈接,內容,點贊數,評論數(這些都可以在網頁源代碼中找到)
在這裏插入圖片描述
修改的item.py文件如下
在這裏插入圖片描述

5. 爬蟲模板文件修改

5.1 模板可行性檢驗

首先習慣性的創建一個爬蟲模板後,直接打印返回的內容,看看是否可以正常運行,修改最後一行代碼如下,然後在命令行執行爬取的指令
在這裏插入圖片描述
cmd執行的爬取指令

scrapy crawl jokes

輸出的結果中顯示如下(要求必須使用模擬瀏覽器的方式爬取)
在這裏插入圖片描述
進行代碼修改,設置瀏覽器請求頭,baisc模板創建後默認會生成爬取第一頁的網址,也就是start_urls參數,這裏由於要使用請求頭訪問,因此可以把這個參數註釋掉,自己手動設置請求頭和起始網址,需要使用到start_requests函數,注意導入Request方法
在這裏插入圖片描述
保存後在cmd界面執行爬取命令,展示結果如下,可以發現能以正常獲取網頁內容
在這裏插入圖片描述
這一步的檢測非常重要,要養成一個習慣,在爬取內容之前,先測試這個模板是否是直接可用的,然後再進行爬取字段內容代碼的輸入

5.2 相關字段數據爬取

上面添加請求頭之後,就可以正常返回網頁請求的數據了,那麼接下來就是引入正則表達式,進行相關字段數據的爬取。由於是進行正則表達式提取,所以需要在網頁源代碼下進行匹配

1) 段子作者
在這裏插入圖片描述

首先需要導入items.py文件中的類名和re庫,通過上面的信息匹配可以看到作者信息都是在h2標籤中(兩個結果中選擇簡單有規律的標籤),對應的數據爬取的代碼如下

import scrapy
from scrapy.http import Request
from ..items import QsbkItem
import re

class JokesSpider(scrapy.Spider):
	name = 'jokes'
	allowed_domains = ['qiushibaike.com/text']
	# start_urls = ['http://qiushibaike.com/text/']

	def start_requests(self):
		headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
		yield Request('http://qiushibaike.com/text/',headers=headers)

	def parse(self, response):
		item = QsbkItem()
		txt = response.text
		item['name'] = re.findall(r'<h2>\n(.*?)\n</h2>',txt)
		print(item['name'],len(item['name']))

→ 輸出的結果爲:(剛好對應段子首頁的25個作者,後面的計數就是爲了驗證爬取數據的準確性)
在這裏插入圖片描述
2)段子鏈接
在這裏插入圖片描述
選取最近的網頁鏈接,進行信息提取,代碼如下,直接把網址部分替換

item['link'] = re.findall(r'a href="(.*?)" target="_blank" class="contentHerf"',txt)
print(item['link'],len(item['link']))

★★★ 3) 段子內容的匹配
在這裏插入圖片描述
可以看到內容都是在span標籤當中,因此可以嘗試進行獲取,代碼如下

item['content'] = re.findall(r'<span>\n\n\n(.*?)\n\n</span>',txt)
print(item['content'],len(item['content']))

→ 輸出的結果爲:(之前加上的計數,就是爲了驗證爬取數據的準確性,這裏明顯少了數據)
在這裏插入圖片描述
因此就需要進行問題的查找,內容都是在span標籤中,而span標籤太多了,不能作爲查找的關鍵詞(這裏的意思是如果只查找span這個單詞),因此可以查找上面的content標籤,對應的剛好爲25個結果,然後依次查看每個結果,最終發現問題,如下

a. 嘗試着第一次解決問題

第21處,發現多了一個省略號導致並不是兩個回車的格式
在這裏插入圖片描述
第25處,也是和上面一樣
在這裏插入圖片描述
因此代碼就需要進行修改,要求可以匹配到一個或者多個回車換行符,代碼如下,關於正則表達式的匹配模式可以參考正則表達式模式

#\s匹配字符,匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]
item['content'] = re.findall(r'<span>\s+(.*?)\s+</span>',txt)
print(item['content'],len(item['content']))

→ 輸出的結果爲:(這時候卻發現匹配的結果卻多了,存在不需要的信息)
在這裏插入圖片描述
b. 嘗試着第二次解決問題

再進行問題的查找,既然內容前後的回車換行符的問題解決了,那麼就只剩下內容裏面的回車換行符的問題了,因此代碼修改如下

#內容中也存在多行,所以偶多次換行的問題,這裏使用的就是*,匹配零次或者多次的換行符
item['content'] = re.findall(r'<span>\s+(.*?\s*.*?)\s+</span>',txt)
print(item['content'],len(item['content']))

→ 輸出的結果爲:(最後的計數檢驗證明爬取數據成功了)
在這裏插入圖片描述
4) 點贊數匹配
在這裏插入圖片描述
直接可以給出代碼

item['thumb_up'] =  re.findall(r'<i class="number">(.*?)</i> 好笑',txt)
print(item['thumb_up'],len(item['thumb_up']))

5) 評論數匹配
在這裏插入圖片描述
也是可以直接給出代碼

item['comment'] = re.findall(r'<i class="number">(.*?)</i> 評論',txt)
print(item['comment'],len(item['comment']))

5.3 相關字段數據爬取全部代碼

也就是爬蟲模板jokes.py文件中的全部代碼,如下

# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import Request
from ..items import QsbkItem
import re

class JokesSpider(scrapy.Spider):
	name = 'jokes'
	allowed_domains = ['qiushibaike.com/text']
	# start_urls = ['http://qiushibaike.com/text/']

	def start_requests(self):
		headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
		yield Request('http://qiushibaike.com/text/',headers=headers)

	def parse(self, response):
		item = QsbkItem()
		txt = response.text
		item['name'] = re.findall(r'<h2>\n(.*?)\n</h2>',txt)
		item['link'] = re.findall(r'a href="(.*?)" target="_blank" class="contentHerf"',txt)
		item['content'] = re.findall(r'<span>\s+(.*?\s*.*?)\s+</span>',txt)
		item['thumb_up'] =  re.findall(r'<i class="number">(.*?)</i> 好笑',txt)
		item['comment'] = re.findall(r'<i class="number">(.*?)</i> 評論',txt)
		print(item['name'], len(item['name']))
		print(item['link'],len(item['link']))
		print(item['content'],len(item['content']))
		print(item['thumb_up'],len(item['thumb_up']))
		print(item['comment'],len(item['comment']))
		return item

→ 輸出的結果爲:(5個字段的數據量均爲25,證明數據獲取成功)
在這裏插入圖片描述

6. settings.py文件修改

因爲要存儲爬取的數據,所以需要開啓pipeline管道,修改如下
在這裏插入圖片描述

7. pipeline.py文件修改

確保上一步進行操作了,不然的話,即使代碼修改好了也不會保存數據的。在保存數據之前,先查看一下返回的item數據是什麼樣子的,才能繼續下一步操作,很多時候數據的類型並不是我們以爲的那樣子,比如這裏的item就是,看上去像字典,實際上的輸出並不是。

操作如下,註釋掉模板文件的print語句,在pipeline.py文件中打印item數據及類型,代碼如下

class QsbkPipeline(object):
    def process_item(self, item, spider):
    	print(item,type(item))
        return item

在cmd執行爬蟲指令,輸出結果如下
在這裏插入圖片描述
經過查看,發現這種數據轉換成爲字典之後就是字典套列表的形式,可以直接轉化爲pandas中的DataFrame格式,然後生成csv或者xlsx文件,代碼修改如下

#先導入pandas庫
import pandas as pd

class QsbkPipeline(object):
	def process_item(self, item, spider):
		# print(type(item),item)
		df = pd.DataFrame(dict(item)) #轉化爲字典後之間編程DataFrame數據
		df.to_csv('jokes.csv',index=False,encoding='gbk') #注意編碼的格式
		print('Finished!')
		return item

→ 輸出的結果爲:(數據自動按照設置的字段的先後進行輸出了,如過是要在自定義字段輸出,因爲是DataFrame數據,就變得超級簡單了,通過重新制定列順序即可)
在這裏插入圖片描述
至此,結合正則表達式爬取糗事百科段子首頁步驟詳解就梳理完畢,下一個博客更新:自動化模板爬取糗事百科全站段子內容步驟詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章