- 哈罗啊,又见面了,这几天考试+各种事情,耽误了点时间,不够我终于又做了个案例
- 还是看着知乎大神的帖子Wakingup的帖子
- 话不多说,上代码
'''
根据知乎大神
代码作者:高佳乐
'''
##先导入各种库
import re ##re正则表达式
import requests ##获取url
from bs4 import BeautifulSoup ##bs4解析
import time ##爬虫嘛,要有礼貌
import random ##开始我想用随机数转换head来着,试了试没事
import os ##弄文件及,一页一个文件夹
from lxml import etree ##xpath的库
##定义一个类,爬虫
class spider():
##初始化
def __init__(self): ##初始化函数
self.url = 'http://tieba.baidu.com' ##使他的初始化函数是贴吧首页
return
##获取贴吧的url
def getUrl(self,url): ##获取url的函数(参数是一个url,网址)
html = requests.get(url) ##html是requests.get获取到的源码
html_text = html.text ##html_text是上边获取到代码后然后书写进来
return html_text ##这个函数返回html_text以便赋值
##获取帖子的标题
def title(self,url):
html = self.getUrl(url) ##html是用getUrl获取到的代码
soup = BeautifulSoup(html,'lxml') ##soup是用BeautiflSoup解析的结构树,用的是lxml
title = soup.find(class_="core_title_txt")##然后获取class=“core_title_text”的节点
#print('这个贴吧的标题是:',title.get_text()) ##这个已经注释了,解释也没用了
return title.get_text() ##返回的是上边获到标题节点的内容
##获取帖子的总页数
def pages(self,url): ##这个函数是获取总页数
html = self.getUrl(url) ##html是用getUrl获取到的代码
soup = etree.HTML(html) ##然后soup是用etree.HTML把上边获得的代码解析,以便使用xpath
pages = soup.xpath('.//div[@id="thread_theme_5"]//li[@class="l_reply_num"]/span[last()]')##因为用正则有点麻烦我感觉,用bs4我也觉得有点烦,就用了xpath,xpath刚开始用,原谅我太菜
for page in pages: ##上边的xpath是在此节点中不管那个位置的id=“thread_theme_5的div里不管在哪的class=“l_reply_num”的li的最后一个span
break; ##因为获得的是列表,所以要遍历,因为我只获取一个值,所以我在这个循环里循环后直接结束
return page.text ##因为上边返回的是一个那样的,所以返回值带上text返回文本
##获取楼主和内容
def content(self,url): ##获取楼主的内容,参数是url
html = self.getUrl(url) ##html是用getUrl获取到的代码
##我用的正则,有点麻烦,用在我这个帖子里好使,别的没准就报错了,推荐用xpath或者Bs4
zhengze = re.compile('<li.*?_author_name.*?_blank.*?(.*?)</a>.*?d_post_content.*?save_face_bg_hidden.*?d_post_content j_d_post_content.*?>(.*?)</div>',re.S)
contents = re.findall(zhengze,html) ##上边是定义一个正则,这里就是使用在html筛选上边条件的全部节点,返回列表
number = 1 ##计数器,这是个记住器,以便记住第几楼
for i in contents:
print('第%d个帖子\n楼主:%s\n内容:%s\n'%(number,i[0],i[1]))
print()
number+=1
##获取图片
def img(self,url): ##获取图片的函数
html = self.getUrl(url) ##html也是用getUrl获取的代码
soup = BeautifulSoup(html,'lxml') ##soup是用BS4解析的代码,用的lxml
images = soup.select('img[class="BDE_Image"]')##然后用select查到符合‘class=“BDE_Image”’的img标签,返回列表
number = 0 ##这是个计数器,
imgs = [] ##这里创建一个空列表以便吧图片地址存到这里,你会问上边不是有了吗,其实上边是有列表,但是上边的是节点的列表就是还设有别的属性,咱们只要scr属性的
for i in images: ##这是一个计一页有多少图片的方法,当然这是最屌丝的方法
number+=1 ##读取一个节点,number+1
if number > 0: ##计数下来,number>0的话
print('厉害,厉害,这里有%s个图片,爬完就跑,刺激'%number)##输出这点话
else: ##反之就是<=0 就说这话
print('这里没有图片,快跑')
number = 1 ##这里number在=1,以便计数
for image in images: ##用image在images读取,也就是在上边爬到的图片节点中读取
img = image.get('src') ##这里get(src)就是,img只获得这个节点的src属性,就是纯url了
print('正在爬取,第%d图片:'%number,img)##输出上边获取图片的url
imgs.append(img) ##然后把上边的纯连接img追加到开始创建的那个空列表里,这不就会成为一个纯连接的列表了
number+=1 ##number+1 以便计数
return imgs ##返回那个纯连接的列表
##创建文件夹,和图片
def make(self,name): ##创建文件夹的函数
dir = os.getcwd()+'\第'+str(name)+'文件夹' ##先定义文件的名字,就是os.getcwd获取当前工作路径,+文件夹的名
# 去除首位空格
dir = dir.strip()
# 去除尾部 \ 符号
dir = dir.rstrip('\\')
##判断目录是否存在
panduan = os.path.exists(dir) ##exists判断目录是否存在,是=true,否=False
if panduan: ##如果有就已存在
print(dir,'已存在')
else: ##反之,也就是假,没有
os.makedirs(dir) ##就创建这个文件夹,当然我这的路径是绝对路径
print(dir,'已创建成功')
return dir ##返回那个文件夹的路径,以便下边的切换路径
##保存图片
def saveimage(self,url): ##保存图片了
images = self.img(url) ##images是用img获取到的纯连接的那个列表
num = 1 ##num=1计数器
for img in images: ##用循环让img在那个返回的纯连接的列表里读取
fil = str(num) + '.jpg' ##然后定义图片名字.jpg
html = requests.get(img).content ##因为直接一个地址是写不到图片里边去的,要写入二进制,所以要先获取那个图片的内容,然后.content转化成二进制
f = open(fil,'wb') ##然后打开fil的文件可写可读,没有就是创建
f.write(html) ##然后写入图片的二进制
f.close() ##然后关闭,随手关闭是个好孩子
num+=1 ##当然计数器要+1
print('第%s保存成功'%fil) ##提示图片保存成功更有逼格
##操控,一个贴吧的操控
def all(self,number): ##这个函数就是把所有的方法封装到这里
##贴吧地址是self.url+帖子号
url = self.url+'/p/'+str(number) ##因为地址也是首页+帖子号,这个也是第一页
##获取标题
title = self.title(url) ##有title方法获取标题
print('这个帖子的标题是%s'%title)
##获取总页数
page = int(self.pages(url)) ##用pages获取帖子总页数,并转换成整数型,以便下边的+1
##根据总页数获取全部的页数,并获取图片
num = 1 ##num这里就是计数,页数了
print('第1页') ##这里是第一页
##获取内容
self.content(url) ##第一页是不加pn的所以要单独分开来获取,url是上边弄得首页+帖子号,这里是获取内容和楼主
self.img(url) ##这里是获取图片的详细资料
dir = self.make(num) ##这里是创建文件夹,因为一页保存一个文件夹,所以这是第一个
os.chdir(dir) ##上边创建好文件夹后,转换到文件夹下
self.saveimage(url) ##然后保存,然后就跑
num+=1 ##第一页保存了,当然是第二页了,后边的页数也不一样了,
for i in range(num,page+1): ##之前获取到的总页数在这里,因为要获取全部,第一页之前已经获取了,这里既是从第2页开始到总页数+1后停止,为什么+1?因为for取首不娶尾
url_2 = url + '?pn=' + str(i) ##这里是给每页的url获取,因为第二页后每页都是首页+帖子号+?pn=页数了
print('第%d页'%i) ##计数第几页
time.sleep(1) ##爬虫要礼貌,礼貌,所以要sleep,1.。其实我打算想着0.1,但是为了世界和平所以要大点了,→_→
self.content(url_2) ##获取第i页这内容
self.img(url_2) ##获取第i页图片详情
dir = self.make(i) ##然后创建第i个文件夹,根据i的数创建
os.chdir(dir) ##然后切换到新创建的第i个文件夹里
time.sleep(1) ##然后讲一下礼貌
self.saveimage(url_2) ##然后保存第i页的图片
time.sleep(1) ##再讲一下礼貌
img = spider()
img.all(int(input('输入帖子号')))
-
(这段是一个内心的小活动,可以省略看下边)
学校换老师开始前端实例了┓( ´-` )┏,偷偷告诉你们我其实学的专业是ui设计,不会代码的ui不是一个好美工( ̄ー ̄),所以我决定好好学前端了,据说这样可以避免以后工作上和程序员的矛盾,嘛哈哈哈。当然爬虫我也要抓住,好不容易有这样的机会。 -
这里,这次是把贴吧,旅游吧里的一个帖子爬图片和内容,足不出户,就可以看美景,还出去什么旅游,还不如在宿舍乖乖敲代码。emm对了我那个抓取楼主和内容的时候用的正则,可能我这好使别的就不好使了,没时间改xpath了(其实不也不知道能不能改),见谅。
-
好了到了这就要再见了,砸门下次再见。坚持,加油,努力。
网友评论