吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4092|回复: 11
收起左侧

[Python 原创] 新手向的一次完整实战----一键化自动下载整本小说

  [复制链接]
we37 发表于 2021-1-10 22:58
    今天具体看了一下写爬虫的另外一种手段,lxml+xpath,只会beautifulsoup的我很感兴趣,想着趁这个机会练练手,本来就想找了一个小说网站爬个小说练手,结果在边学边实战的过程中,看到网站的搜索栏突发奇想:是不是可以通过直接调用搜索栏的api(不知道算不算api)实现搜索即下载的自动化,然后经过一下午终于实现了,当然在这个过程中碰到了很多问题,一边学一边写,网上有很多xpath的教程,这里就不多说,代码肯定还有很多可以优化的地方,大佬请多多指点,本文主要介绍我的思路和在编写的过程中遇到的各种问题,小白向(我就是个小白)。
    整个project的流程大致是这样的:先使用网站的搜索功能检索想要的小说;然后再搜索出来的页面内检索是否有该小说,如果没有,则询问用户是否再次检索;若有则找出该小说对应的url;接下来顺着这个url找到对应小说章节页面,再提取各个章节的url,最后找到章节内容并写入本地文件。
流程图.png
    按照这个顺序,第一步先找出网站搜索功能的api,通过Chrome开发者工具(F12)的network发现在搜索栏输入小说名称(这里我就用 吞噬星空 来试验)之后,网站直接发送的doc文件中就包含着检索出的小说名称和地址,说明网站并未通过js文件传输这部分内容,这样就意味着我们很容易就能通过rq.get获取到网页里检索出的结果的name和url,用于对比和下一步操作,但在这之前我们还需要考虑如何做到整个步骤中最重要的一点----自动查找,也就是我们得想办法找到如何调用搜索的方法。最开始我希望能在doc文件中找到蛛丝马迹,但并未如我所愿,最后通过多次搜索,瞅了一眼url,突然发现它变简短了,而且随着搜索名称的变化只有&q=后面的内容在变化,立刻将这个写入代码中
[Python] 纯文本查看 复制代码
'''
url前后变化
前:https://so.biqusoso.com/s1.php?ie=gbk&siteid=booktxt.net&s=2758772450457967865&q=%CD%CC%CA%C9%D0%C7%BF%D5
后:https://so.biqusoso.com/s1.php?ie=utf-8&siteid=booktxt.net&q=吞噬星空
'''
#search_url就是搜索的接口,直接将要搜索的小说名跟在后面就可以进行搜索
search_url='https://so.biqusoso.com/s1.php?ie=utf-8&&siteid=booktxt.net&q='


这样我们就能通过rq.get(search_url+bookname)的方式进行搜索,然后通过etree和xpath结合使用的方式找到我们想要的内容。

[Python] 纯文本查看 复制代码
#按书名搜索
def search_bookname(bookname):
   search_result_html=rq.get(search_url+bookname)
   search_htm=etree.HTML(search_result_html.text)
   search_result_url = search_htm.xpath('//span[@class="s2"]/a/@href')#筛选出所有class=s2的span,并找出其下的a标中的href,存入列表search_result_url中
   search_result_bookname = search_htm.xpath('//span[@class="s2"]/a/text()')
   for i in range(len(search_result_bookname)):#遍历所有的搜索结果
      if search_result_bookname[i]==bookname:#判断搜索的小说名与搜索结果是否一致
         return search_result_url[i]
      else:
         return 0

    在做完这一步后,我发现了一个问题,那就是在此网页中获取的目标url并不是最终的url,而需要进一步的重定向才能得到真正的url,这并不方便我们后续的使用,因为写爬虫爬取过小说内容的都应该知道,这类网站的href中存的只有网页后缀,还需要在前面补齐章节页面的url才能真正指向我们想要的地址,通过一张图来明白我刚才说的问题
111.png
    我产生一个想法,用这个中转url加上后缀之后是否能够进入章节内容界面,遗憾的是并不可以,所以如果不能获取到这个真正的url,不能补齐,那就只能手动补齐,也就偏离了我们一键自动化下载的想法,所以这个重定向后的url我们一定要获取到!
经过我翻阅查找后发现urllib.request有一个方法可以获取到,代码如下

[Python] 纯文本查看 复制代码
  rs = urllib.request.urlopen(fake_url)
  return str(rs.geturl())


这个代码能将重定向后的url获取到,这样我们就得到了继续向前走的方向

[Python] 纯文本查看 复制代码
#获取真正的url
def real_url(fake_url):
    rs = urllib.request.urlopen(fake_url)
    return str(rs.geturl())


跟着上面的流程图走,接下来我们要做的就是获取小说各个章节的url,这里比较简单,就不多做叙述。
[Python] 纯文本查看 复制代码
#获取小说章节
def book_chapter(book_url):
   html=rq.get(book_url,headers=header)
   html.encoding='gbk'
   chapter=etree.HTML(html.text)
   chapter_url=chapter.xpath('//*[@id="list"]/dl/dd/a/@href')#找出所有id=list的节点之下的href放入列表chapter_url中
   return chapter_url


然后就是一章一章的将章节内容写入本地txt文件内
[Python] 纯文本查看 复制代码
#单个章节写入文件内
def singlechapter_write(singlechapter_url):
  html=rq.get(singlechapter_url,headers=header)
  html.encoding='gbk'
  htm=etree.HTML(html.text)
  data=htm.xpath('//*[@id="content"]/text()')
  singlechapter_name=htm.xpath('//*[@class="bookname"]/h1/text()')
  f=open('1.txt','a',encoding='utf-8')
  f.write('       '+singlechapter_name[0]+'\n')
  for i in range(len(data)):
    f.write(str(data[i]))
  f.write('\n\n\n')
  f.close()

因为我在这里选择将整本小说写入一个txt文件内,所以在open内使用'a'即追加写入。
走到这,看了一下整个代码,忽然发现重要的人机交互没有写进去,那就再写一个函数。
[Python] 纯文本查看 复制代码
#搜索且完成后的交互
def start_search(bookname):
    while 1:
        book_url = search_bookname(bookname)
        if book_url == 0:
            print('没搜到,真不好意思')
            key = input('还要搜吗,搜就输1,不搜就0')
            if key == 0:
                sys.exit()
        else:
            break
    return book_url


这样模块化的函数就全部写完了,我们还需要像c语言一样将他们整合使用起来,
[Python] 纯文本查看 复制代码
if __name__=='__main__':
  bookname=input('你要搜什么书呢:')
  book_url=start_search(bookname)
  book_url=real_url(book_url)
  chapter_url=book_chapter(book_url)
  for i in range(10): #这里的10次是为了方便测试,所以填写少,如果要下载整本可以写为len(chapter_url)
      url=book_url+chapter_url[i]  #在这里将章节页面url和后缀合并在一起形成新的url,然后get下来
      singlechapter_write(url)


整个编写过程就是这样,不算曲折但也费了我很大精力,可以发现python真的是一个很好使用的语言,后面还有更多的高级操作我也要继续学下去。

另外推荐一个模块my_fake_useragent,使用很方便。

完整源码
[Python] 纯文本查看 复制代码
import requests as rq
from lxml import etree
import sys
import my_fake_useragent as fu
import urllib.request
agent=fu.UserAgent()

header={
'Referer':'https://www.booktxt.net/',
'User-Agent': agent.random()
}
search_url='https://so.biqusoso.com/s1.php?ie=utf-8&&siteid=booktxt.net&q='

#按照书名搜索
def search_bookname(bookname):
   search_result_html=rq.get(search_url+bookname)
   search_htm=etree.HTML(search_result_html.text)
   search_result_url = search_htm.xpath('//span[@class="s2"]/a/@href')
   search_result_bookname = search_htm.xpath('//span[@class="s2"]/a/text()')
   for i in range(len(search_result_bookname)):
      if search_result_bookname[i]==bookname:
         return search_result_url[i]
      else:
         return 0

#获取真正的url
def real_url(fake_url):
    rs = urllib.request.urlopen(fake_url)
    return str(rs.geturl())

#获取小说章节
def book_chapter(book_url):
   html=rq.get(book_url,headers=header)
   html.encoding='gbk'
   chapter=etree.HTML(html.text)
   chapter_url=chapter.xpath('//*[@id="list"]/dl/dd/a/@href')
   return chapter_url

#单个章节写入文件内
def singlechapter_write(singlechapter_url):
  html=rq.get(singlechapter_url,headers=header)
  html.encoding='gbk'
  htm=etree.HTML(html.text)
  data=htm.xpath('//*[@id="content"]/text()')
  singlechapter_name=htm.xpath('//*[@class="bookname"]/h1/text()')
  f=open('1.txt','a',encoding='utf-8')
  f.write('       '+singlechapter_name[0]+'\n')
  for i in range(len(data)):
    f.write(str(data[i]))
  f.write('\n\n\n')
  f.close()

#搜索且完成后的交互
def start_search(bookname):
    while 1:
        book_url = search_bookname(bookname)
        if book_url == 0:
            print('没搜到,真不好意思')
            key = input('还要搜吗,搜就输1,不搜就0')
            if key == 0:
                sys.exit()
        else:
            break
    return book_url

if __name__=='__main__':
  bookname=input('你要搜什么书呢:')
  book_url=start_search(bookname)
  book_url=real_url(book_url)
  chapter_url=book_chapter(book_url)
  for i in range(10):
      url=book_url+chapter_url[i]
      singlechapter_write(url)

免费评分

参与人数 5吾爱币 +14 热心值 +4 收起 理由
人二 + 1 + 1 谢谢@Thanks!
苏紫方璇 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
wuboxun + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
一次过 + 1 + 1 加油
Bluesky10 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

竹笋家 发表于 2021-1-12 15:57
C:\Users\G3\Desktop>python C:\Users\G3\Desktop\index.py
Traceback (most recent call last):
  File "C:\Users\G3\Desktop\index.py", line 4, in <module>
    import my_fake_useragent as fu
ModuleNotFoundError: No module named 'my_fake_useragent'

这个是啥错了?
 楼主| we37 发表于 2021-1-12 17:10
竹笋家 发表于 2021-1-12 15:57
C:%users\G3\Desktop>python C:%users\G3\Desktop\index.py
Traceback (most recent call last):
  File  ...

你没有装my-fake-UserAgent的模块,使用cmd输入pip install my-fake-useragent来安装。
另外这个代码还有一点bug,我晚上把改完后的发出来
jacker 发表于 2021-1-11 07:48
wuai_leader 发表于 2021-1-11 09:05
不错,感谢分享
chenyognzhi1218 发表于 2021-1-11 09:08
刚想学些这方面,感谢楼主分享经验
888365 发表于 2021-1-11 09:10
正好在学习python 哈哈
a2556483812 发表于 2021-1-11 09:19
将来肯定是个高手,我要给大哥点点赞
梦幻恋尘 发表于 2021-1-11 17:15
高手都是
荒原love狼 发表于 2021-1-11 17:45
感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-1 06:06

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表