Python爬虫之BeautifulSoup+Requests爬取喜欢博主的全部博文(六)
Python爬虫之BeautifulSoup+Requests爬取喜欢博主的全部博文
原创不易,转载前请注明博主的链接地址:https://blog.****.net/weixin_42555080
本次代码的环境:
运行平台: Windows
Python版本: Python3.x
IDE: PyCharm
一、 前言
当你比较喜欢一个博主的文章,而又想把它全部下载下来,这时候我们可以通过爬虫快速的爬取文章内容,如果需要还可以对文章进行Python的内容分析。而对于向我这样的Python初学者来说,这里面会遇到几个问题:
1)如何爬取一篇文章的内容
2)如何爬取分页的多篇文章的内容
3)如何将爬取的内容写入指定文件中
而这每一个问题中都有会涉及到很多小的问题。其实我们的代码也是按照这个思路来的,好了,那我么接下来我们开启学习之旅。
免责说明:这篇文章爬取的是https://blog.****.net/rlnLo2pNEfx9c/article/list/1(如图1所示)这个博主的文章,本次只是用来交流学习,如此博主有任何不满等问题,请联系我,我会立刻改换爬取的url。
图1
二、 代码编写与效果展示
首先呢,按照我们的惯例还是先给出代码和最终效果:
- 代码:
import requests
from bs4 import BeautifulSoup
import urllib.request
import time
import os
import urllib.error
class download(object):
def __init__(self):
self.chapter_name = []
self.href_list = []
self.head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3493.3 Safari/537.36',
'Accept': '*/*',
'connection': 'keep-alive',
'accept-encoding': 'zip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9'
}
def get_url(self):
for i in range(8):
url = 'https://blog.****.net/rlnLo2pNEfx9c/article/list/%s' % (i + 1)
strhtml = requests.get(url, params='html',headers=self.head)
soup = BeautifulSoup(strhtml.text, 'lxml')
data = soup.select('#mainBox > main > div.article-list > div > h4 > a')
# print(data[0].get_text.remove[0])
for item in data:
result = {
'title': item.get_text().strip()[18:-1],
'URL': item.get('href'),
# 'URL' : re.findall('\d+',item.get('href'))
}
self.chapter_name.append(result.get('title'))
self.href_list.append(result.get('URL'))
def readSigleArticle(self,herf):
if(herf=='https://blog.****.net/yoyo_liyy/article/details/82762601'):
self.href_list.remove(herf)
else:
try:
req = urllib.request.Request(herf)
urllib.request.urlopen(req)
singleURL = herf
strhtml = requests.get(singleURL, params='html')
soup = BeautifulSoup(strhtml.text, 'lxml')
data = soup.find_all('div', class_='rich_media_content')
self.article_content = data[0].text.replace('。', '。\n\n')
except urllib.error.HTTPError:
print(herf+ '=访问页面出错')
time.sleep(2)
except urllib.error.URLError:
print(herf + '=访问页面出错')
time.sleep(2)
def write(self):
folder_path = './****'
i = 0
if os.path.exists(folder_path) == False:
os.makedirs(folder_path)
for herf in self.href_list:
path = folder_path+'/{}'.format(i+1)
txtPath = path + '/{}'.format(i + 1) + '.txt'
if os.path.exists(path) == False:
os.makedirs(path)
open(txtPath, 'w')
print(herf)
with open(txtPath, 'a', encoding='utf-8') as f:
f.write(self.article_content)
if __name__ == '__main__':
dl=download()
dl.get_url()
for url in dl.href_list:
dl.readSigleArticle(url)
dl.write()
- 结果展示
图2是是为每一篇文章都建立一个文件夹,图3是每个文件夹下都有一个扩展名为.txt的文件,图4是其中一篇.txt文件内容,图5是生成了一个名为“****”的文件夹存放所有的子文件夹和下载内容。
图2
图3
图4
图5
三、 代码讲解
接下来一一讲解一下代码,这次的代码其实是对前几篇文章代码的一个综合应用,最主要用到的还是BeautifulSoup和Requests库,还有一些time库、os库等这些我们以前也讲过了。当然如果一下子接受不了这么多代码,屡不清逻辑的话,也可以先参考我的这几篇文章:Python学习之使用Beautiful Soup解析网页(简析)、Python爬虫基础之requests+BeautifulSoup+Image 爬取图片并存到本地(四)、 Python爬虫基础之Requests和XPath实例(二)这些内容相对来说更加容易理解。
好了咱们接下来分模块讲解代码。
1)初始化变量模块
def __init__(self):
self.chapter_name = []
self.href_list = []
self.head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3493.3 Safari/537.36',
'Accept': '*/*',
'connection': 'keep-alive',
'accept-encoding': 'zip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9'
}
这里面的变量都是全局变量,在这里面我定义了chapter_name、href_list这两个列表用来分别存放文章姓名和文章地址链接,当然还有我们的headers这个的作用我在Python爬虫基础之requests+BeautifulSoup+Image 爬取图片并存到本地(四)这篇文章里讲过,忘记的小伙伴可以去看一下。有人会问你这个传递的“self”是啥子东西吗?这个我把它理解问一个桥梁,通过self.XX在一个函数中就可以给其他函数传递内容,当然也可以把它理解为一个java学的public,即定义了一个共有属性。
2) 获取全部文章的url模块
def get_url(self):
for i in range(8):
url = 'https://blog.****.net/rlnLo2pNEfx9c/article/list/%s' % (i + 1)
strhtml = requests.get(url, params='html',headers=self.head)
soup = BeautifulSoup(strhtml.text, 'lxml')
data = soup.select('#mainBox > main > div.article-list > div > h4 > a')
for item in data:
result = {
'title': item.get_text().strip()[18:-1],
'URL': item.get('href'),
}
self.chapter_name.append(result.get('title'))
self.href_list.append(result.get('URL'))
这篇文章里面的内容大部分我再这篇文章Python学习之使用Beautiful Soup解析网页(简析)已经涉及到了,忘记的小伙伴可以去踩踩哦!
挑一些没有以前涉及到内容讲解一下:(1)首先呢,解释一下,我的range(Num)中的Num为什么是8,这是因为看博主的全部文章只用了8个分页,这个数字实际是分页的计数。(2)url = ‘https://blog.****.net/rlnLo2pNEfx9c/article/list/%s’ % (i + 1)这个里面我们用到了字符格式化,这个内容可以参考这两篇文章:https://www.cnblogs.com/fat39/p/7159881.html和https://www.cnblogs.com/czqq/p/6108557.html,同时也需要解释一下为什么要这么写,通过打开不同分页,
https://blog.****.net/rlnLo2pNEfx9c/article/list/1
https://blog.****.net/rlnLo2pNEfx9c/article/list/2
https://blog.****.net/rlnLo2pNEfx9c/article/list/3
我们可以看到他们的url的不同就是在最后一个数字,所以我们可以通过控制最后一个数字,通过拼接字符串实现改变url,进而实现读取不同分页博文的url的功能。(3)最后两句还是通过self这个桥梁将数据公有化。
3)单篇文章内容下载
def readSigleArticle(self,herf):
if(herf=='https://blog.****.net/yoyo_liyy/article/details/82762601'):
self.href_list.remove(herf)
else:
try:
req = urllib.request.Request(herf)
urllib.request.urlopen(req)
singleURL = herf
strhtml = requests.get(singleURL, params='html')
soup = BeautifulSoup(strhtml.text, 'lxml')
data = soup.find_all('div', class_='rich_media_content')
self.article_content = data[0].text.replace('。', '。\n\n')
except urllib.error.HTTPError:
print(herf+ '=访问页面出错')
time.sleep(2)
except urllib.error.URLError:
print(herf + '=访问页面出错')
time.sleep(2)
其中(1)
if(herf==‘https://blog.****.net/yoyo_liyy/article/details/82762601’):
self.href_list.remove(herf)
之所以写这部分内容,是因为爬取完“获取全部文章的url模块“后看到里面竟然出现了一篇完全不相干的内容,在页面上也没找到,所以当读到它的时候就去除该链接。(2)为了避免出现打不开的页面,特意写了一个异常处理块,这里面涉及到的内容可以看一下这篇文章https://blog.****.net/sinat_41104353/article/details/79296541
(3)其中self.article_content = data[0].text.replace(’。’, ‘。\n\n’)
再说这个代码之前我们可以看一下图6这个内容,我们发现这些文本信息都是一个完整的句子,并以句号结尾,其实我们获得的data数据是一个完整的列表对象(该对象里面有全部的HTML内容),我们通过data[0].text取到该HTML中的文本信息(但是此时的内容是一个没有换行的列表信息),然后通过replace(‘。’,’。\n\n’)去替换就可以实现获得整篇文章的文本,并且是一句一换行,比较美观。
图6
4) 写模块
def write(self):
folder_path = './****'
i = 0
if os.path.exists(folder_path) == False:
os.makedirs(folder_path)
for herf in self.href_list:
path = folder_path+'/{}'.format(i+1)
txtPath = path + '/{}'.format(i + 1) + '.txt'
if os.path.exists(path) == False:
os.makedirs(path)
open(txtPath, 'w')
print(herf)
with open(txtPath, 'a', encoding='utf-8') as f:
f.write(self.article_content)
这个内容大部分已经涉及到了,忘记的小伙伴可以去看一下我的这篇文章哦!Python爬虫基础之requests+BeautifulSoup+Image 爬取图片并存到本地(四)
5)主函数模块
if __name__ == '__main__':
dl=download()
dl.get_url()
for url in dl.href_list:
dl.readSigleArticle(url)
dl.write()
在这个模块进行函数调用。
四 总结
总而言之,我们这次是通过定义一个download类在类中有多个函数分别实现: def init(self)初始化变量、def get_url(self)获得全部的url、def readSigleArticle(self,herf)读取单篇文章的内容、def write(self)在本地写下文章的内容,通过在主函数if name == 'main’中实例化类,调用类中的方法,实现喜欢博主的全部博文的目的。本篇内容综合应用了前面学到的内容,算是一个阶段的成果。同时也希望大佬们批评指正,因为是新手难免会有说的不恰当甚至错误的内容,还请大佬们不要手下留情。