scrapy爬虫爬取17k小说网全部章节信息(MongoDB,分页)

跟着教程爬取京东的时候,一会爬出来,一会儿爬不出来,京东反扒挺厉害啊。还是17k好爬一些。跟着教程走,还是出不来结果,看着自己的代码没错啊。使用17k一试,果然很顺利啊。看来目前也只会爬一些简单的网站,如果网站有反爬虫举措,那我就捉襟见肘了。

17k小说网分类中小说还是挺多的,为了方便查看结果,就缩小了小说书籍的范围。

【图片】

今天是2023年10月19日, AM 11:02:48,今天csdn图片出错了,不管是用什么浏览器,还是使用剪切板粘贴,上传图片,都失败了,文章里加不了图片。

这样只有6页,100多条结果,爬起来也快一些。

多练习,多看教程,原来代码是这个意思啊。刚开始,只会照着教程抄代码,囫囵吞枣,先有个大概的了解和熟悉,现在要慢慢深入理解代码的含义了。原来scrapy爬虫里面也是可以递归函数的,只是自己不会罢了。

app.py

from typing import Any

import scrapy
from scrapy import Request
from scrapy.http import Response
import re
from ..items import Scrapy05Item


class AppSpider(scrapy.Spider):
    name = "app"
    allowed_domains = ["www.17k.com"]
    # start_urls = ["https://www.17k.com/all/book/2_0_0_0_0_0_0_0_1.html"]
    start_urls = ["https://www.17k.com/all/book/2_21_115_1_3_0_1_0_1.html"]


    def parse(self, response):
        # 获取首页数据
        links = response.xpath('//td[@class="td4"]/a/@href').extract()
        for index, link in enumerate(links):
            link = "https:" + link
            yield scrapy.Request(url=link, callback=self.parse_detail)
        # 翻页,函数递归
        exp = re.compile('book/2_21_115_1_3_0_1_0_(\d*?).html')
        result = exp.findall(response.url)[0]
        page = int(result) + 1
        if len(links) != 0:
            next_url = "https://www.17k.com/all/book/2_21_115_1_3_0_1_0_{}.html".format(page)
            # print(next_url)
            yield scrapy.Request(url=next_url, callback=self.parse)


    def parse_detail(self, response):
        item = Scrapy05Item()
        book_type = response.xpath('//div[@class="infoPath"]/a[3]/text()').get()
        title = response.xpath('//div[@class="infoPath"]/a[4]/text()').get()
        chapter = response.xpath('//*[@id="readArea"]/div[1]/h1/text()').get()
        content = response.xpath('//*[@id="readArea"]/div[1]/div[2]/p[1]/text()').get()
        if book_type is not None:
            item["book_type"] = book_type
            item["title"] = title
            item["chapter"] = chapter
            item["content"] = content
        print(book_type, title, chapter, content[:10])
        yield item

使用正则表达式获取当前链接中的翻页参数,就是变化的数值,让它+1,形成新的链接。yield scrapy.Request()不仅可以调用其他函数,还可以递归自己,为啥之前没有想到呢?看来合适的教程就是捷径啊。

items.py

import scrapy


class Scrapy05Item(scrapy.Item):

    book_type = scrapy.Field()
    title = scrapy.Field()
    chapter = scrapy.Field()
    content = scrapy.Field()
    pass

pipelines.py

import pymongo


class Scrapy05Pipeline:
    def __init__(self):
        self.res = None
        print("-" * 10, "开始", "-" * 10)
        self.client = pymongo.MongoClient("mongodb://localhost:27017")
        self.db = self.client["17k"]
        self.collection = self.db["chapter"]
        self.collection.delete_many({})  # 清空MongoDB

    def process_item(self, item, spider):
        self.res = self.collection.insert_one(dict(item))
        # print("self.res.inserted_id:", self.res.inserted_id)
        return item

    def __del__(self):
        print("-" * 10, "结束", "-" * 10)

越来越发现,pipelines里面的代码,都成固定的了,几乎不用修改,可以拿之前的直接用。

settings.py

BOT_NAME = "scrapy_05"

SPIDER_MODULES = ["scrapy_05.spiders"]
NEWSPIDER_MODULE = "scrapy_05.spiders"


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36"

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
LOG_LEVEL = "ERROR"

ITEM_PIPELINES = {
   "scrapy_05.pipelines.Scrapy05Pipeline": 300,
}

附上python截取字符串的操作代码:https://www.ycpai.cn/python/xBRw8f2K.html

在Python中,可以通过切片操作来截取字符串。切片操作可以通过指定起始位置和结束位置来截取一个字符串的一部分,语法如下:

```python

string[start:end]

```

其中,start表示起始位置,end表示结束位置。需要注意的是,切片操作是左闭右开的,即包含起始位置,不包含结束位置。如果不指定start,则默认从字符串首字符开始截取;如果不指定end,则默认截取到字符串末尾。

下面是一些切片操作的示例:

```python

string = "Hello, World!"

# 截取前5个字符

print(string[:5]) # 输出:Hello

# 截取第6个字符到字符串末尾

print(string[6:]) # 输出:World!

# 截取第3个字符到第8个字符

print(string[2:8]) # 输出:llo, W

```

2. 使用split方法截取字符串

在Python中,还可以使用split方法来截取字符串。split方法可以通过指定分隔符来分隔字符串,并返回分隔后的字符串列表。语法如下:

```python

string.split(separator)

```

其中,separator表示分隔符。如果不指定分隔符,则默认使用空格作为分隔符。

下面是一些split方法的示例:

```python

string = "Hello, World!"

# 使用逗号分隔字符串

print(string.split(",")) # 输出:['Hello', ' World!']

# 使用空格分隔字符串

print(string.split()) # 输出:['Hello,', 'World!']

```

3. 使用正则表达式截取字符串

在Python中,也可以使用正则表达式来截取字符串。正则表达式可以匹配字符串中的某个模式,并返回匹配的结果。Python中的re模块提供了正则表达式的支持。语法如下:

```python

re.findall(pattern, string)

```

其中,pattern表示正则表达式模式,string表示要匹配的字符串。re.findall方法会返回所有匹配的结果,以列表的形式返回。

下面是一些使用正则表达式截取字符串的示例:

```python

import re

string = "Hello, World!"

# 匹配所有以大写字母开头的单词

print(re.findall(r'\b[A-Z]\w+', string)) # 输出:['Hello', 'World']

# 匹配所有以小写字母开头的单词

print(re.findall(r'\b[a-z]\w+', string)) # 输出:['ello', 'orld']

```

4. 使用字符串方法截取字符串

在Python中,还可以使用字符串方法来截取字符串。Python中的字符串方法非常丰富,常用的有find、index、replace等。这里只介绍find和index方法。

find方法可以在字符串中查找子串,并返回子串第一次出现的位置。如果找不到子串,则返回-1。语法如下:

```python

string.find(substring)

```

其中,substring表示要查找的子串。

index方法和find方法类似,不同之处在于如果找不到子串,则会抛出ValueError异常。语法如下:

```python

string.index(substring)

```

下面是一些使用find和index方法截取字符串的示例:

```python

string = "Hello, World!"

# 查找子串的位置

print(string.find("World")) # 输出:7

print(string.index("World")) # 输出:7

# 查找不存在的子串

print(string.find("Python")) # 输出:-1

# print(string.index("Python")) # 抛出ValueError异常

```

综上所述,本文介绍了Python中截取字符串的几种方法,包括切片、split方法、正则表达式和字符串方法。不同的方法适用于不同的场景,需要根据实际情况选择。掌握这些方法可以帮助我们更好地处理字符串,并从中获取需要的信息。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

andux

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值