欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python爬虫实例(笔趣阁小说爬取)

程序员文章站 2022-04-20 09:46:46
最近考完试了,开始学习python爬虫,由于一些盗版小说网站几乎没有反爬机制,且网页结构简单,所以选择了小说网站笔趣阁来进行python爬虫的学习。0X00、准备工作安装标准库lxml、requests、re和requests.exceptions0X01、页面分析我们以小说《九星霸体诀》为例,首先查看页面源码,整个页面只有一个

标签,包裹了本章小说的标题,而正文内容全部在一个
标签中,每段的间隔则是一个
标签,简单的页面结构使得我们的爬取工...

最近考完试了,开始学习python爬虫,由于一些盗版小说网站几乎没有反爬机制,且网页结构简单,所以选择了小说网站笔趣阁来进行python爬虫的学习。

0X00、准备工作

安装标准库lxml、requests、re和requests.exceptions


0X01、页面分析

我们以小说《九星霸体诀》为例,首先查看页面源码,整个页面只有一个<h1>标签,包裹了本章小说的标题,而正文内容全部在一个<div>标签中,每段的间隔则是一个<br>标签,简单的页面结构使得我们的爬取工作简单了很多。
python爬虫实例(笔趣阁小说爬取)
python爬虫实例(笔趣阁小说爬取)然后观察每章小说的URL,第一章URL为:https://www.biquge.tw/47_47879/3155529.html,之后每章在之后的数字递增。
不过要注意,之后有的数字被跳过了,在爬取的时候要对其内容进行判断得知是否为有效URL。


0X02、代码实现

首先第一个爬取单个页面的函数get_one_page,传入参数url,请求该页面,如果返回状态码200,证明请求成功,然后由于前面提到的无效的url也会返回200,所以进行了简单的判断,返回内容是否含有“章”字,如果有则函数返回响应内容,无则返回None。

def get_one_page(url):
    try:
        headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"}
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            if '章' in response.text:
                return response.text
        else:
            return None
    except RequestException:
        return None

之后是第二个函数parse_page,对得到的响应的内容进行解析,并将其存入文档中,注意这里的html.replace(u’\xa0’, u’ '),如果不进行替换,则会出现报错:UnicodeEncodeError: ‘gbk’ codec can’t encode character ‘\xa0’ in position 0。然后将每个<br/>标签替换为换行符。
之后由于标题在仅有的<h1>标签中,所以我们就选择了使用正则表达式来进行标题的提取。
然后正文内容的话,我们选择使用xpath来进行提取。之后还要对内容进行一些处理,将前后的空白内容全部删掉,将每段前面的空格替换为水平制表符\t。
这一步开始我写的是text = re.sub(' *', '\t', text),但是不知道为什么没有成功替换,于是我直接放入了段首的八个空格。

def parse_page(html):
    html.replace(u'\xa0', u' ')
    html = re.sub('<br/>', '\n', html)
    # 正则表达式匹配获取标题
    title = re.search('<h1>(.*)</h1>', html, flags=0)
    print(title.group(1) + ' 开始爬取')
    html = etree.HTML(html)
    # xpath获取正文内容
    context = html.xpath('//*[@id="content"]')
    for i in context:
        with open('context.txt', 'a+', encoding='utf-8') as file_data:
            file_data.write(title.group(1) + '\n\n')
            text = i.text.strip()
            text = re.sub('      ', '\t', text)
            file_data.write('\t' + text + '\n')
            print('爬取成功')

之后就是代码的主体部分,for循环得到每一个url,然后对其进行请求,如果返回不为None,则进行相应内容的解析,最终代码完成。

if __name__ == '__main__':
    for i in range(3155529, 3239451):
        url = 'https://www.biquge.tw/47_47879/' + str(i) + '.html'
        html_data = get_one_page(url)
        if html_data is not None:
            parse_page(html_data)

0X03:完整代码

import requests
from requests.exceptions import RequestException
from lxml import etree
import re


def get_one_page(url):
    try:
        headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"}
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            if '章' in response.text:
                return response.text
        else:
            return None
    except RequestException:
        return None


def parse_page(html):
    html.replace(u'\xa0', u' ')
    html = re.sub('<br/>', '\n', html)
    # 正则表达式匹配获取标题
    title = re.search('<h1>(.*)</h1>', html, flags=0)
    print(title.group(1) + ' 开始爬取')
    html = etree.HTML(html)
    # xpath获取正文内容
    context = html.xpath('//*[@id="content"]')
    for i in context:
        with open('context.txt', 'a+', encoding='utf-8') as file_data:
            file_data.write(title.group(1) + '\n\n')
            text = i.text.strip()
            text = re.sub('      ', '\t', text)
            file_data.write('\t' + text + '\n')
            print('爬取成功')


if __name__ == '__main__':
    for i in range(3155529, 3239451):
        url = 'https://www.biquge.tw/47_47879/' + str(i) + '.html'
        html_data = get_one_page(url)
        if html_data is not None:
            parse_page(html_data)

0X04:反思

这是我写的第一个python爬虫项目,很简陋,而且运行效率很低,不知道是我的电脑有问题还是怎么回事,每次都是爬了几十章甚至十几章后就会卡顿半天甚至卡顿好几分钟(害)。
接下来去学习多线程,让代码可以变得高效一些,加油!

本文地址:https://blog.csdn.net/qq_45653588/article/details/107105090