看不到小说?直接爬虫

一行数据

共 6498字,需浏览 13分钟

 ·

2020-11-01 20:48

点击上方“一行数据”,星标公众号
重磅干货,第一时间送达

大家好,我是一行

这篇是一位读者的投稿文章,居然说我的爬虫文章分享的少,你们自己看看这篇文章怎么样,给多少个?,我后台给他添加多少 ?*10 的积分数量

一、思路和目的:

之前在最开始学习爬虫的时候就看过大神写过爬取小说的案例,之前觉得非常牛逼,后来学习了爬虫,感觉还是挺简单的。好的,下面开始我们的代码之旅。

二、步骤和内容:

第一步:确认环境

想要写好,首先我们需要拥有正确的环境配置。这里我采用的基础是基于selenium来写的,selenium简而言之就是模拟人类操作浏览器,这样可以比较有效的处理ajax等数据加载方式。如果没有selenium的朋友,可以自行在csdn中查找。

第二步:确认爬取的目标和基础分析:

首先今天的受害者是:http://www.xbiquge.la。网站截图如下:受害网站首页

接下来的大体思路就是:使用selenium模拟输入和搜索,然后列出所有的搜索结果,然后反馈给用户,根据用户的选择打开相应的小说,然后爬取小说内容即可。

第三步:写出大体框架

1.导入模块:

#导入基本模块
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
from lxml import etree
import requests
import os

2.大体框架:

class Spider(object):
    def __init__(self):
        self.driver_path = r'D:\CHROM\chrome\chromedriver.exe'
        self.options = Options()
        self.options.add_argument('--headless')
        self.options.add_argument('--disable-gpu')
        self.driver = webdriver.Chrome(executable_path=self.driver_path,options=self.options)
  
        self.base_url = 'http://www.xbiquge.la'
        self.headers = {
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
        }

    def interactive(self):
        self.driver.get('http://www.xbiquge.la/')
        #我运行的时候,为了避免网速不好,休息两秒钟
        time.sleep(2)
        #搜索方法,该方法返回首页网页的html源代码
        text = self.search()
        #输出可选择书籍的列表,该方法返回的是书籍列表的url
        url_list = self.show_list(text)
        #选择合适的书籍并爬取章节
        self.spider(url_list)
        #保存至本地

说明:selenium模拟浏览器,如果不指定一定的参数,模拟的过程会默认展示出来,为了减少这种情况的出现,所以加上了这三行代码:

self.options = Options()
self.options.add_argument('--headless')
self.options.add_argument('--disable-gpu')

3.完成搜索方法self.search():

def search(self):
        book_name = input('请输入搜索书籍的名字:')
  
  #获取输入框的input标签和搜索按钮的button标签
        search_tag = self.driver.find_element_by_name('searchkey')
        button_tag = self.driver.find_element_by_id('sss')
        #这里采用send_keys(xxxx)方法,向输入框输入内容然后点击按钮即可
        search_tag.send_keys(book_name)
        button_tag.click()
        time.sleep(1)
        #获取html源码
        text = self.driver.page_source
     #返回源码
        return text

好的,接下来分析下如何写获取input和button代码:如何获取标签-01

首先鼠标放于此处并右击,选择检查可以得到以下图片的内容:如何获取input和button标签-02

可以看见,这两个标签都是容易获取的,因为selenium对于input有一个专门的name方法,而button标签则有id属性,更是容易获取。因此,可以采用下面这两行获取相应的标签:

search_tag = self.driver.find_element_by_name('searchkey')
button_tag = self.driver.find_element_by_id('sss')

4.完成输出可选择书籍列表的信息函数self.show_list():

def show_list(self,text):
  #使用lxml库解析html源代码
        html = etree.HTML(text)
        #获取书籍信息
        bookNameList = html.xpath('//table//tr//td[@class="even"]//a/text()')
        bookUrlList = html.xpath('//table//tr//td[@class="even"]//a/@href')
        lastestChapterList = html.xpath('//table//tr//td[@class="odd"]//a/text()')
        authorList = html.xpath('//table//tr//td[@class="even"]/text()')
        updateDateList = html.xpath('//table//tr//td[@align="center"]/text()')
        #输出书籍信息
        for name,author,chapter,date in zip(bookNameList,authorList,lastestChapterList,updateDateList):
            info = '''
name    : {bookName}
author  : {authorName}
chapter : {chapterName}
date    : {updateDate}
'''
.format(bookName=name,authorName=author,chapterName=chapter,updateDate=date)
            print(('book info of %s' % name).center(80,'-'))
            print(info)
            
  #返回相应书籍对应url列表
        return bookUrlList

好的,接下来分析下这段代码的思路:首先,我们随意输入一本书的名字或者作者的名字(这里我以辰东为例),如下图:输出书籍列表函数-01

接下来,我们鼠标放于此处并右击检查,可以得到下面图片的信息:输出书籍列表函数-02

显然,上面标注的就是我们需要获取的信息。好的,下面我们只需按部就班的使用xpath(lxml中支持的语法)去获取相应信息即可,采用的以下几个语句:

#获取书籍信息
bookNameList = html.xpath('//table//tr//td[@class="even"]//a/text()')
bookUrlList = html.xpath('//table//tr//td[@class="even"]//a/@href')
lastestChapterList = html.xpath('//table//tr//td[@class="odd"]//a/text()')
authorList = html.xpath('//table//tr//td[@class="even"]/text()')
updateDateList = html.xpath('//table//tr//td[@align="center"]/text()')

为了输出的美观,采用了一定手段,这里就不多赘述。下面是美化后输出的形式举例:输出书籍列表函数-03

5.完成获取小说内容的函数 self.spider():

def spider(self,url_list):
    #这里用户根据之前输出的书籍列表输入相应的数字
    decision = int(input('请选择合适的书籍(输入序号,ex:1 2 3 ):'))
    target_url = url_list[decision-1]
    
    #由于该网站的反爬不是很严格,所以这里只设置了headers参数里的user-agent
    response = requests.get(target_url,headers=self.headers)
    text = response.content.decode('utf-8')
    #这里采用lxml方法获取所有章节的url
    html = etree.HTML(text)
    #这里有两个辅助函数,主要是为了让代码更易读
    chapter_url_list = self.spider_get_urls(html)
    #爬取小说对应url的内容
    self.spider_get_content(chapter_url_list)   

好的,开始分析:首先,我们随意打开一本辰东大神的书(这里我选择的是《圣墟》):获取书籍内容函数-01

鼠标放于此处并右击,可得以下信息:获取书籍内容函数-02

这里你会发现,这个网站并没有将章节分页,所以上图的所有dd标签即为所有的章节,然后我们就可以采用lxml库对于这个网页解析获取对应的url-----即self.spider_get_urls()函数

def spider_get_urls(self,html):
 #获取所有的a标签里面的url链接
 chapter_list = html.xpath('//div[@class="box_con"]//dl//dd/a/@href')
 #对于url进行拼接为完整的url
 for i in range(len(chapter_list)):
  chapter_list[i] = self.base_url + chapter_list[i]
 #返回url列表
 return chapter_list

这里a标签的href属性的url只有一半,如:/13/13959/5939039.html,需要我们进行拼接为完整的url。接下来我们开始下载内容即self.spider_get_content() 函数:

def spider_get_content(self,chapter_url_list):
 info_dict = {}
 for url in chapter_url_list:
  #打开网页
  self.driver.get(url)
  #为避免没有加载出来,休息5秒
  time.sleep(5)
  #采用lxml库解析html网页源代码
  text  = self.driver.page_source
  html = etree.HTML(text)
  title = html.xpath('//div[@class="bookname"]/h1/text()')[0]
  content_list = html.xpath('//div[@class="box_con"]//div[@id="content"]//text()')
  #删除垃圾信息
  content_list.pop(-1)
  content_list.pop(-1)
  #开始输出结果
  result = ''
  for content in content_list:
         result+=(content.strip()+'\n')
  info_dict[title] = result
 return info_dict

首先我们需要一章一章的下载,并且每次下载之间必须留有一定的时间间隔,避免因为短时间访问过多而被封禁,当然你可以使用ip代理或者多线程提升效率。其次,我们容易发现,这里获取的信息并不是全都是我们需要的,其中下面的数据不是我们需要的 获取书籍内容函数-03

但是仍然能被爬取,所以我们需要将他们删除,就用到了下面代码:#因为是列表,所以删除

content_list.pop(-1)
content_list.pop(-1)

最后我们采用字典的方式,一个章节名(key),一个小说内容(value)的形式返回。效果如下图:获取书籍内容函数-04

6.完成保存本地函数self.save():

def save(self,result_dict):
 #创建文件夹
 os.mkdir('book')
 os.chdir('./book')
 #保存
    count = 1
    for key in result_dict:
        f = open(key+'.txt','w')
        f.write(result_dict[key])
        f.close()
        print('保存完%s章' % count)
        count+=1
 print('保存完毕')

这部分没什么好说的,大家都会。

第四步、分析总结

1.全部代码如下:

  • 网址:https://yihang.cowtransfer.com/s/1408b077542749
  • 密码:yihangsb

2.缺点分析:

首先,效率很低,因为没有使用多线程或者代理,所以必须温柔的访问网站,不然可能会被封禁。但是由于某种神奇的原因,我并没有写多线程版本,而关于ip代理主要是免费的代理太不靠谱了,付费的又不想浪费钱,

雷军,扎克伯格,Linus 等巨佬的办公桌

可能是全网最好用的伪原创工具!

积分送书 雨露均沾


再重申一遍,多少个?,给这位读者 ?*10的积分数量

浏览 33
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报