小言_互联网的博客

第一次爬小说,乱码?没安装Beautiful Soup库?

482人阅读  评论(0)

最近《传闻中的陈芊芊》十分的火,我也上车了 哈哈哈哈,但是电视剧已经不能满足我对剧情的好奇,总希望在小说里面找不同。

import requests
target = 'https://www.biqiuge.com/book/52415/85860763.html'
req = requests.get(url=target)
print(req.text)

当我满心欢喜的点了F5,出现了……嗯,看不到。😭

出现中文乱码,怎么办👀?

1、首先为什么会出现乱码。乱码的问题,本质上来说就是编码和解码采用的编码方案不同。
打开原网页,找到网页编码。

通过查看源代码可以发现这个网址采用的编码是GBK

 <meta http-equiv="Content-Type" content="text/html; charset=gbk" />

补充内容:
Content-Type:在HTTP协议消息头中,使用Content-Type来表示请求和响应中的媒体类型信息。它用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据。

Content-Type:type/subtype ;parameter

  • type:主类型,任意的字符串,如text,如果是*号代表所有;
  • subtype:子类型,任意的字符串,如html,如果是*号代表所有,用“/”与主类型隔开;
  • parameter:可选参数,如charset,boundary等。

2、此时,我们需要将编码改为GBK。

encode()方法:以 encoding 指定的编码格式编码字符串。
encode()方法语法:

  • str.encode(encoding=‘GBK’,errors=‘strict’)

参数

  • encoding – 要使用的编码,如"GBK"。
import requests
target = 'https://www.biqiuge.com/book/52415/85860763.html'
req = requests.get(url=target)
req.encoding='GBK'
print(req.text)


3、获取了HTML信息,现在我们就需要把正文提取出来,不然看着脑子疼。🤨
先找到我们要找到文本所在处。

不难发现,文章的所有内容都放在了一个名为div的“东西下面”,这个”东西”就是html标签。HTML标签是HTML语言中最基本的单位,HTML标签是HTML最重要的组成部分。

<div id="content", class="showtxt">

id和class就是div标签的属性,content和showtxt是属性值,一个属性对应一个属性值,是用来区分不同的div标签。
class属性为showtxt的div标签。我们可以以此下手!

安装Beautiful Soup4失败?

Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据,有了它我们可以很方便地提取出HTML或XML标签中的内容。
并用findall()函数匹配所有符合规律的内容,并以列表的形式返回结果

from bs4 import BeautifulSoup
import requests
target = 'https://www.biqiuge.com/book/52415/85860763.html'
req = requests.get(url=target)
req.encoding='GBK'
html=req.text
bf=BeautifulSoup(html)
texts=bf.find_all('div',class_='showtxt')
print(texts)

兴奋的按下F5,又……?突然想到我昨天安装的是Beautiful Soup,


如果不加上 4,会是老版本也就是 bs3,它是为了兼容性而存在,目前已不推荐

怎么安装第三方库?

  • 先找到安装python的文件夹,并且找到Scrips。
  • 点进去,然后shift+右键
  • 找到在此处“打开Powershell窗口”,点他。
    -输入——pip install beautifulsoup4


安装好bs4之后,果然行了,但是还是有多余,比如div标签名,br标签,以及各种空格。怎么去除这些东西呢?我们继续编写代码。

<br> 可插入一个简单的换行符。

<br> 标签是空标签(意味着它没有结束标签,因此这是错误的:<br></br>)。在 XHTML 中,把结束标签放在开始标签中,也就是 <br />。


拿爬取的内容跟原网页对比发现:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为空白

\xa0表示不间断空白符,爬虫中遇到它的概率不可谓不小,而经常和它一同出现的还有\u3000、\u2800、\t等Unicode字符串。

find_all匹配的返回的结果是一个列表。提取匹配结果后,使用text属性,提取文本内容,滤除br标签。随后使用replace方法,剔除空格,替换为回车进行分段。 在html中是用来表示空格的。

replace(‘\xa0’*8,’\n\n’)就是去掉下图的八个空格符号,并用回车代替。

from bs4 import BeautifulSoup
import requests

target = 'https://www.biqiuge.com/book/52415/85860763.html'
req = requests.get(url=target)
req.encoding='GBK'
html=req.text
bf=BeautifulSoup(html)
texts=bf.find_all('div',class_='showtxt')
print(texts[0].text.replace('\xa0'*8,'\n\n'))


这样我们一章就爬完了。
就先这样8,溜了,去吃午饭了。

尝试爬取整本书

上面我们已经学会爬取一个章节。那么怎么爬取整本小说呢?


这些章节都存放在了class属性为listmain的div标签下,选取部分html代码如下:

<div class="listmain">
	<dl>
		<dt>《传闻中的三公主》最新章节列表</dt>
		<dd><a href ="/book/52415/85774549.html">第一百七十五章 真是好不要脸</a></dd>
		<dd><a href ="/book/52415/85774550.html">第一百七十四章 天下无不散之筵席</a></dd>
		<dd><a href ="/book/52415/85774551.html">第一百七十三章 要点东西</a></dd>
		<dd><a href ="/book/52415/85774552.html">第一百七十二章 陈芊芊算漏的那个人</a></dd>
		<dd><a href ="/book/52415/85774553.html">第一百七十一章 你把韩烁送走了</a></dd>
		<dd><a href ="/book/52415/85774554.html">第一百七十章 你不喜欢我</a></dd>
		<dt>《传闻中的三公主》正文卷</dt>
		<dd><a href ="/book/52415/86867523.html">第一章 阴差阳错</a></dd>
		<dd><a href ="/book/52415/86755792.html">第二章 当街抢亲</a></dd>
		<dd><a href ="/book/52415/86755791.html">第三章 影帝的指点</a></dd>
		<dd><a href ="/book/52415/86755790.html">第四章 穿越成女配</a></dd>
		<dd><a href ="/book/52415/86755789.html">第五章 离韩烁那扫把星越远越好</a></dd>
		<dd><a href ="/book/52415/86755788.html">第六章 这是杀马儆我啊</a></dd>
		<dd><a href ="/book/52415/86755787.html">第七章 论如何穿回现代</a></dd>
		<dd><a href ="/book/52415/86755786.html">第八章 一切都要给洞房让路</a></dd>
		<dd><a href ="/book/52415/86755785.html">第九章 你家守宫砂是日抛的啊</a></dd>
		<dd><a href ="/book/52415/86755784.html">第十章 酒中下毒</a></dd>
		<dd><a href ="/book/52415/86755783.html">第十一章 韩烁入狱</a></dd>
		<dd><a href ="/book/52415/86755782.html">第十二章 我怀孕了!</a></dd>
		<dd><a href ="/book/52415/85774552.html">第一百七十二章 陈芊芊算漏的那个人</a></dd>

	</dl>
</div>
1<div></div>限定了<div>标签的开始和结束的位置,他们是成对出现的,有开始位置,就有结束位置。
2、在<div>标签包含<dl>标签,那这个<dl>标签就是<div>标签的子节点,<dl>标签又包含<dt>标签和<dd>标签,那么<dt>标签和<dd>标签就是<div>标签的孙节点。
3、我们看到每个章节的名字存放在了<a>标签里面。<a>标签还有一个href属性。这里就不得不提一下<a>标签的定义了,<a>标签定义了一个超链接,用于从一张页面链接到另一张页面。<a> 标签最重要的属性是 href 属性,它指示链接的目标。

根据我们昨天提取章节的方法,得:


我们可以根据标签的href属性值获得每个章节的链接和名称了。

from bs4 import BeautifulSoup
import requests
if __name__ == "__main__":
    server='https://www.biqiuge.com/'
    target = 'https://www.biqiuge.com/book/52415/'
    req = requests.get(url = target)
    req.encoding='GBK'
    html = req.text
    div_bf = BeautifulSoup(html)
    div = div_bf.find_all('div', class_ = 'listmain')
    a_bf=BeautifulSoup(str(div[0]))
    a=a_bf.find_all('a')#find_all返回的是一个列表,里边存放了很多的<a>标签
    for each in a:#用for循环遍历每个<a>标签并打印出来
        print(each.string,server+each.get('href'))


发现上面有6个下面也会重复。

from bs4 import BeautifulSoup
import requests, sys

class downloader(object):

    def __init__(self):
        self.server = 'https://www.biqiuge.com/'
        self.target = 'https://www.biqiuge.com/book/52415/'
        self.names = []            #存放章节名
        self.urls = []            #存放章节链接
        self.nums = 0            #章节数

 
    def get_download_url(self):
        req = requests.get(url = self.target)
        html = req.text
        div_bf = BeautifulSoup(html)
        div = div_bf.find_all('div', class_ = 'listmain')
        a_bf = BeautifulSoup(str(div[0]))
        a = a_bf.find_all('a')
        self.nums = len(a[6:])  #剔除不必要的章节,并统计章节数
        for each in a[6:]:
            self.names.append(each.string)
            self.urls.append(self.server + each.get('href'))

    def get_contents(self, target):
        req = requests.get(url = target)
        req.encoding='GBK'
        html = req.text
        bf = BeautifulSoup(html)
        texts = bf.find_all('div', class_ = 'showtxt')
        texts = texts[0].text.replace('\xa0'*8,'\n\n')
        return texts

    def writer(self, name, path, text):
        write_flag = True
        with open(path, 'a', encoding='UTF-8') as f:
            f.write(name + '\n')
            f.writelines(text)
            f.write('\n\n')

if __name__ == "__main__":
    dl = downloader()
    dl.get_download_url()
    print('《传闻中的陈芊芊》开始下载:')
    for i in range(dl.nums):
        dl.writer(dl.names[i], '传闻中的陈芊芊.txt', dl.get_contents(dl.urls[i]))
        sys.stdout.write("  已下载:%.3f%%" %  float(i/dl.nums) + '\r')
        sys.stdout.flush()
    print('《传闻中的陈芊芊》下载完成')




转载:https://blog.csdn.net/weixin_43787365/article/details/106518251
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场