天天育儿网,内容丰富有趣,生活中的好帮手!
天天育儿网 > python 小说 小说_python潇湘书院网站小说爬虫

python 小说 小说_python潇湘书院网站小说爬虫

时间:2022-11-22 05:13:59

相关推荐

python 小说 小说_python潇湘书院网站小说爬虫

很久没有写爬虫了,最近接到一个抓取小说的项目顺便做此纪录练练手,之后工作中可能也会有部分场景要用到爬虫,爬取竞争对手进行数据分析什么的。

目标网站:潇湘书院

环境准备:

python3

requests库

BeautifulSoup库

整体思路

抓取这个小说网站免费板块的所有内容,查看页面发现这个板块一共有6697页,每页有20本小说,那整体思路就是先抓取每页的20个小说名称和url,然后进入每本小说的阅读地址,拿到每一个章节的标题和url,抓取每章节的正文内容并写到本地txt文本中。

单页分析

这里请求使用requests,解析页面用非常方便的BeautifulSoup,在一个文章标题上右键检查,在高亮的这条a标签右键,copy selector,通过这条selector来定位BeautifulSoup解析后小说所在的位置。

1

body > div.content > div > div > div.inner-mainbar > div.search-result > div.result-list > ul > li:nth-child(1) > div > h4 > a

其中li:nth-child(1)很明显是指这个小说在当前页面小说列表中排列第一个,我们想要本页面所有的20本小说,所以就删掉这个:nth-child(1),再将selector语句精简一下只要能定位到即可,如下:

1

div.result-list > ul > li > div > h4 > a

然后将它写入代码,print查看一下结果。

1

2

3

4

5

6

7

import requests,os

from bs4 import BeautifulSoup

webdata = requests.get('/search?vip=0&sort=2')

soup = BeautifulSoup(webdata.text,'lxml')

books = soup.select('div.result-list > ul > li > div > h4 > a')

print(books)

结果是一个列表,列表中有20个元素,分别对应的20个小说,我们想要的是每个元素中href后面的链接和小说的名字,用循环提取出来。

1

2

3

4

5

6

...

for book in books:

bookname = book.text

bookurl = '' + book.get('href')

bookid = book.get('href').split('/')[-1].split('.')[0]

print(bookname,bookurl,bookid)

这样就很简单的拿到了单个页面20本小说的标题和url地址,可以看到上面我把地址中的一串数字用单独取出来了,这个数字其实就是小说对应的唯一ID,后面要用到。

章节分析

点击一个小说进入详情页面,切换至”作品目录”下可以看到所有的章节,这时候在一个章节上右键检查,跟上面方法一样,同样可以很简单的获取到该小说所有章节的名称和url地址以及章节ID。

为了在一篇文章介绍尽可能多的方法,这里我不用上面这个地方来获取章节信息,从另一个地方进入。点击“开始阅读”进入第一章节的正文,在页面的左边可以看到一个“目录”按钮,点看以后就能看到所有的章节名称了。然而在这些章节名称上右键发现当前页面禁用了鼠标右键功能,无法检查元素当然也就不能copy它的selector。

这种按钮的点击肯定是向服务器发送了请求的,打开fiddler进行抓包,再次点击目录按钮,此时可以看到这个请求已经被成功捕获,点击这条请求查看详细信息,这个接口的功能就是查询所有的章节信息。

真实的请求地址是/partview/GetChapterListNoSub?bookid=945608&isvip=0,其中bookid就是我们前面找到的bookid,这里可以做成参数化依次传入其他小说的ID。

1

2

3

4

5

6

7

...

url = '/partview/GetChapterListNoSub?bookid=945608&isvip=0'

titles = BeautifulSoup(requests.get(url).text,'lxml').select('ul > li > a')

for title in titles:

titlename = title.text #章节名称

titleurl = '' + title.get('href') #章节地址

print(titlename,titleurl)

正文下载

上一步取到的titleurl是每一章节的阅读地址,直接requests请求并解析拿到正文内容

1

contents = BeautifulSoup(requests.get(titleurl).text, 'lxml').select('div#auto-chapter > p') #正文内容

返回结果是一个列表,每一个元素是一个段落,将每一段内容前后无用的标签剔除并写到本地的txt文本,写入方式为a+,每次写入时在后面追加,不会覆盖之前的内容,文本自动按照前面获取到的小说名来命名。

1

2

3

4

5

6

...

for content in contents:

content = str(content).replace('

', '\n').replace('

', '')

f = open(path + '%s.txt' % bookname, 'a+')

f.write(content)

f.close()

到此为止三个步骤已经完成,可以顺利的爬下一个章节的内容了,现在通过几个for循环将这几个步骤整合,就可以源源不断的开始下载小说了。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

#coding=utf-8

import requests,time,os

from bs4 import BeautifulSoup

path = r'C:\Users\lipei\Desktop\潇湘书院爬虫\小说\\' #本地存放小说的路径

def get_books(url):

webdata = requests.get(url,timeout=60)

soup = BeautifulSoup(webdata.text,'lxml')

books = soup.select('div.result-list > ul > li > div > h4 > a')

for book in books:

bookid = book.get('href').split('/')[-1].split('.')[0] #小说ID作为下一个请求ur中的参数

bookname = book.text #小说名称

bookurl = '' + book.get('href') #小说url地址

if bookname+'.txt' in oldlists: #判断是否已经下载过,若存在则跳过

continue

else:

pass

print('=====================正在下载【' + bookname + '】=====================')

url = '/partview/GetChapterListNoSub?bookid=%s&isvip=0' % bookid

titles = BeautifulSoup(requests.get(url,timeout=60).text,'lxml').select('ul > li > a')

for title in titles:

titleurl = '' + title.get('href') #章节url地址

titlename = title.text #章节名称

# print(titlename,titleurl)

try:

f = open(path + '%s.txt' % bookname, 'a+') #章节名称写到txt文本

f.write('\n'*2 + titlename + '\n')

f.close()

except:

pass

contents = BeautifulSoup(requests.get(titleurl,timeout=60).text, 'lxml').select('div#auto-chapter > p')

for content in contents:

content = str(content).replace('

', '\n').replace('

', '')

try:

f = open(path + '%s.txt' % bookname, 'a+') #正文内容卸载txt文本,紧接在章节名称的下面

f.write(content)

f.close()

except:

pass

print(titlename + '[已下载]')

if __name__ == "__main__":

urls = ['/search?vip=0&sort=2&pn={}'.format(i) for i in range(6697)] #免费板块每一页的url通过最后的pn参数控制

global oldlists

oldlists = os.listdir(path) #爬虫开始之前检查当前目录已有的文件

for url in urls:

get_books(url)

#控制每天爬取的数量,达到要求后停止任务,通过任务开始前后目录中的文件数量相减来判断

newlists = os.listdir(path)

num = len(newlists) - len(oldlists)

if num >= 20:

print('今日任务下载完毕,今日下载小说%d本' % num)

break

else:

pass

写在最后

在测试过程中发现短时间持续请求该网站的话会可能被服务器拒绝,但是并没有封禁IP,这可能是这个网站唯一的反爬措施了,然而并没有卵用,将请求放在一个无限循环里面,若被拒绝就自动重连,连上以后跳出循环。

后面如果遇到封禁IP的网站再讲如何通过更换IP来规避。

1

2

3

4

5

6

7

...

while True:

try:

webdata = requests.get(url,timeout=60)

break #连接成功就跳出循环

except:

time.sleep(3)

如有失效,请留言告知丨转载请注明原文链接:python潇湘书院网站小说爬虫

如果觉得《python 小说 小说_python潇湘书院网站小说爬虫》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。