这篇文章我们将使用 urllib 和 re 模块爬取百度贴吧,并使用三种文件格式存储数据,下面先贴上最终的效果图

1、网页分析

(1)准备工作

首先我们使用 Chrome 浏览器打开 百度贴吧,在输入栏中输入关键字进行搜索,这里示例为 “计算机吧”

(2)分析 URL 规律

接下来我们开始分析网站的 URL 规律,以便于通过构造 URL 获取网站中所有网页的内容

第一页:http://tieba.baidu.com/f?kw=计算机&ie=utf-8&pn=0

第二页:http://tieba.baidu.com/f?kw=计算机&ie=utf-8&pn=50

第三页:http://tieba.baidu.com/f?kw=计算机&ie=utf-8&pn=100

...

通过观察不难发现,它的 URL 十分有规律,主要的请求参数分析如下:

  • kw:搜索的关键字,使用 URL 编码,可以通过 urllib.parse.quote() 方法实现
  • ie:字符编码的格式,其值为 utf-8
  • pn:当前页面的页码,并且以 50 为步幅增长

所以完整的 URL 可以泛化如下:http://tieba.baidu.com/f?kw={keyword}&ie=utf-8&pn={page}

核心代码如下:

import urllib.request
import urllib.parse
# 获取网页源代码
def get_page(url):
# 构造请求头部
headers = {
'USER-AGENT':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
# 构造请求对象
req = urllib.request.Request(url=url,headers=headers)
# 发送请求,得到响应
response = urllib.request.urlopen(req)
# 获得网页源代码
html = response.read().decode('utf-8')
# 返回网页源代码
return html

(3)分析内容规律

接下来我们直接使用快捷键 Ctrl+U 打开网页的源代码,认真分析每一页中我们需要抓取的数据

容易发现每一个帖子的内容都被包含在一个 <li> 标签中,我们可以使用正则表达式进行匹配,具体包括:

  • 主题名称:r'href="/p/\d+" title="(.+?)"'
  • 主题作者:r'title="主题作者: (.+?)"'
  • 链接地址:r'href="/p/(\d+)"'
  • 回复数:r'title="回复">(\d+)<'
  • 创建日期:r'title="创建时间">(.+?)<'

核心代码如下:

import re
# 解析网页源代码,提取数据
def parse_page(html):
# 主题名称
titles = re.findall(r'href="/p/\d+" title="(.+?)"',html)
# 主题作者
authods = re.findall(r'title="主题作者: (.+?)"',html)
# 链接地址
nums = re.findall(r'href="/p/(\d+)"',html)
links = ['http://tieba.baidu.com/p/'+str(num) for num in nums]
# 回复数量
focus = re.findall(r'title="回复">(\d+)',html)
# 创建时间
ctimes = re.findall(r'title="创建时间">(.+?)<',html)
# 获得结果
data = zip(titles,authods,links,focus,ctimes)
# 返回结果
return data

(4)保存数据

下面将数据保存为 txt 文件、json 文件和 csv 文件

import json
import csv
# 打开文件
def openfile(fm,fileName):
fd = None
if fm == 'txt':
fd = open(fileName+'.txt','w',encoding='utf-8')
elif fm == 'json':
fd = open(fileName+'.json','w',encoding='utf-8')
elif fm == 'csv':
fd = open(fileName+'.csv','w',encoding='utf-8',newline='')
return fd # 将数据保存到文件
def save2file(fm,fd,data):
if fm == 'txt':
for item in data:
fd.write('----------------------------------------\n')
fd.write('title:' + str(item[0]) + '\n')
fd.write('authod:' + str(item[1]) + '\n')
fd.write('link:' + str(item[2]) + '\n')
fd.write('focus:' + str(item[3]) + '\n')
fd.write('ctime:' + str(item[4]) + '\n')
if fm == 'json':
temp = ('title','authod','link','focus','ctime')
for item in data:
json.dump(dict(zip(temp,item)),fd,ensure_ascii=False)
if fm == 'csv':
writer = csv.writer(fd)
for item in data:
writer.writerow(item)

2、编码实现

完整代码如下,也很简单,还不到 100 行

import urllib.request
import urllib.parse
import re
import json
import csv
import time
import random # 获取网页源代码
def get_page(url):
headers = {
'USER-AGENT':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
req = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(req)
html = response.read().decode('utf-8')
return html # 解析网页源代码,提取数据
def parse_page(html):
titles = re.findall(r'href="/p/\d+" title="(.+?)"',html)
authods = re.findall(r'title="主题作者: (.+?)"',html)
nums = re.findall(r'href="/p/(\d+)"',html)
links = ['http://tieba.baidu.com/p/'+str(num) for num in nums]
focus = re.findall(r'title="回复">(\d+)',html)
ctimes = re.findall(r'title="创建时间">(.+?)<',html)
data = zip(titles,authods,links,focus,ctimes)
return data # 打开文件
def openfile(fm,fileName):
if fm == 'txt':
return open(fileName+'.txt','w',encoding='utf-8')
elif fm == 'json':
return open(fileName+'.json','w',encoding='utf-8')
elif fm == 'csv':
return open(fileName+'.csv','w',encoding='utf-8',newline='')
else:
return None # 将数据保存到文件
def save2file(fm,fd,data):
if fm == 'txt':
for item in data:
fd.write('----------------------------------------\n')
fd.write('title:' + str(item[0]) + '\n')
fd.write('authod:' + str(item[1]) + '\n')
fd.write('link:' + str(item[2]) + '\n')
fd.write('focus:' + str(item[3]) + '\n')
fd.write('ctime:' + str(item[4]) + '\n')
if fm == 'json':
temp = ('title','authod','link','focus','ctime')
for item in data:
json.dump(dict(zip(temp,item)),fd,ensure_ascii=False)
if fm == 'csv':
writer = csv.writer(fd)
for item in data:
writer.writerow(item) # 开始爬取网页
def crawl():
kw = input('请输入主题贴吧名字:')
base_url = 'http://tieba.baidu.com/f?kw=' + urllib.parse.quote(kw) + '&ie=utf-8&pn={page}'
fm = input('请输入文件保存格式(txt、json、csv):')
while fm!='txt' and fm!='json' and fm!='csv':
fm = input('输入错误,请重新输入文件保存格式(txt、json、csv):')
fd = openfile(fm,kw)
page = 0
total_page = int(re.findall(r'共有主题数<span class="red_text">(\d+)</span>个',get_page(base_url.format(page=str(0))))[0])
print('开始爬取')
while page < total_page:
print('正在爬取第', int(page/50+1), '页.......')
html = get_page(base_url.format(page=str(page)))
data = parse_page(html)
save2file(fm,fd,data)
page += 50
time.sleep(random.random())
fd.close()
print('结束爬取') if __name__ == '__main__':
crawl()

【爬虫系列相关文章】

爬虫系列(六) 用urllib和re爬取百度贴吧的更多相关文章

  1. 爬虫系列(十) 用requests和xpath爬取豆瓣电影

    这篇文章我们将使用 requests 和 xpath 爬取豆瓣电影 Top250,下面先贴上最终的效果图: 1.网页分析 (1)分析 URL 规律 我们首先使用 Chrome 浏览器打开 豆瓣电影 T ...

  2. 爬虫系列(十一) 用requests和xpath爬取豆瓣电影评论

    这篇文章,我们继续利用 requests 和 xpath 爬取豆瓣电影的短评,下面还是先贴上效果图: 1.网页分析 (1)翻页 我们还是使用 Chrome 浏览器打开豆瓣电影中某一部电影的评论进行分析 ...

  3. Python3爬虫(1)_使用Urllib进行网络爬取

    网络爬虫 又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者,是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫 ...

  4. 爬虫系列5:scrapy动态页面爬取的另一种思路

    前面有篇文章给出了爬取动态页面的一种思路,即应用Selenium+Firefox(参考<scrapy动态页面爬取>).但是selenium需要运行本地浏览器,比较耗时,不太适合大规模网页抓 ...

  5. 爬虫第六篇:scrapy框架爬取某书网整站爬虫爬取

    新建项目 # 新建项目$ scrapy startproject jianshu# 进入到文件夹 $ cd jainshu# 新建spider文件 $ scrapy genspider -t craw ...

  6. 爬虫系列(四) 用urllib实现英语翻译

    这篇文章我们将以 百度翻译 为例,分析网络请求的过程,然后使用 urllib 编写一个英语翻译的小模块 1.准备工作 首先使用 Chrome 浏览器打开 百度翻译,这里,我们选择 Chrome 浏览器 ...

  7. 爬虫实战(一) 用Python爬取百度百科

    最近博主遇到这样一个需求:当用户输入一个词语时,返回这个词语的解释 我的第一个想法是做一个数据库,把常用的词语和词语的解释放到数据库里面,当用户查询时直接读取数据库结果 但是自己又没有心思做这样一个数 ...

  8. 百度图片爬虫-python版-如何爬取百度图片?

    上一篇我写了如何爬取百度网盘的爬虫,在这里还是重温一下,把链接附上: http://www.cnblogs.com/huangxie/p/5473273.html 这一篇我想写写如何爬取百度图片的爬虫 ...

  9. Python爬虫 - 爬取百度html代码前200行

    Python爬虫 - 爬取百度html代码前200行 - 改进版,  增加了对字符串的.strip()处理 源代码如下: # 改进版, 增加了 .strip()方法的使用 # coding=utf-8 ...

随机推荐

  1. 权限问题导致无法删除ftp文件

    首先吐槽一下,使用新版编辑器,发了两遍愣是time out,果断放弃 这个文章也是一件小事,大致说一下: 有一个java操作ftp文件的程序,运行删除时,总是返回false,也没有报错.開始考虑是没有 ...

  2. java常见的面试题

    1. super()与this()的差别? super和this的差别: 1)super(參数):调用基类中的某一个构造函数(应该为构造函数中的第一条语句) 2)this(參数):调用本类中还有一种形 ...

  3. SQL SEVER 2008中的演示样例数据库

    SQL SEVER 2008数据库是什么我就不说了,我在这里分享一下怎样学习SQL SEVER 2008数据库,假设是对数据库或是SQL SEVER 数据库全然陌生或是不熟悉的人来说,建议看看一些视频 ...

  4. ant+jmeter中build.xml配置详解

  5. cocos2d-x 3.1.1 学习笔记[16] Particle 粒子效果

    //plist文件中面有粒子效果的各种參数 //textureFileName相应着使用粒子的图片 auto particle = ParticleSystemQuad::create("s ...

  6. ubuntu如何完全卸载和安装 Java及android环境?【转】

    本文转载自:https://my.oschina.net/lxrm/blog/110638 最近,迷上了java,一时间什么环境变量/虚拟机都猛然袭来,有点不适.环境配置在前,这所自然.平时搞PHP都 ...

  7. javascript 将变量值作为对象属性 获取对象对应的值

    例子 var var="name"; var objname="obj"; objname=objname+"."+var; alert(e ...

  8. DCloud-MUI:窗口管理

    ylbtech-DCloud-MUI:窗口管理 通过预加载解决切页白屏问题,通过封装原生动画解决SPA模式的动画卡顿 1.返回顶部 1.页面初始化 在app开发中,若要使用HTML5+扩展api,必须 ...

  9. 工具分享1:文本编辑器EditPlus、汇编编译器masm、Dos盒子

    工具已打包好,需要即下载 链接 https://pan.baidu.com/s/1dvMyvW 密码 mic4

  10. jQuery学习笔记之插件开发(4)

    jQuery学习笔记之插件开发(4) github源码地址 插件:了让原有功能的增强. 1.插件的种类(3种):局部.全局.选择器插件 1.1封装对象方法的插件 这种类型的插件是把一些常用或者重复使用 ...