爬虫第一课

今天开始学习爬虫啦,学完爬虫就要开始干大事咯。本次学习主要参考:
Jack-Cui python 爬虫系列
我只记录下关键的学习内容,系统的东西还是要参考博主原文。

1 爬虫的简介

爬虫就是通过网页地址URL获取服务器发送给浏览器的网址HTML信息。

2 简单实例,下载小说

使用requests库进行爬取信息。requests的基础方法
在这里插入图片描述
第一节课的实战是小说下载,由于原博主提供的小说已经目前我不能爬,所以我换了一个龙族5,龙族5挺好看的。

2.1 获取全网页信息

首先第一步就是获取整个网页的信息。这用到了requests.get()

if __name__ ==  '__main__':
    target = 'http://m.yunxs.com/longzu5/8897118.html'
    req = requests.get(url = target)
    print(req.text)

2.2 解析网页信息

提取网页感兴趣的方法有正则表达式、Xpath、Beautiful Soup等。
正文的内容保存在

标签下。
<div>的标准模式为<div id=" ",class="",style=""
id和class是div的标签属性,一个属性对应一个属性值,用于区分不同的div标签。在本例子中,div的属性值为:id=‘chaptercontent’ class=‘Readarea ReadAjax_content’。通过下面的代码可以获得div标签内的内容。

from bs4 import BeautifulSoup as BS
html = req.text
bs = BS(html)
#text = bs.find_all('div',class_='Readarea ReadAjax_content')
text = bs.find_all('div',id='chaptercontent')       #这里需要注意id没有'_'
#text = bs.find_all('div',id='chaptercontent',class_='Readarea ReadAjax_content')
print(text)

在上述代码执行后,还会出现<br><div>、空格等我们不需要的内容。find_all返回结果是一个列表,使用text属性可以获得文本内容,滤除标签。再使用replace方法,剔除空格,替换回车进行分段。 在html中是用来表示空格的。replace(‘\xa0’*8,’\n\n’)就是去掉下图的八个空格符号,并用回车代替。

fin_text = text[0].text.replace('\xa0*4', '\n\n')

2.3 下载整本小说

要下载整本小说,就要获取每个章节的链接。我们在小说目录页进行检查。我们发现章节链接放在了class属性为"book_last"的<div>标签下,而具体链接又在<dd>标签下。

子节点
子节点
子节点
孙子节点
孙子节点
div
dl
dd
dd

<dd>标签内又有<a>标签,<a>标签用于定义超链接,href属性指示链接的目标。
<a href ="/longzu5/619908.html" >5、《龙族5》预告<a/>
因此我们通过获取<a>的href值就可以获得各个章节的链接和名称。我们先匹配class属性的<div>标签,再匹配<a>标签。
ps:后来发现直接取标签a就可以了,不用在父节点下检索

###匹配标签a
from bs4 import BeautifulSoup as BS
import requests

if __name__ == '__main__':
    server = 'http://m.yunxs.com'
    target = 'http://m.yunxs.com/longzu5/'
    req = requests.get(url = target)
    html = req.text
    bs_html = BS(html)
    div = bs_html.find_all('div',class_ = 'book_last')
    a_bf = BS(str(div))
    a = a_bf.find_all('a')
    links = []
    chapters = []
    for each in a:
        #print(each.get('href'))
        links.append(server+ each.get('href'))
        chapters.append(each.string+ " " + server+ each.get('href'))
    #print(links)
    texts=[]
    for target in links:
        req = requests.get(url = target)
        html = req.text
        bs_html = BS(html)
        div = bs_html.find_all('div',id='chaptercontent')
        #print(div)
        fin_text = div[0].text.replace('\xa0'*4, '\n')
#         print(fin_text)
        texts.append(fin_text)
    print(texts)

与原文例子不同,龙族中的目录分页存在不同网页中,因此需要跳转到不同网页获取所有的目录,本文写了一个获取所有目录链接的代码,之后用set()获得不一样的目录。当然,由于每一页重复的章节相同,可以直接从某一个链接开始添加,这样就不会得到乱序的目录。
由于一章中获取下一页的方法相似,因此不再浪费时间做探讨。

#有下一页的存在把所有链接读出来
from bs4 import BeautifulSoup as BS
import requests

if __name__ == '__main__':
    
    server = 'http://m.yunxs.com'
    links = []
    contain_pages = []
    next_page = True
    target = 'http://m.yunxs.com/longzu5/'
    
    while next_page == True:

        req = requests.get(url = target)
        html = req.text
        bs_html = BS(html)
        
        div_booklist = bs_html.find_all('div',class_ = 'book_last')
        a_bf = BS(str(div_booklist))
        a = a_bf.find_all('a')
        for each in a:
            links.append(server+ each.get('href'))
#         next_page = False
        #print(links)
       
        div_nextpage = bs_html.find_all('div',class_ = 'listpage')
        a_bf = BS(str(div_nextpage))
        a = a_bf.find_all('a')
        for each in a:
            contain_pages.append(each.get('href'))
        
        print(contain_pages)
        print(contain_pages[1])
        if contain_pages[1] == None:
            next_page = False
            print("bubu")
            break
        else:
            print("haha")
            target =  server+str(contain_pages[1])
            contain_pages.clear()
    print(links)
    print(len(links))
    links = set(links)
    print(links)
    print(len(links))

最后使用原博文作者的方法下载整本小说,包括使用了一章下一页的方法。

from bs4 import BeautifulSoup as BS
import requests,sys

class downloader(object):
    
    def __init__(self):
        self.server  = 'http://m.yunxs.com'
        self.target = 'http://m.yunxs.com/longzu5/'
        self.names = []  #存放章节名
        self.urls = []   #用来存放链接
        self.nums = 0   #章节数

        
        
    def get_download_url(self):
        req = requests.get(url = self.target)
        html = req.text
        div_bf = BS(html)
        div = div_bf.find_all('div',class_ = 'book_last')
        
        a_bf = BS(str(div))
        a = a_bf.find_all('a')
        self.nums = len(a)
        for each in a:
            self.names.append(each.string)
            self.urls.append(self.server+each.get('href'))
            
    def get_contents(self,target):
        req  = requests.get(url = target)
        html = req.text
        bf = BS(html)
        texts = bf.find_all('div',id='chaptercontent')
        fin_text = texts[0].text.replace('\xa0'*4, '\n')
        
        links = []
        next_page_link = bf.find_all('a',id="pb_next",class_='Readpage_up')
        #print(next_page_link)
        for each in next_page_link:
            #print(service)
            links.append(service + each.get('href'))

        #print(links)

        if links!=[]:
            #print(links[0])
            req = requests.get(url = links[0])
            html = req.text
            bs = BS(html)
            text2 = bs.find_all('div',id='chaptercontent')
            fin2_text = text2[0].text.replace('\xa0'*4, '\n\n')
            #print('haha')


        #print(fin2_text)
        final_text = fin_text + '\n\n' + fin2_text
        return final_text
    
    def writer(self,name,path,text):
        write_flag = True
        with open(path,'a',encoding='utf-8') as f:   #'a'也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
            f.write(name+"\n")
            f.writelines(text)
            f.write('\n\n')
            
if __name__ == '__main__':
    dl = downloader()
    dl.get_download_url()
    print('龙族开始下载:')
    path = 'C:\\Users\\Administrator\\Anaconda3\\Web_Spider\\lesson 1'
    for i in range(dl.nums):
        dl.writer(dl.names[i], '龙族.txt',dl.get_contents(dl.urls[i]))
        sys.stdout.write("已下载:%0.3f%%" % float(i/dl.nums) + '\r')  #\r 默认将指针返回到最开始后输出(在原位置再次输出)
        sys.stdout.flush()
    print('finish')

至此小说下载的实战就结束啦。撒花。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值