爬虫开发01--request模块

it2026-06-15  7

 

目录

request模块

request模块的编码流程

解决response返回中文乱码问题

request实战

1、爬取整个页面的数据--不带参数的get请求

2、爬取整个页面的数据--带请求参数params和请求头headers的get请求

3、爬取页面局部数据(Ajax请求返回json数据)--带参数的post请求

4、爬取页面局部数据(鼠标滚动,获取页面动态加载的json数据)--带参数的post请求

5、爬取页面局部数据(按照查询的关键字,获取页面动态加载的文本数据)--带参数的post请求

6、通过页面动态加载,获取公司id,再通过id获取公司详情信息--post请求

7、图片数据爬取


request模块

python中原生的一款基于网络请求的模块,功能强大,简单便捷,效率很高;模拟浏览器发请求;同类的比较老的模块是urllib模块;安装:pip install --user requests

 

request模块的编码流程

指定url发起请求获取响应数据持久化存储

 

解决response返回中文乱码问题

response.encoding = 'utf-8',指定响应报文的编码格式(中文乱码情况);response默认使用iso-8859-1编码对消息体进行编码,传送数据给客户端。已经爬好的带有\u5430的字符串怎么转为正常的中文显示字符串? python3: 字符串.encode(‘utf-8’).decode(‘unicode_escape’)

 

request实战

1、爬取整个页面的数据--不带参数的get请求

需求:爬取搜狗首页的页面数据

爬取地址:https://www.sogou.com/

 

获取不带参数的get请求的响应报文

# 1、需求:爬取搜狗首页的页面数据 # 获取不带参数的get请求的响应报文 import requests def getHtmlPageText(): # 指定url url = 'https://www.sogou.com/' # 发起请求 response = requests.get(url) # 获取字符串类型的响应数据(参考接口返回的Content-Type类型) page_text = response.text # 持久化存储 with open('./sougou.html', 'w', encoding='UTF-8') as file: file.write(page_text) print('爬虫结束') if __name__ == '__main__': getHtmlPageText()

输出结果:当前脚本目录保存sougou.html

 

2、爬取整个页面的数据--带请求参数params和请求头headers的get请求

需求:爬取搜狗指定词条对应的搜索结果页面(简易网页采集器)

爬取地址:https://www.sogou.com/

 

请求参数params和请求头headers的get请求

封装请求参数params和请求头headers的字典;params,请求带有参数;headers,请求访问时,要UA伪装,伪装是浏览器发起的请求,就要设置User-Agent(请求载体的身份标识);UA检测,指门户网站的服务器会检测,对应请求的载体身份标识,如果检测到请求的载体身份标识为某一款浏览器,说明该请求是一个正常的请求;如果检测到请求的载体身份标识不是基于某一款浏览器的,则表示该请求为不正常的请求(即爬虫),服务器端就可能拒绝该次请求;UA伪装,让爬虫对应的请求载体身份标识伪装成某一款浏览器;response.encoding = 'utf-8',指定响应报文的编码格式(中文乱码情况);response默认使用iso-8859-1编码对消息体进行编码,传送数据给客户端。已经爬好的带有\u5430的字符串怎么转为正常的中文显示字符串? python3: 字符串.encode(‘utf-8’).decode(‘unicode_escape’) # 2、需求:爬取搜狗指定词条对应的搜索结果页面(简易网页采集器) # 获取带有请求参数params和headers的get请求的响应报文 import requests def getSearchResultPage(searchKeyword): url = 'https://www.sogou.com/web' # 直接访问搜索结果页面,处理url携带的参数,封装到字典中 param = { 'query': searchKeyword } # UA伪装,将对应的User-Agent封装到一个字典中 header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36' } # 对指定的url发起的请求,对应url是携带参数的,并且请求过程中处理了参数 response = requests.get(url, params=param, headers=header) # response默认使用iso-8859-1编码对消息体进行编码,传送数据给客户端。 # 指定响应报文的编码格式 response.encoding = 'utf-8' page_text = response.text fileName = searchKeyword + '.html' with open(fileName, 'w', encoding='utf-8') as file: file.write(page_text) print('爬虫结束') if __name__ == '__main__': getSearchResultPage("python") getSearchResultPage("测试")

输出结果:

 

3、爬取页面局部数据(Ajax请求返回json数据)--带参数的post请求

需求:破解百度翻译(页面局部刷新后,结果的获取,即Ajax请求的响应结果)

爬取的请求地址:https://fanyi.baidu.com/langdetect

Ajax请求返回的json对象数据,是字典类型;

持久化存储,保存格式为.json文件;

with open('xxx.json', 'w', encoding='utf-8') as file: json.dump(response.json(), fp=file, ensure_ascii=False)

# 3、带参数的post请求,爬取页面中某个局部的数据(Ajax请求数据的返回结果) # 需求:破解百度翻译(页面局部刷新后,结果的获取,即Ajax请求的响应结果) import requests import json def getWordsTranslation(keyword): post_url = 'https://fanyi.baidu.com/v2transapi' # UA伪装 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36' } # post请求body data = { 'from': 'en', 'to': 'zh', 'query': keyword, 'transtype': 'realtime', 'simple_means_flag': '3', 'sign': '871501.634748', 'token': '849a7650ac16b0f2af46dbaaf4416389', 'domain': 'common' } response = requests.post(url=post_url, data=data, headers=headers) # Ajax请求返回的json对象数据,是字典类型 dict_obj = response.json() # 持久化存储 fileName = keyword + '.json' with open(fileName, 'w', encoding='utf-8') as file: json.dump(dict_obj, fp=file, ensure_ascii=False) print('爬虫结束') if __name__ == '__main__': getWordsTranslation("dog")

输出结果:百度翻译增加了反爬机制,所以爬虫程序获取不到翻译结果了;参考分析方式进行学习;

{"errno": 997, "errmsg": "未知错误", "query": "dog", "from": "en", "to": "zh", "error": 997}

 

4、爬取页面局部数据(鼠标滚动,获取页面动态加载的json数据)--带参数的post请求

需求:爬取豆瓣电影分类排行榜中的电影详情数据

豆瓣排行榜地址:https://movie.douban.com/typerank?type_name=喜剧&type=24&interval_id=100:90&action=

实际爬取地址:https://movie.douban.com/j/chart/top_list

# 4、需求:爬取豆瓣电影分类排行榜中的电影详情数据 # 爬取喜剧类型的电影详情数据(页面数据随着鼠标滚动发起ajax请求获取到json对象数据) import requests import json def getPageData(get_url, type, type_name, start, limit): header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36' } param = { 'type': type, 'interval_id': '100:90', 'action': '', 'start': start, # 从库中的第几部电影去取 'limit': limit # 一次取出的个数 } response = requests.get(url=get_url, params=param, headers=header) list_data = response.json() file_name = type_name + '.json' with open(file_name, 'w', encoding='utf-8') as file: json.dump(list_data, fp=file, ensure_ascii=False) print('爬虫结束') if __name__ == '__main__': get_url = 'https://movie.douban.com/j/chart/top_list' start = '0' # 从库中的第几部电影去取 limit = '20' # 一次取出的个数 # 获取喜剧排行榜 type = '24' type_name = '喜剧' getPageData(get_url, type, type_name, start, limit) # 获取喜剧排行榜 type = '13' type_name = '爱情' getPageData(get_url, type, type_name, start, limit)

输出结果:

 

5、爬取页面局部数据(按照查询的关键字,获取页面动态加载的文本数据)--带参数的post请求

需求:爬取肯德基餐厅查询中指定地点的餐厅数

肯德基餐厅查询地址:http://www.kfc.com.cn/kfccda/storelist/index.aspx

实际爬取地址:http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx

# 5、需求:爬取肯德基餐厅查询中指定地点的餐厅数 import requests import json def getStoreList(post_url, store_keyword): header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36' } param = { "op": "keyword", "cname": "", "pid": "", "keyword": "嘉定", "pageIndex": "1", "pageSize": "10" } response = requests.post(url=post_url, params=param, headers=header) page_text = response.text with open(store_keyword + '.html', 'w', encoding='utf-8') as file: file.write(page_text) print('爬虫结束') if __name__ == '__main__': post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx' # 餐厅关键字 store_keyword = '嘉定' getStoreList(post_url, store_keyword)

输出结果:

{"Table":[{"rowcount":5}],"Table1":[{"rownum":1,"storeName":"嘉定城北","addressDetail":"平城路1188号","pro":"Wi-Fi,礼品卡,溯源","provinceName":"上海市","cityName":"上海市"},{"rownum":2,"storeName":"嘉定","addressDetail":"清河路8号","pro":"24小时,Wi-Fi,礼品卡,生日餐会,溯源","provinceName":"上海市","cityName":"上海市"},{"rownum":3,"storeName":"泰城","addressDetail":"嘉定镇沿江路泰城时尚广场一楼肯德基","pro":"Wi-Fi,生日餐会","provinceName":"江西省","cityName":"赣州市"},{"rownum":4,"storeName":"嘉定万达","addressDetail":"胜辛路426号2层2062、2063号商铺","pro":"Wi-Fi","provinceName":"上海市","cityName":"上海市"},{"rownum":5,"storeName":"嘉定万达甜品站","addressDetail":"胜辛路426号","pro":"Wi-Fi","provinceName":"上海市","cityName":"上海市"}]}

 

6、通过页面动态加载,获取公司id,再通过id获取公司详情信息--post请求

需求:爬取国家药品监督管理总局中基于中华人民共和国化妆品生产许可证相关数据

化妆品许可证网址:http://scxk.nmpa.gov.cn:81/xk/

访问的化妆品许可证网址,不能直接获取到数据,需要访问动态加载的地址,才能获取到数据;

实际爬取地址1:http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList

实际爬取地址2:http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById

1)在化妆品公司查询页面,通过动态加载,获取到所有公司的id;

2)再分别通过id,获取到对应公司的所有化妆品详情信息;

# 6、通过页面动态加载,获取公司id,再通过id获取公司详情信息--post请求 # 需求:爬取国家药品监督管理总局中基于中华人民共和国化妆品生产许可证相关数据 import requests # 在查询页面,获取所有化妆品公司的id def getAllCompanyId(post_url, header): page_size = '15' # 每次请求获取15个记录 page_count = 10 # 获取10页公司数据 companys_id_list = [] # 所有化妆品公司的id for page_no in range(1, page_count + 1): param = { "on": "true", "page": page_no, "pageSize": page_size, "productName": "", "conditionType": "1", "applyname": "", "applysn": "" } response = requests.post(url=post_url, params=param, headers=header) response.encoding = 'utf-8' print(response.text) dict_data = response.json() for i in range(0, int(page_size)): companys_id_list.append(dict_data['list'][i]['ID']) return companys_id_list # 依据化妆品公司id,获取对应化妆品公司的企业生产许可信息 def getCompanysInfo(post_url, header, companys_id_list): # 化妆品公司的企业生产许可信息 all_companys_info = [] for id in companys_id_list: param = { 'id': str(id) } response = requests.post(url=post_url, headers=header, params=param) company_info = response.json() all_companys_info.append(company_info) # 数据持久化,将企业生产许可信息保存为.csv格式 with open('companyInfo.csv', 'w', encoding='gbk') as file: file.write('企业名称,许可证编号,法定代表人,状态\n') for company_info in all_companys_info: str_lst = [company_info['epsName'], company_info['productSn'],company_info['legalPerson'],company_info['xkType']+'\n'] file.write(','.join(str_lst)) if __name__ == '__main__': header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36' } # 在查询页面,获取所有化妆品公司的id companys_post_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList' companys_id_list = getAllCompanyId(companys_post_url, header) # 依据化妆品公司id,获取对应化妆品公司的企业生产许可信息,并持久化 companyinfo_post_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById' getCompanysInfo(companyinfo_post_url, header, companys_id_list)

输出结果:

 

7、图片数据爬取

需求:爬取糗事百科中糗图板块下所有的糗图图片

1)爬取一张糗图图片

response.content,返回的是二进制形式的图片数据;response.text,返回的是字符串;response.json(),返回的是json对象; # 需求:爬取一张糗图图片 import requests import os.path import os def getPicture(): if not os.path.exists('qiutu'): os.mkdir('qiutu') get_pic_url = 'https://pic.qiushibaike.com/system/pictures/12372/123723104/medium/BJ1W0M0W681LJ4Z2.jpg' header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36' } response = requests.get(url=get_pic_url, headers=header) # content返回的是二进制形式的图片数据 img_data = response.content with open('./qiutu/BJ1W0M0W681LJ4Z2.jpg', 'wb') as file: file.write(img_data) print('爬虫结束') if __name__ == '__main__': getPicture()

输出结果:

 

2)爬取糗事百科中糗图板块下所有的糗图图片

# 爬取糗事百科中糗图板块下所有的糗图图片 import requests import re import os import os.path # 获取所有糗图的src请求地址,返回list类型 def getImageSrc(get_url, header): session = requests.session() session.keep_alive = False # 关闭多余连接 response = session.get(url=get_url, headers=header) response.encoding = 'utf-8' # 爬取url对应的一整张页面内容 page_text = response.text # 使用聚焦爬虫将页面中所有的糗图进行解析/提取 ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>' img_src_list = re.findall(ex, page_text, re.S) # re.S单行匹配 img_src_lists = [] # 拼接所有图片的请求地址 for src in img_src_list: src = "https:" + src img_src_lists.append(src) return img_src_lists # 2、依据糗图是下载地址,保存图片数据 def saveImage(img_src_lists, header, page_no): if not os.path.exists(f'./qiutu/{page_no}'): os.makedirs(f'./qiutu/{page_no}') # 创建多级目录 # 遍历图片地址,进行保存 for src in img_src_lists: session = requests.session() session.keep_alive = False # 关闭多余连接 response = session.get(url=src, headers=header) # 获取图片二进制数据 img_data = response.content file_name = src.rsplit(sep='/', maxsplit=1)[1] with open(f'./qiutu/{page_no}/{file_name}', 'wb') as fp: fp.write(img_data) if __name__ == '__main__': header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36' } requests.adapters.DEFAULT_RETRIES = 5 # 增加重连次数 # 1、先爬取糗事百科中糗图板块的页面数据,获取所有糗图的src page_count = 13 for page_no in range(1, page_count+1): page_get_url = 'https://www.qiushibaike.com/imgrank/page/{0}/'.format(page_no) img_src_lists = getImageSrc(page_get_url, header) # 2、依据糗图是下载地址,保存图片数据 saveImage(img_src_lists, header, page_no) print(f"------爬取第{page_no}页图片结束----------") print('爬取糗图结束')

输出结果:爬取了13页的糗图图片(按照页面目录存放)

 

 

最新回复(0)