爬虫系列(六) 用urllib和re爬取百度贴吧
这篇文章我们将使用 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-8pn:当前页面的页码,并且以 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爬取百度贴吧的更多相关文章
- 爬虫系列(十) 用requests和xpath爬取豆瓣电影
这篇文章我们将使用 requests 和 xpath 爬取豆瓣电影 Top250,下面先贴上最终的效果图: 1.网页分析 (1)分析 URL 规律 我们首先使用 Chrome 浏览器打开 豆瓣电影 T ...
- 爬虫系列(十一) 用requests和xpath爬取豆瓣电影评论
这篇文章,我们继续利用 requests 和 xpath 爬取豆瓣电影的短评,下面还是先贴上效果图: 1.网页分析 (1)翻页 我们还是使用 Chrome 浏览器打开豆瓣电影中某一部电影的评论进行分析 ...
- Python3爬虫(1)_使用Urllib进行网络爬取
网络爬虫 又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者,是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫 ...
- 爬虫系列5:scrapy动态页面爬取的另一种思路
前面有篇文章给出了爬取动态页面的一种思路,即应用Selenium+Firefox(参考<scrapy动态页面爬取>).但是selenium需要运行本地浏览器,比较耗时,不太适合大规模网页抓 ...
- 爬虫第六篇:scrapy框架爬取某书网整站爬虫爬取
新建项目 # 新建项目$ scrapy startproject jianshu# 进入到文件夹 $ cd jainshu# 新建spider文件 $ scrapy genspider -t craw ...
- 爬虫系列(四) 用urllib实现英语翻译
这篇文章我们将以 百度翻译 为例,分析网络请求的过程,然后使用 urllib 编写一个英语翻译的小模块 1.准备工作 首先使用 Chrome 浏览器打开 百度翻译,这里,我们选择 Chrome 浏览器 ...
- 爬虫实战(一) 用Python爬取百度百科
最近博主遇到这样一个需求:当用户输入一个词语时,返回这个词语的解释 我的第一个想法是做一个数据库,把常用的词语和词语的解释放到数据库里面,当用户查询时直接读取数据库结果 但是自己又没有心思做这样一个数 ...
- 百度图片爬虫-python版-如何爬取百度图片?
上一篇我写了如何爬取百度网盘的爬虫,在这里还是重温一下,把链接附上: http://www.cnblogs.com/huangxie/p/5473273.html 这一篇我想写写如何爬取百度图片的爬虫 ...
- Python爬虫 - 爬取百度html代码前200行
Python爬虫 - 爬取百度html代码前200行 - 改进版, 增加了对字符串的.strip()处理 源代码如下: # 改进版, 增加了 .strip()方法的使用 # coding=utf-8 ...
随机推荐
- UINavigationController具体解释(一)
@UINavigationControlle简单介绍: 1.导航控制器,专门管理控制器的控制器. 2.採用栈的方式管理全部controller,每一个controller管理各自的视图 @UINavi ...
- 一张图告诉你Git的所有命令
- 上机题目(0基础)- 数据库事务(Java)
/* * 文件名称:JDBCTestCase.java * 版权:Copyright 2006-2011 Huawei Tech. Co. Ltd. All Rights Reserved. * 描写 ...
- 一句话实现Mysql查询结果带行号
SELECT @rowno:=@rowno + 1 AS rowno,a.* FROM tableName a,(SELECT @rowno:=0) b
- How to Integrate .NET Projects with Jenkins
https://www.swtestacademy.com/jenkins-dotnet-integration/ 8) Unit Tests and Test Coverage Settings D ...
- SQL Server2012 T-SQL基础教程--读书笔记(5-7章)
SQL Server2012 T-SQL基础教程--读书笔记(5-7章) SqlServer T-SQL 示例数据库:点我 Chapter 05 表表达式 5.1 派生表 5.1.1 分配列别名 5. ...
- Spark深入之RDD
目录 Part III. Low-Level APIs Resilient Distributed Datasets (RDDs) 1.介绍 2.RDD代码 3.KV RDD 4.RDD Join A ...
- acc文件的运行
1.method 1: use "acc" >acc hello.acc world.mc <--- compilation will generate the hel ...
- bzoj1231[Usaco2008 Nov]mixup2 混乱的奶牛(状压dp)
1231: [Usaco2008 Nov]mixup2 混乱的奶牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1032 Solved: 588[ ...
- Gym - 101981K The 2018 ICPC Asia Nanjing Regional Contest K.Kangaroo Puzzle 暴力或随机
题面 题意:给你1个20*20的格子图,有的是障碍有的是怪,你可以每次指定上下左右的方向,然后所有怪都会向那个方向走, 如果2个怪撞上了,就融合在一起,让你给不超过5w步,让所有怪都融合 题解:我们可 ...