python利用scrapy框架爬取起点

先上自己做完之后回顾细节和思路的东西,之后代码一起上。

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 re
from urllib.request import urlopen
from scrapy.http import Request
# from urllib.request import Request
from bs4 import BeautifulSoup
from lxml import etree
import pymongo
import scrapy
from scrapy.selector import HtmlXPathSelector
client = pymongo.MongoClient(host="127.0.0.1")
db = client.QiDian
collection = db.Novelclass          #表名classification

import 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 re
from urllib.request import urlopen
from scrapy.http import Request
import pymongo
import scrapy
from time import sleep
from scrapy.selector import HtmlXPathSelector

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

import redis  # 导入redis数据库

r = redis.Redis(host=‘127.0.0.1‘, port=6379, db=0)

ii = 0

class 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 re
from urllib.request import urlopen
from scrapy.http import Request
import pymongo
import scrapy
from time import sleep
from scrapy.selector import HtmlXPathSelector
from bson.objectid import ObjectId

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

import redis  # 导入redis数据库

r = redis.Redis(host=‘127.0.0.1‘, port=6379, db=0)

# ii = 0

class 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 re
from urllib.request import urlopen
from scrapy.http import Request
import pymongo
import scrapy
from time import sleep
from scrapy.selector import HtmlXPathSelector
from bson.objectid import ObjectId

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

import 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 re
from urllib.request import urlopen
from scrapy.http import Request
import pymongo
import scrapy
from time import sleep
from scrapy.selector import HtmlXPathSelector
from bson.objectid import ObjectId

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

import 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()

  好了 ,大功告成

时间: 2024-08-29 04:09:54

python利用scrapy框架爬取起点的相关文章

基于python的scrapy框架爬取豆瓣电影及其可视化

1.Scrapy框架介绍 主要介绍,spiders,engine,scheduler,downloader,Item pipeline scrapy常见命令如下: 对应在scrapy文件中有,自己增加爬虫文件,系统生成items,pipelines,setting的配置文件就这些. items写需要爬取的属性名,pipelines写一些数据流操作,写入文件,还是导入数据库中.主要爬虫文件写domain,属性名的xpath,在每页添加属性对应的信息等. movieRank = scrapy.Fie

python 使用scrapy框架爬取一个图书网站的信息

1.新建项目 scrapy start_project book_project 2.编写items类 3.编写spider类 # -*- coding: utf-8 -*- import scrapy from book_project.items import BookItem class BookInfoSpider(scrapy.Spider): name = "bookinfo"#定义爬虫的名字 allowed_domains = ["allitebooks.com

03_使用scrapy框架爬取豆瓣电影TOP250

前言: 本次项目是使用scrapy框架,爬取豆瓣电影TOP250的相关信息.其中涉及到代理IP,随机UA代理,最后将得到的数据保存到mongoDB中.本次爬取的内容实则不难.主要是熟悉scrapy相关命令以及理解框架各部分的作用. 1.本次目标 爬取豆瓣电影TOP250的信息,将得到的数据保存到mongoDB中. 2.准备工作 需要安装好scrapy以及mongoDB,安装步骤这里不做赘述.(这里最好是先了解scrapy框架各个部分的基本作用和基础知识,这样方便后面的内容的理解.scrapy文档

python爬虫---scrapy框架爬取图片,scrapy手动发送请求,发送post请求,提升爬取效率,请求传参(meta),五大核心组件,中间件

# settings 配置 UA USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36' 一丶scrapy的图片数据爬取(流数据的爬取) ? scrapy中封装好了一个管道类(ImagesPipeline),基于该管道类可以实现图片资源的请求和持久化存储 编码流程: 爬虫文件中解析出图片的地址 将

scrapy框架爬取豆瓣读书(1)

1.scrapy框架 Scrapy,Python开发的一个快速.高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy用途广泛,可以用于数据挖掘.监测和自动化测试. Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改.它也提供了多种类型爬虫的基类,如BaseSpider.sitemap爬虫等,最新版本又提供了web2.0爬虫的支持. 主要组件: 2.快速开始 scrapy startproject douban cd到douban根目录

使用scrapy框架爬取蜂鸟论坛的摄影图片并下载到本地

目标网站:http://bbs.fengniao.com/使用框架:scrapy 因为有很多模块的方法都还不是很熟悉,所有本次爬虫有很多代码都用得比较笨,希望各位读者能给处意见 首先创建好爬虫项目,并使用crawl模板创建爬虫文件 通过观察论坛的规律得出,很多贴子的页数往往大于一页,那么要将贴子里各页的图片下载到同一文件夹内,并且不能重名,就是获取到当前的页码数,已页码数+自然数的方式命令文件.发现scrapy自动爬虫会爬很多重复的页面,度娘后得出两个解决方法,第一个是用布隆过滤器,布隆过滤器相

scrapy框架爬取小说信息

1.爬取目标网站:http://www.zhaoxiaoshuo.com/all.php?c=0&o=0&s=0&f=2&l=0&page=1 2.爬取目标网站信息:小说类型  小说书名  小说作者  小说字数  小说投票数  小说搜藏数  小说状态 3.scrapy框架结构: zhaoxiaoshuo zhaoxiaoshuo spiders __init__.py zhaoxiaoshuo.py items.py middlewares.py pipelines

Python的scrapy之爬取链家网房价信息并保存到本地

因为有在北京租房的打算,于是上网浏览了一下链家网站的房价,想将他们爬取下来,并保存到本地. 先看链家网的源码..房价信息 都保存在 ul 下的li 里面 ? 爬虫结构: ? 其中封装了一个数据库处理模块,还有一个user-agent池.. 先看mylianjia.py # -*- coding: utf-8 -*- import scrapy from ..items import LianjiaItem from scrapy.http import Request from parsel i

scrapy框架爬取糗事百科

在编写案例之前首先理解几个问题,1:什么是爬虫2:为什么说python是门友好的爬虫语言?3:选用哪种框架编写爬虫程序 一:什么是爬虫? 爬虫 webSpider 也称之为网络蜘蛛,是使用一段编写好的代码所生成的应用程序使其游弋于互联网这个庞大的体系中,帮助我们将想要的内容从目标服务器中搬到我们本地,通 过解析将所需要的数据结构化入库,为企业或个人决策提供依据.比如股票走势,某产品在淘宝上现存的经销商数量及销量等等 二:为什么说python是门友好的爬虫语言? 语言只是门工具,不同的语言侧重的领