requests实战 -- 爬取17k免费小说

目标url:小说_17K小说网|最新小说下载-一起免费看小说

网站特色:动态cookie

需要先注册一个账号

网站分为免费小说和vip小说,vip小说只能开头vip才能爬取

需要先将免费小说加入书架,然后进行爬取:

步骤: 模拟登陆爬取数据 -> 爬取章节 -> 爬取每本小说的完整内容

 ⑴ 模拟登陆爬取数据

经过一些列ua、Referer、cookie之后尝试之后,发现cookie是动态的

于是,使用session会话,去动态获取cookie

先退出登陆,打开f12,点击登陆,看请求方式、请求url、以及载荷

 登陆后,手动从首页进入“书架”,会带一个"https://user.17k.com/www/"的Referer

但那并不是真正的ajax请求对应的书架url

直接上代码:

import requests

#模拟登陆17k,获取cookie,并拿到书架里的小说
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
    }

#定义session登陆,不会担心随机cookie,每次访问都带着session
session = requests.session()
session.post("https://passport.17k.com/ck/user/login",
             data = {
                "loginName": "13*********",
                "password": "*******"},
             headers = headers)

#错误的书架ajax请求url
# res = session.get("https://user.17k.com/www/bookshelf/")

#找到真正的书架对应的ajax请求url
res = session.get("https://user.17k.com/ck/author2/shelf?page=1&appKey=2406394919")
res.encoding ="utf-8"    #windows默认gbk,外面要写编码规则
# print(res.text)

#写入是还需要定义编码规则,否则html文件中还是有乱码
# with open("17k.html","w",encoding="utf-8") as f:
#     f.write(res.text)

#将ajax的json数据反序列化为字典,并获取data这个键
data = res.json().get("data")
print(data) #查看data

#取出字典里的每个item
for item in data:
    print(item)

⑵ 爬取章节及链接

由于每本小说的Volume属性值数量不同,这里先爬下来所有的Volume下的所有a标签

import requests
from lxml import etree
#模拟登陆17k,获取cookie,并拿到书架里的小说
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
    }

#定义session登陆,不会担心随机cookie,每次访问都带着session
session = requests.session()
session.post("https://passport.17k.com/ck/user/login",
             data = {
                "loginName": "13*******",
                "password": "*******"},
             headers = headers)

#找到真正的书架对应的ajax请求url
res = session.get("https://user.17k.com/ck/author2/shelf?page=1&appKey=2406394919")
res.encoding ="utf-8"    #windows默认gbk,外面要写编码规则

data = res.json().get("data")

#book已在data中;循环处理每一本书籍
for bookDict in data:
    print(bookDict)
    bookId = bookDict.get("bookId")
    #获取每一本书架书籍的章节页面,通过bookId获取
    #错误路径,没有章节信息
    # res = requests.get(f"https://www.17k.com/list/{bookId}}.html")

    #正确路径:对应页面"点击阅读"后,显示有所有章节的url
    res = requests.get(f"https://www.17k.com/list/{bookId}.html")
    res.encoding = "utf8"

    #解析每一本书籍的章节链接
    selector = etree.HTML(res.text)
    #拿到一本数据对应的所有a标签(作品,正文/章节,外传所有的a标签)
    items = selector.xpath('//dl[@class="Volume"]/dd/a')
    #处理每一本书籍的每一章节信息
    for item in items:
        chapter_href = item.xpath("./@href")[0] #获取a标签里的href
        chapter_title = item.xpath("./span/text()")[0].strip()   #获取a标签里的第一个文本,即章节名
        print("链接:",chapter_href)
        print("章节名:",chapter_title)

    #爬取章节内容:href上面已解析,包含bookId和章节id
        res = requests.get("https://www.17k.com/" + chapter_href)
        res.encoding = "utf8"
        chapter_html = res.text  #获取章节对应的html文件
        print(chapter_html)

        selector = etree.HTML(res.text) #解析章节内容
        #拿到出最后p标签外的所有章节内容对应的p标签,排除最后一个p标签
        chapter_text = selector.xpath('//div[contains(@class,"content")]/div[@class="p"]/p[position()<last()-1]/text()')
        print(chapter_text)

        break

⑶ 爬取每本小说的完整内容

最后:创建总的文件夹、每本书的文件夹、以及每个章节的文件

完整代码如下:

import requests
from lxml import etree
import os
#模拟登陆17k,获取cookie,并拿到书架里的小说
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
    }

#定义session登陆,不会担心随机cookie,每次访问都带着session
session = requests.session()
session.post("https://passport.17k.com/ck/user/login",
             data = {
                "loginName": "1*******",
                "password": "********"},
             headers = headers)

#找到真正的书架对应的ajax请求url
res = session.get("https://user.17k.com/ck/author2/shelf?page=1&appKey=2406394919")
res.encoding ="utf-8"    #windows默认gbk,外面要写编码规则

data = res.json().get("data")

#创建个人书架的文件夹
root_path = "my_books"  #根路径
if not os.path.exists(root_path):
    os.mkdir(root_path)

#book已在data中;循环处理每一本书籍
for bookDict in data:
    print(bookDict)
    bookId = bookDict["bookId"]
    bookName = bookDict["bookName"]

    #创建一个书籍的文件夹
    book_path = os.path.join(root_path,bookName)
    if not os.path.exists(book_path):
        os.mkdir(book_path)

    #获取每一本书架书籍的章节页面,通过bookId获取
    #错误路径,没有章节信息
    # res = requests.get(f"https://www.17k.com/list/{bookId}}.html")

    #正确路径:对应页面"点击阅读"后,显示有所有章节的url
    res = requests.get(f"https://www.17k.com/list/{bookId}.html")
    res.encoding = "utf8"

    #解析每一本书籍的章节链接
    selector = etree.HTML(res.text)
    #拿到一本数据对应的所有a标签(作品,正文/章节,外传所有的a标签)
    items = selector.xpath('//dl[@class="Volume"]/dd/a')
    #处理每一本书籍的每一章节信息
    for item in items:
        chapter_href = item.xpath("./@href")[0] #获取a标签里的href
        chapter_title = item.xpath("./span/text()")[0].strip()   #获取a标签里的第一个文本,即章节名

    #爬取章节内容:href上面已解析,包含bookId和章节id
        res = requests.get("https://www.17k.com/" + chapter_href)
        res.encoding = "utf8"
        chapter_html = res.text  #获取章节对应的html文件

        selector = etree.HTML(res.text) #解析章节内容
        #拿到出最后p标签外的所有章节内容对应的p标签,排除最后一个p标签
        chapter_text = selector.xpath('//div[contains(@class,"content")]/div[@class="p"]/p[position()<last()-1]/text()')

        #进行下载章节,写入文件
        chapter_path = os.path.join(book_path,chapter_title)
        #这里chapter_path加了双引号,就不会生成章节对应的文件。。
        with open(chapter_path,"w",encoding="utf8") as f:
            for line in chapter_text:
                f.write(line + "\n")

        import time
        import random

        time.sleep(random.randint(1,3))
        print(f"{bookName}书籍的{chapter_title}章节下载完成!")

书籍太多,先暂停运行了 


⑷ 功能函数化,优化完整代码

上面的代码是第一版,里面也有一些小细节,但总的来说,内容可以爬下来,也正常生成了想要的3级目录。

但是代码比较乱,所以进行优化:将每一个功能封装为一个函数

import requests
from lxml import etree
import os
import time
import random

#定义session登陆,不会担心随机cookie,每次访问都带着session
session = requests.session()
#模拟登陆17k,获取cookie,并拿到书架里的小说
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" }

#定义登陆17k的函数:
def login():
    session.post("https://passport.17k.com/ck/user/login",
                 data={
                     "loginName": "1*******",
                     "password": "*******"},
                 headers=headers)

#定义获取每本书籍的函数:
def get_shelf_books():
    res = session.get("https://user.17k.com/ck/author2/shelf?page=1&appKey=2406394919")
    res.encoding ="utf-8"    #windows默认gbk,外面要写编码规则
    data = res.json().get("data")
    return data

#定义下载每一本书籍的每一章节信息的函数:
def get_books(data):
    for bookDict in data:
        print(bookDict)
        bookId = bookDict["bookId"]
        bookName = bookDict["bookName"]

        #创建一个书籍的文件夹
        book_path = os.path.join(root_path,bookName)
        if not os.path.exists(book_path):
            os.mkdir(book_path)
        get_chapter(bookName,bookId,book_path)

#定义处理章节内容的函数:
def get_chapter(bookName,bookId,book_path):
    # 爬取每一本书架书籍的章节页面:
    res = requests.get(f"https://www.17k.com/list/{bookId}.html")
    res.encoding = "utf8"

    # 解析每一本书籍的章节链接
    selector = etree.HTML(res.text)
    # 拿到一本数据对应的所有a标签(作品,正文/章节,外传所有的a标签)
    items = selector.xpath('//dl[@class="Volume"]/dd/a')
    # 处理每一本书籍的每一章节信息
    for item in items:
        chapter_href = item.xpath("./@href")[0]  # 获取a标签里的href
        chapter_title = item.xpath("./span/text()")[0].strip()  # 获取a标签里的第一个文本,即章节名

        # 爬取章节内容:href上面已解析,包含bookId和章节id
        res = requests.get("https://www.17k.com/" + chapter_href)
        res.encoding = "utf8"
        chapter_html = res.text  # 获取章节对应的html文件

        selector = etree.HTML(res.text)  # 解析章节内容
        # 拿到出最后p标签外的所有章节内容对应的p标签,排除最后一个p标签
        chapter_text = selector.xpath('//div[contains(@class,"content")]/div[@class="p"]/p[position()<last()-1]/text()')

        dowlood(book_path,chapter_title,chapter_text)

        time.sleep(random.randint(1, 3))
        print(f"{bookName}书籍的{chapter_title}章节下载完成!")

#定义写入章节内容的函数:
def dowlood(book_path, chapter_title, chapter_text):
    chapter_path = os.path.join(book_path, chapter_title + ".txt")
    with open(chapter_path, "w", encoding="utf8") as f:
        for line in chapter_text:
            f.write(line.strip() + " ")


'''
主要逻辑:
(1) 模拟登陆,获取cookie
'''
login()
#(2)爬取书架上的书籍信息
data = get_shelf_books()

#(3)创建个人书架的文件夹
root_path = "my_books"  #根路径
if not os.path.exists(root_path):
    os.mkdir(root_path)

#(4) 遍历下载每一本书籍的每一章节信息
get_books(data)

由于小说内容太多,一本小说200个多章节☹,这里我在爬完一整本小说293章后,先暂停程序

最后的整理好的代码,还有优化的空间,就先到这里了

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。 爬虫的工作流程包括以下几个关键步骤: URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。 请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的HTML内容。这通常通过HTTP请求库实现,如Python中的Requests库。 解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。 数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。 遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫需要遵守网站的robots.txt协议,限制访问频率和深度,并模拟人类访问行为,如设置User-Agent。 反爬虫应对: 由于爬虫的存在,一些网站采取了反爬虫措施,如验证码、IP封锁等。爬虫工程师需要设计相应的策略来应对这些挑战。 爬虫在各个领域都有广泛的应用,包括搜索引擎索引、数据挖掘、价格监测、新闻聚合等。然而,使用爬虫需要遵守法律和伦理规范,尊重网站的使用政策,并确保对被访问网站的服务器负责。
好的,我可以为您介绍一下如何使用 Python 爬虫来爬取房产数据并保存到本地。 首先,您需要选择一个合适的网站来进行爬取。例如,可以选择链家网、安居客等房产网站。然后,您需要分析该网站的页面结构和数据请求方式,确定需要爬取哪些数据,以及如何获取这些数据。 接着,您可以使用 Pythonrequests 库来发送 HTTP 请求,获取网页内容。然后,可以使用 BeautifulSoup 库来解析网页内容,提取需要的数据。 最后,您可以使用 Python 的 Pandas 库将数据保存到本地的 Excel 或 CSV 文件中。以下是一个示例代码: ```python import requests from bs4 import BeautifulSoup import pandas as pd # 发送 HTTP 请求获取网页内容 url = 'https://bj.lianjia.com/ershoufang/' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'} response = requests.get(url, headers=headers) soup = BeautifulSoup(response.content, 'html.parser') # 解析网页内容,提取需要的数据 house_list = soup.find_all('div', {'class': 'info'}) data = [] for house in house_list: name = house.find('div', {'class': 'title'}).text.strip() price = house.find('div', {'class': 'price'}).text.strip() area = house.find('div', {'class': 'houseInfo'}).text.strip() data.append([name, price, area]) # 将数据保存到本地文件 df = pd.DataFrame(data, columns=['名称', '价格', '面积']) df.to_excel('house_data.xlsx', index=False) ``` 这是一个简单的示例代码,您可以根据您需要爬取的数据和网站的不同来进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值