python 学了有一段时间了, 觉得看书也只是划水, 还是要动手码代码, 感觉对爬数据挺有感觉, 想爬来试试, 于是开始了学习崔庆才的网络爬虫开发实战, 由于信息技术的更新, 崔老师的书中的源代码跑起来感觉会有一些出入, 所以还是要多看时间最近的相关博客,,,,,, 还是在崔老师的基础上再结合博客修改之后的.
在搜索栏搜街拍, 然后右键, 检查, network, 注意, 运用开发者页面的时候点击 network, 如果点 Elements, 看到的不是源代码. 由于页面是 Ajax 过的, 所以我们直接看 XHR
因为头条的页面是向上滚动鼠标就可以继续加载页面, 就会发现每次滚动滚轮, name 这一栏都会有新的刷新内容, 分析 name 栏中每个选项的 Preview 和 Response
我们可以发现在第一项的 Preview 这一栏包含了一组 data 信息, 里面出现了具体的图片名称和其他信息, 所以, 我们可以继续滚动页面, 对比其他的类似选项, 在经过对比后我们可以发现, 每一条 url 的变化仅是 offset 这一项发生了变化, 在崔老师的书中写的比较详细, 具体怎么构建 url, 所以在这里, 直接把代码复制过来
- import requests
- import os
- from hashlib import md5
- from urllib.parse import urlencode
- from multiprocessing.pool import Pool
- def get_data(offset):
- #构造 URL, 发送请求
- params = {
- 'aid': '24',
- 'app_name': 'web_search',
- 'offset': offset,
- 'format': 'json',
- 'autoload': 'true',
- 'count': '20',
- 'en_qc': '1',
- 'cur_tab': '1',
- 'from': 'search_tab',
- }
- base_url = 'https://www.toutiao.com/api/search/content/?keyword=街拍'
- url = base_url + urlencode(params)
然后判断 requests 请求后的结果, 并将其改成成 JSON 格式
try: res = requests.get(url) if res.status_code == 200: return res.JSON() except requests.ConnectionError: return 'sorry.'
接下来就是对请求的结果进行信息提取, 获取图片的名称, 以及图片的下载地址
def get_img(data): if data.get('data'): page_data = data.get('data') for item in page_data: title = item.get('title') imgs = item.get('image_list') for img in imgs: #yield 是一个生成器, 具体的解释可以去博客: https://blog.csdn.net/qq_33472765/article/details/80839417 yield { 'title': title, 'img': img.get('url') }
现在我们需要的就是将图片保存, 建立文件夹, 然后用 title 给文件夹命名
def save(item): img_path = 'img' + '/' + item.get('title') if not os.path.exists(img_path): os.makedirs(img_path) try: res = requests.get(item.get('img')) if res.status_code == 200: file_path = img_path + '/' + '{name}.{suffix}'.format( name=md5(res.content).hexdigest(), suffix='jpg') if not os.path.exists(file_path): with open(file_path, 'wb') as f: f.write(res.content) print('Successful') else: print('Already Download') except requests.ConnectionError: print('Failed to save images')
接下来就是构造一个 offset 数组, 然后进行遍历
def main(offset): data = get_data(offset) for item in get_img(data): print(item) save(item) START = 0 END = 10 if __name__ == "__main__": pool = Pool() offsets = ([n * 20 for n in range(START, END + 1)]) pool.map(main,offsets) pool.close() pool.join()
多进程模块 Pool 的用法可以看看博客 https://www.cnblogs.com/zrmw/p/10272034.html
最后所有的代码:
import requests import os from hashlib import md5 from urllib.parse import urlencode from multiprocessing.pool import Pool def get_data(offset): #构造 URL, 发送请求 params = { 'aid': '24', 'app_name': 'web_search', 'offset': offset, 'format': 'json', 'autoload': 'true', 'count': '20', 'en_qc': '1', 'cur_tab': '1', 'from': 'search_tab', } base_url = 'https://www.toutiao.com/api/search/content/?keyword=街拍' url = base_url + urlencode(params) try: res = requests.get(url) if res.status_code == 200: return res.JSON() except requests.ConnectionError: return 'sorry.' def get_img(data): if data.get('data'): page_data = data.get('data') for item in page_data: title = item.get('title') imgs = item.get('image_list') for img in imgs: yield { 'title': title, 'img': img.get('url') } def save(item): img_path = 'img' + '/' + item.get('title') if not os.path.exists(img_path): os.makedirs(img_path) try: res = requests.get(item.get('img')) if res.status_code == 200: file_path = img_path + '/' + '{name}.{suffix}'.format( name=md5(res.content).hexdigest(), suffix='jpg') if not os.path.exists(file_path): with open(file_path, 'wb') as f: f.write(res.content) print('Successful') else: print('Already Download') except requests.ConnectionError: print('Failed to save images') def main(offset): data = get_data(offset) for item in get_img(data): print(item) save(item) START = 0 END = 10 if __name__ == "__main__": pool = Pool() offsets = ([n * 20 for n in range(START, END + 1)]) pool.map(main,offsets) pool.close() pool.join()
代码主要参考崔老师书中的代码和其他的博客, 大家如果感兴趣, 还是要多看看近一年的博客, 因为现在网络的变化太快了, 如有问题, 欢迎大家一起探讨
来源: http://www.bubuko.com/infodetail-3184401.html