Python urllib模块爬虫实战:从基础请求到贴吧数据抓取
本文详解Python中urllib模块的核心用法,涵盖urlopen发起请求、Request设置User-Agent伪装、urlencode处理查询参数及quote编码等关键步骤。通过百度贴吧多页数据抓取的完整案例,演示如何构建爬虫类、拼接URL并保存HTML文件,帮助开发者掌握基础网络数据采集技能。
Python爬虫基础与urllib模块概述
前言
网络爬虫,亦称网络蜘蛛或网络机器人,是一种自动抓取互联网数据的程序。其核心原理是利用Python程序模拟人类在浏览器中的点击与访问行为,且模拟程度越高,获取数据的成功率通常越大。这类技术主要应用于数据分析、项目测试数据准备以及满足公司业务对特定网络数据的需求。
数据来源渠道多样,既包括企业内部数据库、第三方购买的数据集,也涵盖通过爬虫技术从公开网络获取的信息。在Python生态中,网络爬虫领域已拥有成熟的请求与解析模块,以及功能强大的Scrapy框架,为开发者提供了丰富的工具支持。
爬虫分类
1、通用网络爬虫:主要由搜索引擎使用,需严格遵守robots协议(即君子协议)。
robots协议:网站通过此文件告知搜索引擎哪些页面允许抓取,哪些页面禁止抓取。例如,淘宝的robots协议位于https://www.taobao.com/robots.txt。
2、聚焦网络爬虫:由开发者自行编写的特定用途爬虫程序。
网络爬虫工作流程与分类
爬虫爬取数据步骤
- 确定需要爬取的URL地址
- 由请求模块向指定的URL地址发出请求,并接收网站的响应。
- 从响应内容中提取所需数据
- 从响应中提取所需数据,并进行保存。
- 若页面中存在其他需要继续跟进的URL地址,则重复第2步发送请求,如此循环往复。
urllib.request模块核心用法
请求模块
from urllib import request
request.urlopen() 用于向网站发起请求并获取响应对象。
参数说明:
URL:指定需要爬取的网页地址。
timeout:设置等待响应的超时时间,若指定时间内未收到响应,则抛出超时异常。
响应对象(response)常用方法:
- string = response.read().decode('utf-8'):获取响应对象的内容(即网页源代码)。返回内容类型为字节串bytes,需使用decode转换为字符串string。
- url = response.geturl():返回实际获取数据的URL地址。
- code = response.getcode():返回HTTP响应状态码。
from urllib import request
url = 'http://www.baidu.com/'
# 向百度发请求,得到响应对象
response = request.urlopen(url)
# 返回网页源代码
print(response.read().decode('utf-8'))
# 返回http响应码
print(response.getcode()) # 200
# 返回实际数据URL地址
print(response.geturl()) # http://www.baidu.com/
urllib.request.Request() 用于创建请求对象,通过包装请求(如重构User-Agent),使程序的行为更接近正常人类用户的请求,从而降低被反爬机制拦截的风险。
参数说明:
URL:指定请求的目标URL地址。
headers:添加请求头信息,这是爬虫与反爬虫策略博弈的第一步。
使用流程:
1、创建请求对象(重构User-Agent)
req = urllib.request.Request(url=url,headers={'User-Agent':'Mozilla/5.0 xxxx'})
2、利用请求对象发起请求,获取响应对象(通过urlopen)
res = urllib.request.urlopen(req)
3、通过响应对象获取响应内容
html = res.read().decode('utf-8')
from urllib import request
url = 'http://httpbin.org/get'
headers = {'User-Agent':'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3)'}
# 创建请求对象(包装请求)
req = request.Request(url=url,headers=headers)
# 发请求,获取响应对象
res = request.urlopen(req)
# 读取内容,返回网页代码
html = res.read().decode('utf-8')
print(html)
URL编码与参数拼接技巧
URL地址编码
urllib.parse.urlencode({dict}):用于对字典格式的查询参数进行编码。
URL地址中单个查询参数的处理。
示例查询参数:{'wd' : '美女'}
经urlencode编码后结果:'wd=%e7%be%8e%e5%a5%b3'
from urllib import parse
url = 'http://www.baidu.com/s?'
query_string = parse.urlencode({'wd':'美女'})
print(query_string) # wd=%E7%BE%8E%E5%A5%B3
url = url + query_string
# http://www.baidu.com/wd=%E7%BE%8E%E5%A5%B3
URL地址中多个查询参数的处理。
from urllib import parse
query_string_dict = {'wd' : '美女',
'pn' : '50'}
query_string = parse.urlencode(query_string_dict)
url = 'http://www.baidu.com/s?{}'.format(query_string)
print(url)
# http://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3&pn=50
拼接URL地址的3种常用方式:
1、字符串直接相加
'https://www.baidu.com/s?' + urlencode({'wd':'美女','pn':'50'})
2、字符串格式化(使用占位符)
'https://www.baidu.com/s?%s' % urlencode({'wd':'美女','pn':'50'})
3、使用format()方法
'https://www.baidu.com/s?{}'.format(urlencode({'wd':'美女','pn':'50'}))
示例:在百度搜索指定内容,并将响应内容保存到本地文件。
from urllib import request
from urllib import parse
# 定义常用变量
word = input('请输入搜索内容:')
url = 'http://www.baidu.com/s?'
headers = {'User-Agent':'Mozilla/5.0'}
# url编码,拼接完整URL
query_string = parse.urlencode({'wd':word})
url = url + query_string
# 三步走
req = request.Request(url=url,headers=headers)
res = request.urlopen(req)
html = res.read().decode('utf-8')
filename = '{}.html'.format(word)
with open(filename,'w',encoding='utf-8') as f:
f.write(html)
urllib.parse.quote(string):用于对字符串进行URL编码。
from urllib import parse
parse.quote('美女') # %E7%BE%8E%E5%A5%B3
urllib.parse.unquote(string):用于对URL编码后的字符串进行解码。
from urllib import parse
result = parse.unquote('%E7%BE%8E%E5%A5%B3')
print(result) # 美女
百度贴吧多页数据抓取实战
百度贴吧网页数据获取实战
- 输入贴吧名称
- 输入起始页码
- 输入终止页码
- 保存至本地文件:生成如第1页.html、第2页.html等文件。
实现步骤:
1、分析URL规律
1、不同贴吧的URL差异
2、不同页码的URL差异
第1页URL示例:http://tieba.baidu.com/f?kw=????&pn=0
第2页URL示例:http://tieba.baidu.com/f?kw=????&pn=50
第n页URL规律:pn=(n-1)*50
2、获取网页内容
3、保存数据(本地文件或数据库)
from urllib import request,parse
import time
import random
class BaiduSpider(object):
def __init__(self):
self.url = 'http://tieba.baidu.com/f?kw={}&pn={}'
self.headers = {'User-Agent':'Mozilla/5.0'}
# 获取响应
def get_page(self,url):
req = request.Request(url=url,headers=self.headers)
res = request.urlopen(req)
html = res.read().decode('utf-8')
return html
# 保存数据
def write_page(self,filename,html):
with open(filename,'w') as f:
f.write(html)
# 主函数
def main(self):
name = input('请输入贴吧名:')
start = int(input('请输入起始页:'))
end = int(input('请输入终止页:'))
# 拼接URL地址,发请求
for page in range(start,end+1):
pn = (page-1)*50
kw = parse.quote(name) # url编码
url = self.url.format(kw,pn)
html = self.get_page(url) # 获取响应,并保存
filename = '{}-第{}页.html'.format(name,page)
self.write_page(filename,html)
print('第{}页爬取成功'.format(page)) # 提示进度
time.sleep(random.randint(1,3)) # 控制爬取速度
if __name__ == '__main__':
spider = BaiduSpider()
spider.main()
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









