scrapy爬取CSDN論壇問題及內容
爬蟲相信大家都有所瞭解,我對爬蟲就不做詳細介紹了。本次我決定使用scrapy爬取CSDN論壇釋出的問題以及回答的內容。
首先,我們需要建立一個scrapy專案。
scrapy startproject test1
然後進入scrapy專案中,建立一個爬蟲。
#進入scrapy專案中
cd test1
#建立爬蟲
scrapy genspider csdn_spider bbs.csdn.net
建立爬蟲時,前兩個引數是固定的,第三個引數是你要建立的爬蟲檔案的名字,第四個引數是你要爬取的網站的網址,此處我們先隨便寫上一個。四個引數缺一不可。
接下來我們開啟我們的專案,找到spider資料夾中我們剛建立的 'csdn_spider.py'檔案。下面我們就要開始我們的爬蟲專案了。
先對CSDN論壇進行分析,我們發現論壇的分頁是比較簡單的,每一頁的網址只有特定地方的數字變了一下。所以我們可以建立一個函式對論壇每一頁的url進行拼接。
#拼接url
def joint_url(url):
# for i in range(1,101):
#此處範圍可以先改小點進行測試,測試成功後可以再進行增大範圍的操作。
return [url.format(i) for i in range(1,10)]
下面分析每一個問題的url。我們會發現每個問題的url是這樣的。
<a href="/topics/392451197" class="topic_title" target="_blank" title="關於讀取EXCEL出現亂碼的問題">關於讀取EXCEL出現亂碼的問題</a>
這個超連結是不完整的,所以我們需要再寫一個函式拼接問題的url。
#拼接各個問題的url
def question_url(url):
#篩選出符合條件的url(只有滿足條件的才是問題的url)
if '/topics' in url:
return "https://bbs.csdn.net"+url
else:
return None
網址都得到了,那麼下面就可以爬取網頁,並分析網頁中我們想要得到的內容了。
下面就開始爬蟲的整個流程。
首先,確定要爬取的種子網頁。
因為我們設定了url拼接,所以我們的種子網頁是多個,這裡展示一下。
#匯入類庫
import scrapy
from scrapy import Request
class CsdnspiderSpider(scrapy.Spider):
#爬蟲名字,用來啟動爬蟲
name = 'csdn_spider'
#過濾掉不滿足條件的網址
allowed_domains = ['bbs.csdn.net']
def __init__(self):
#種子網址,與上面定義的拼接函式搭配使用。
self.urls = 'https://bbs.csdn.net/forums/OL_Script?page={}'
此處函式名必須是start_requests
def start_requests(self):
#迴圈訪問每一頁
for url_str in joint_url(self.urls):
#迭代器,引數1:訪問網站url,引數2:回撥函式,函式名必須是parse
yield Request(url=url_str,callback=self.parse)
獲得返回的網頁內容後,對內容進行篩選
#此處函式名必須是parse
def parse(self, response):
"""
提取每一頁中的問題
:param response:
:return:
"""
#使用xpath,匹配出問題的連結
all_title_urls = response.xpath('//td[@class="forums_topic"]/a/@href').extract()
for one_title in all_title_urls:
#完整的每個問題的url
full_url = question_url(one_title)
if full_url:
#下面的回撥函式函式名可以是其他的,只有第一個回撥函式名必須是parse。
yield Request(url=full_url,callback=self.question)
此時,我們需要找到 'item.py'檔案,它的作用就跟Django中 'models.py' 相同。然後在裡面輸入以下程式碼。
class CsdnspiderItem(scrapy.Item):
title = scrapy.Field()
content = scrapy.Field()
接下來回到 'csdn_spider.py' 檔案中,首先在最上方需要匯入剛才建立的類。
from test1.items import CsdnspiderItem
再對每一個問題網址裡面的內容進行篩選。
def question(self,response):
"""
提取每個問題中的回答內容
:param response:
:return:
"""
# print(response.body)
try:
one_question_title = response.xpath('//span[@class="title text_overflow"]/text()').extract()
one_question_title = one_question_title[0]
except:
one_question_title = 'none'
try:
one_question_contents = response.xpath('//div[@class="post_body post_body_min_h"]/text()').extract()
except:
one_question_contents = 'none'
contents_str = ''
for i in one_question_contents:
contents_str += i
contents_str = ' '.join(contents_str.split())
item = CsdnspiderItem()
item["title"] = one_question_title
item["content"] = contents_str
yield item
資料現在已經有了,那麼我們把資料存到哪裡呢?不要著急,scrapy已經為我們考慮到了。開啟 'piplines.py' 檔案,在這裡,我們將進行我們的資料庫儲存操作。這裡我們使用sqlite資料庫。
import sqlite3
class CsdnspiderPipeline(object):
def __init__(self):
self.conn = sqlite3.connect('./../csdn.db')
self.cur = self.conn.cursor()
self.cur.execute(
"create table IF NOT EXISTS infos(id integer primary key autoincrement, question text,answer text);")
self.conn.commit()
def process_item(self, item, spider):
self.cur.execute('insert into infos(question,answer) values(?,?)',[item['title'],item['content']])
self.conn.commit()
return item
注意,我們還需要去'setting.py'檔案中設定一下才可以使用。
ITEM_PIPELINES = {
'test1.pipelines.CsdnspiderPipeline': 300,
}
下面,我們在終端中輸入 ‘scrapy crawl csdn_spider’就可以執行爬蟲了。
有的時候,這樣容易被封掉,我們可以使用瀏覽器模擬的操作,找到 ‘middlewares.py’ 檔案,這時scrapy的中介軟體,我們在這裡寫瀏覽器模擬的類。
from scrapy.http import HtmlResponse
from selenium.common.exceptions import TimeoutException
import time
from selenium import webdriver
from selenium.webdriver.firefox.options import Options as FOptions
class SeleniumMiddleware(object):
def __init__(self):
self.options = FOptions()
self.options.add_argument('-headless') # 無頭模式
self.browser = webdriver.Firefox(executable_path='E:\FireFox\geckodriver\geckodriver.exe',
firefox_options=self.options)
def process_request(self,request,spider):
try:
print("url is ::::::",request.url)
self.browser.get(request.url)
except TimeoutException as e:
print("超時")
time.sleep(2)
return HtmlResponse(url=self.browser.current_url,body=self.browser.page_source,
encoding="utf-8",request=request)
然後再 'setting.py' 中設定
DOWNLOADER_MIDDLEWARES = {
'test1.middlewares.SeleniumMiddleware': 543,
}
瀏覽器模擬需要用到的東西,在我的瀏覽器模擬的那個部落格中有講到,這裡就不過多講了。
現在算是一個比較完整的爬蟲專案了。總的來說,比較簡單,適合初學者入門學習。