python利用scrapy架構爬取起點

來源:互聯網
上載者:User

標籤:更新   tar   lambda   接下來   utf-8   cti   名稱   $set   extract   

先上自己做完之後回顧細節和思路的東西,之後代碼一起上。

1.Mongodb 建立一個叫QiDian的庫,
然後建立了一個叫Novelclass(小說類別表)
Novelclass(可以把一級類別二級類別都存進去:玄幻--一級類別,東方玄幻--二級類別)的表

client = pymongo.MongoClient(host="127.0.0.1")
db = client.QiDian
collection = db.Novelclass

2.用parse回調方法,獲得一級類別。迴圈取出(要注意拼接問題--"https:"+)。
並將一級類別存入Mongodb(注意一級類別的pid此時為None)。一級類別的連結不需要存入redis資料庫(一級類別的連結只為了找到二級)。

3.此時擷取二級類別(東方玄幻),此時回調parse方法
取得二級類別(名稱+連結)同時二級類別名稱與一級類別名稱放入同一個Mongodb(Novelclass)裡,連結則存入redis庫(classid = self.insertMongo(name[0],pid),self.pushRedis(classid,url,pid))

def insertMongo(self,classname,pid):
classid = collection.insert({‘classname‘:classname,‘pid‘:pid})
return classid
def pushRedis(self,classid,url,pid,):
novelurl = ‘%s,%s,%s‘ %(classid,url,pid)
r.lpush(‘novelurl‘,novelurl)
此時第一步完成。一級類別與二級類別都擷取到。

4.有了二級連結(東方玄幻),接下來要擷取每個二級連結下的小說名字與連結。
(同樣,將小說名字存入Mongodb--Novelname表,連結存入到redis--novelnameurl)
這裡注意我們定義了一個字典,(為了我們能取到arr[0]--也就是二級的id(東方玄幻的id))
因為我們要確定每本小說是屬於哪一類(東方玄幻或者西方玄幻。)
dict = {}
novelurl = bytes.decode(item)
arr = novelurl.split(‘,‘) # 分割字串
qidianNovelSpider.start_urls.append(arr[1])
pid = arr[0]二級(東方玄幻)的_id,也就是流水id,注意不要取成東方玄幻的pid(他的pid則是玄幻的id)
url = arr[1]二級(東方玄幻)的連結
self.dict[url] = {"pid":pid,"num":0}
此時num是為了控制我們爬幾頁。
同樣一個parse回調方法,因為我們要去下一頁,所以我們要確定取到的連結是相同
classInfo = self.dict[response.url]--response.url固定就是這麼寫
pid = classInfo[‘pid‘]--確定了那麼pid=arr[0]
num = classInfo[‘num‘]

if num>3:--------此處num的用處就來了,我只去每個二級連結的前4頁(因為你是取完了前四頁才迴圈回來,所以不是3頁)
return None
同樣注意連結的拼接問題。(不然會報keyerror錯誤)
取到就分別把名字和連結存入Mongodb和redis
classid = collection.insert({‘novelname‘: name, ‘pid‘: pid})此時pid就是(東方玄幻的id也就是唯一id,而不是玄幻的id)
print(name)
self.pushRedis(classid, c, pid)-----(classid就是流水id--_id,c是拼接後的連結,pid則是東方玄幻的id)
現在分類第一頁能取,現在開始寫下一頁的,
hxs = HtmlXPathSelector(response)
hx = hxs.select(‘//li[@class="lbf-pagination-item"]/a[@class="lbf-pagination-next "]‘)
urls = hx.select("@href").extract()
d = "https:" + urls[0]
classInfo[‘num‘] +=1-------(每取一頁,num就+1)
self.dict[d] = classInfo
print(d)
request = Request(d, callback=self.parse)-------(調用上一個回調方法,也就是取那頁名字和連結那個地方。)
yield request
這段代碼就是為了取到下一頁的連結然後去調用上一個方法,把下一頁的名字和連結都拿下來。
之後就是入庫操作,上面有。
Mongodb---Novelname,Redis----novelnameurl

5.接下來要做的是更新書籍資訊(也就是把novelname表更新)
現在Mongodb----novelname表只有書籍名字,而沒有具體資訊。(所以要把作者,簽約,連載或完結,免費或Vip都更新進去)
注意:我是更新而不是建立表。所以說我取得連結同樣還是novelnameurl裡的,只不過把得到的資訊不用另起一個表,而是插入之前有的novelname
client = pymongo.MongoClient(host="127.0.0.1")
db = client.QiDian
collection = db.Novelname(這個表會同上一個py檔案的相同)
同樣的,我還是需要(東方玄幻的_id)
pid = arr[0]
url = arr[1]
self.dict[url] = {"pid":pid}
不過這次是為了更新Mongodb資料庫準備的,
nameInfo = self.dict[response.url]
pid1 = nameInfo[‘pid‘]
pid = ObjectId(pid1)-------(此處是為了等我更新時,"_id"這個鍵對應相同的ObjectId)
之後就是取資訊。
hx = hxs.select(‘//div[@class="book-info "]/h1/span/a[@class="writer"]‘)
hx1 =hxs.select(‘//p[@class="tag"]/span[@class="blue"]‘)
hx2 =hxs.select(‘//p[@class="tag"]/a[@class="red"]‘)
for secItem in hx:
writer = secItem.select("text()").extract()
print(writer)
for secItem1 in hx1:
state = secItem1.select("text()").extract()
print(state)
for secItem2 in hx2:
classes = secItem2.select("text()").extract()
print(classes)
可以這麼取並且列印出來也是順序,而不是說先把每個小說的writer都列印出來,在列印state。
更新Mongodb----novelname表
db.Novelname.update({"_id": pid}, {"$set": {"writer": writer, "state": state, "classes": classes}})
此時上面的pid就起了作用,更新完成。

6.接下來就是爬取每本小說的章節名和連結了。(同上面的取小說名字,只不過更簡單,沒有下一頁)
這裡還是要注意id問題,章節名稱和連結都要對應上每本小說自己的_id(而不是二級的pid)。
插入Mongodb-----Chaptername,redis----chapterurl

7.最後一步,根據章節連結取小說內容,因為我們取了每本小說的所有的連結,所以也不用考慮下一章的問題。
同時,我們取完內容,也要將內容更新到章節表裡,這裡我們需要注意的是,我們取得小說的內容是p標籤的(是字串形式),
所以說我們插入Mongodb就遇到了問題,字串放進去,一條就給你一個id,這不是想要的,要的是一章小說的就一個_id就好。
用到了字串拼接。
ii=""-------先給個空的
hx = hxs.select(‘//div[@class="read-content j_readContent"]/p‘)

for secItem in hx:
contents = secItem.select("text()").extract()
content1 = contents[0]-----取到一個p下的內容
# print(content1)
ii=content1+ii-------取到的就加進去
print(ii)------我們想要的結果
最後更新進Chaptername,
db.Chaptername.update({"_id": pid}, {"$set": {"content": ii}})


Mongodb(Novelclass(一級,二級--玄幻,東方玄幻);Novelname(小說名字,----之後更新進作者,連載等等);Chaptername(章節名字,----更新進章節對應的內容))
Redis(novelurl(單純二級連結---東方玄幻,用不到一級連結);novelnameurl(小說名字連結);chapterurl(章節連結))

 

第一個py檔案

# -*- coding: utf-8 -*-import refrom urllib.request import urlopenfrom scrapy.http import Request# from urllib.request import Requestfrom bs4 import BeautifulSoupfrom lxml import etreeimport pymongoimport scrapyfrom scrapy.selector import HtmlXPathSelectorclient = pymongo.MongoClient(host="127.0.0.1")db = client.QiDiancollection = db.Novelclass          #表名classificationimport redis        #匯入redis資料庫r = redis.Redis(host=‘127.0.0.1‘, port=6379, db=0)class qidianClassSpider(scrapy.Spider):    name = "qidianClass2"    allowed_domains = ["qidian.com"]   #允許訪問的域    start_urls = [        "https://www.qidian.com/all",    ]    #每爬完一個網頁會回調parse方法    def parse(self, response):        hxs = HtmlXPathSelector(response)        hx = hxs.select(‘//div[@class="work-filter type-filter"]/ul[@type="category"]/li[@class=""]/a‘)        for secItem in hx:            url = secItem.select("@href").extract()            c = "https:"+url[0]            name = secItem.select("text()").extract()            classid = self.insertMongo(name[0],None)            print(c)            # a = db.Novelclass.find()            # for item in a:            #     print(item.get(‘_id‘))            # b = item.get(‘_id‘)            # novelurl = ‘%s,%s‘ % (item.get(‘_id‘), c)            # r.lpush(‘novelurl‘, novelurl)            request = Request(c,callback=lambda response,pid=str(classid):self.parse_subclass(response,pid))            yield request    def parse_subclass(self, response,pid):        hxs = HtmlXPathSelector(response)        hx = hxs.select(‘//div[@class="sub-type"]/dl[@class=""]/dd[@class=""]/a‘)        for secItem in hx:            urls = secItem.select("@href").extract()            url = "https:" + urls[0]            name = secItem.select("text()").extract()            classid = self.insertMongo(name[0],pid)            self.pushRedis(classid,url,pid)    def insertMongo(self,classname,pid):        classid = collection.insert({‘classname‘:classname,‘pid‘:pid})        return classid    def pushRedis(self,classid,url,pid,):        novelurl = ‘%s,%s,%s‘ %(classid,url,pid)        r.lpush(‘novelurl‘,novelurl)

  第二個py檔案

# -*- coding: utf-8 -*-import refrom urllib.request import urlopenfrom scrapy.http import Requestimport pymongoimport scrapyfrom time import sleepfrom scrapy.selector import HtmlXPathSelectorclient = pymongo.MongoClient(host="127.0.0.1")db = client.QiDiancollection = db.Novelnameimport redis  # 匯入redis資料庫r = redis.Redis(host=‘127.0.0.1‘, port=6379, db=0)ii = 0class qidianNovelSpider(scrapy.Spider):    name = "qidianClass3"    allowed_domains = ["qidian.com"]    dict = {}    start_urls = []    def __init__(self):  # 定義一個方法        a = r.lrange(‘novelurl‘, 0, -1)        # ii = 0        for item in a:            novelurl = bytes.decode(item)            arr = novelurl.split(‘,‘)  # 分割字串            qidianNovelSpider.start_urls.append(arr[1])            pid = arr[0]            url = arr[1]            self.dict[url] = {"pid":pid,"num":0}            # ii +=1            # if ii>3:            #     break                # qidianNovelSpider.start_urls = start_urls            # print(start_urls)    def parse(self, response):        classInfo = self.dict[response.url]        pid = classInfo[‘pid‘]        num = classInfo[‘num‘]        # print(self.dict)        if num>3:            return None        hxs = HtmlXPathSelector(response)        hx = hxs.select(‘//div[@class="book-mid-info"]/h4/a‘)        for secItem in hx:            url = secItem.select("@href").extract()            c = "https:" + url[0]            name = secItem.select("text()").extract()            classid = collection.insert({‘novelname‘: name, ‘pid‘: pid})            print(name)            self.pushRedis(classid, c, pid)        print(‘-----------遞迴--------------‘)        hxs = HtmlXPathSelector(response)        hx = hxs.select(‘//li[@class="lbf-pagination-item"]/a[@class="lbf-pagination-next "]‘)        urls = hx.select("@href").extract()        d = "https:" + urls[0]        classInfo[‘num‘] +=1        self.dict[d] = classInfo        print(d)        request = Request(d, callback=self.parse)        yield request        print(‘--------end--------------‘)    def pushRedis(self, classid, c, pid):        novelnameurl = ‘%s,%s,%s‘ % (classid, c, pid)        r.lpush(‘novelnameurl‘, novelnameurl)

  第三個py檔案

# -*- coding: utf-8 -*-import refrom urllib.request import urlopenfrom scrapy.http import Requestimport pymongoimport scrapyfrom time import sleepfrom scrapy.selector import HtmlXPathSelectorfrom bson.objectid import ObjectIdclient = pymongo.MongoClient(host="127.0.0.1")db = client.QiDiancollection = db.Novelnameimport redis  # 匯入redis資料庫r = redis.Redis(host=‘127.0.0.1‘, port=6379, db=0)# ii = 0class qidianNovelSpider1(scrapy.Spider):    name = "qidianClass4"    allowed_domains = ["qidian.com"]    dict = {}    start_urls = []    def __init__(self):  # 定義一個方法        a = r.lrange(‘novelnameurl‘, 0, -1)        # ii = 0        for item in a:            novelnameurl = bytes.decode(item)            arr = novelnameurl.split(‘,‘)  # 分割字串            qidianNovelSpider1.start_urls.append(arr[1])            pid = arr[0]            url = arr[1]            self.dict[url] = {"pid":pid}    def parse(self, response):        nameInfo = self.dict[response.url]        pid1 = nameInfo[‘pid‘]        pid = ObjectId(pid1)        print(pid)        hxs = HtmlXPathSelector(response)        hx = hxs.select(‘//div[@class="book-info "]/h1/span/a[@class="writer"]‘)        hx1 =hxs.select(‘//p[@class="tag"]/span[@class="blue"]‘)        hx2 =hxs.select(‘//p[@class="tag"]/a[@class="red"]‘)        for secItem in hx:            writer = secItem.select("text()").extract()            print(writer)        for secItem1 in hx1:            state = secItem1.select("text()").extract()            print(state)        for secItem2 in hx2:            classes = secItem2.select("text()").extract()            print(classes)            # for item in a:            #     b = item.get(‘_id‘)            #     print(b)            db.Novelname.update({"_id": pid}, {"$set": {"writer": writer, "state": state, "classes": classes}})            print(‘------------------------------------------‘)            # classid = collection.insert({‘novelname‘: name, ‘pid‘: Pid})            # print(name)            # self.pushRedis(classid, c, Pid)

  第四個py檔案

# -*- coding: utf-8 -*-import refrom urllib.request import urlopenfrom scrapy.http import Requestimport pymongoimport scrapyfrom time import sleepfrom scrapy.selector import HtmlXPathSelectorfrom bson.objectid import ObjectIdclient = pymongo.MongoClient(host="127.0.0.1")db = client.QiDiancollection = db.Chapternameimport redis  # 匯入redis資料庫r = redis.Redis(host=‘127.0.0.1‘, port=6379, db=0)class qidianNovelSpider1(scrapy.Spider):    name = "qidianClass5"    allowed_domains = ["qidian.com"]    dict = {}    start_urls = []    def __init__(self):  # 定義一個方法        a = r.lrange(‘novelnameurl‘, 0, -1)        # ii = 0        for item in a:            novelnameurl = bytes.decode(item)            arr = novelnameurl.split(‘,‘)  # 分割字串            qidianNovelSpider1.start_urls.append(arr[1])            pid = arr[0]            url = arr[1]            self.dict[url] = {"pid":pid}            print(url)    def parse(self, response):        nameInfo = self.dict[response.url]        pid = nameInfo[‘pid‘]        hxs = HtmlXPathSelector(response)        hx = hxs.select(‘//div[@class="volume-wrap"]/div[@class="volume"]/ul[@class="cf"]/li/a[@target="_blank"]‘)        for secItem in hx:            urls = secItem.select("@href").extract()            url = "https:"+urls[0]            chapter = secItem.select("text()").extract()            print(chapter)            print(url)            classid = collection.insert({‘chaptername‘: chapter, ‘pid‘: pid})            self.pushRedis(classid,url, pid)    def pushRedis(self, classid, url, pid):        chapterurl = ‘%s,%s,%s‘ % (classid, url, pid)        r.lpush(‘chapterurl‘, chapterurl)

  第五個py檔案

# -*- coding: utf-8 -*-import refrom urllib.request import urlopenfrom scrapy.http import Requestimport pymongoimport scrapyfrom time import sleepfrom scrapy.selector import HtmlXPathSelectorfrom bson.objectid import ObjectIdclient = pymongo.MongoClient(host="127.0.0.1")db = client.QiDiancollection = db.Chapternameimport redis  # 匯入redis資料庫r = redis.Redis(host=‘127.0.0.1‘, port=6379, db=0)class qidianNovelSpider1(scrapy.Spider):    name = "qidianClass6"    allowed_domains = ["qidian.com"]    dict = {}    start_urls = []    def __init__(self):  # 定義一個方法        a = r.lrange(‘chapterurl‘, 0, -1)        # ii = 0        for item in a:            chapterurl = bytes.decode(item)            arr = chapterurl.split(‘,‘)  # 分割字串            qidianNovelSpider1.start_urls.append(arr[1])            pid = arr[0]            url = arr[1]            self.dict[url] = {"pid":pid}            # print(url)    def parse(self, response):        nameInfo = self.dict[response.url]        pid1 = nameInfo[‘pid‘]        pid = ObjectId(pid1)        hxs = HtmlXPathSelector(response)        ii=""        hx = hxs.select(‘//div[@class="read-content j_readContent"]/p‘)        for secItem in hx:            contents = secItem.select("text()").extract()            content1 = contents[0]            # print(content1)            ii=content1+ii            # content = bytes(content1,‘GBK‘)        # classid = collection.insert({‘content‘: ii, ‘pid‘: pid1})        db.Chaptername.update({"_id": pid}, {"$set": {"content": ii}})            # print(content)            # f = open(‘1.txt‘,‘wb‘)            # f.write(content)            # f.close()

  好了 ,大功告成

python利用scrapy架構爬取起點

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.