说真的,花了几天的时间来搞一个别人已经干过的项目,不知道是否是不值得,可是后面我本身上手作了以后,我才发现,这必须值得,崔大的书是2018年的,而如今网络的更新速度太快了,书本上的接口知识点都变了,废了老多时间才弄懂这些,不过我以为也值,因此把代码增强了一下,实现了个人功能,下面作个简单的分享。
python
都2020年了还没爬过今日头条,你作爬虫是否是显得OUT了?可是没事,虽然如今的接口都变化了,那我就讲下2020年怎么搞今日头条妹子写真,这是一个改进的项目,里面参加了我本身的不少想法,好比有些很难懂的,我本身用简单的方式去实现了它,我的感受仍是实现的不错的,各位看官能够看看。web
这个妹子以为好看的评论区扣好看,直接教你怎么搞到手!ajax
利用简单的进程池
和Ajax数据爬取技术
对今日头条关键词页面进行分析
和处理
,而后获取每一个页面的连接
,从而得到全部图片的连接
,而后打包下载
,
整个步骤我都会用小模块代码将其展现,实现不了的过来砍我
! 就是这么的负责我跟大家说。json
这里对进程的了解我也不是不少,简单的说下项目须要的函数:api
from multiprocessing import Pool # 调用函数库 p = Pool(4) # 构造一个进程池,单位为4 p.close() # 关闭进程 p.join() # 开启进程
对Pool对象调用join()方法会等待全部子进程执行完毕,调用join()以前必须先调用close(),调用close()以后就不能继续添加新的Process了。
浏览器
更多进程的知识点,还请各位大佬移步:廖老师的课堂服务器
网址的不少信息都不会直接所有出如今源代码里面,好比你刷网页,那些新刷出的网页就是一个个的经过ajax接口加载出来的,这是一种异步加载方式
,原始的页面不会包含不少数据,数据都放在一个个接口里面,只有咱们请求这个ajax接口,而后服务器后台收到这个接口信息,才会把数据返回,而后JavaScript分析这个数据,在渲染到浏览器页面上,这就是咱们看到的模式,
如今愈来愈多的网页都是采用这个异步加载的方式,爬虫就现得没那么容易了,这个概念的讲的也拗口,咱们直接开始实战吧!cookie
目标网址: 今日头条关键词妹子网络
怎么知道他是否是ajax接口,主要有三点:session
注意我这几个箭头,只要你在这里·查找·里面找不到与文章对应的文字仍是连接什么的,那就多是。
在这个XHR里面找到箭头的网址,点击,查看预览,这个时候你随意打开里面的东西,就能发现不少与文章相同的点
仍是这张图,你能够看到X-requested里面的接口是XMLHttpRequets
若是三点同时知足,那他就是Ajax接口,而后异步加载出来的数据。
在第二点的那张图咱们能够看到有0,1,2,3,4,之类的,打开你会发现,都在这里面,图中我用箭头标红了,有标题和页面连接,只要得到这个页面连接,那么就很简单了。
首先请求最开始的页面: https://www.toutiao.com/search/?keyword=%E7%BE%8E%E5%A5%B3
可是咱们不能这样直接把页面交给requests库直接干,由于这是一个ajax接口,若是不加入参数,极可能让你输入什么验证码仍是拉动验证条什么,反正就是很麻烦,那咱们就加入参数,具体措施以下:
def get_page(offset): # offset偏移,由于每一个ajax都是加载固定的页面数 # 这里是20,在第三点图上能够看获得 global headers # 全局变量 我后面还要用 headers = { 'cookie': 'tt_webid=6821518909792273933; WEATHER_CITY=%E5%8C%97%E4%BA%AC; SLARDAR_WEB_ID=b4a776dd-f454-43c6-81cd-bd37cb5fd0ec; tt_webid=6821518909792273933; csrftoken=4a2a6afcc9de4484af87a2ff8cba0638; ttcid=8732e6def0484fae975c136222a44f4932; s_v_web_id=verify_k9o5qf2w_T0dyn2r8_X6CE_4egN_9OwH_CCxYltDKYSQj; __tasessionId=oxyt6axwv1588341559186; tt_scid=VF6tWUudJvebIzhQ.fYRgRk.JHpeP88S02weA943O6b6-7o36CstImgKj1M3tT3mab1b', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Edg/81.0.416.68', 'referer': 'https://www.toutiao.com/search/?keyword=%E7%BE%8E%E5%A5%B3', 'x-requested-with': 'XMLHttpRequest' } # 头信息 加入参数 params = { 'aid': ' 24', 'app_name': ' web_search', 'offset': offset, 'format': ' json', 'keyword': ' 美女', 'autoload': ' true', 'count': ' 20', 'en_qc': ' 1', 'cur_tab': ' 1', 'from': ' search_tab', 'pd': ' synthesis', 'timestamp': int(time.time()) } url = 'https://www.toutiao.com/api/search/content/?' + urlencode(params) # 构造url, 使用到了urlencode() 函数 url = url.replace('=+', '=') # 这里必须注意如今的网址根本不同 # print(url) try: r = requests.get(url, headers=headers, params=params) r.content.decode('utf-8') if r.status_code == 200: return r.json() # 返回json格式 由于全是字典类型 except requests.ConnectionError as e: print(e)
这里必须注意一点,请求的网址已经改掉了,我在代码里面给了解释,仔细看看。
def get_image(json): # 获取图片 if json.get('data'): # 若是这个存在 for item in json.get('data'): if item.get('title') is None: continue # 若是标题是空值 title = item.get('title') # 获取标题 if item.get('article_url') == None: continue url_page = item.get('article_url') # print(url_page) rr = requests.get(url_page, headers=headers) if rr.status_code == 200: pat = '<script>var BASE_DATA = .*?articleInfo:.*?content:(.*?)groupId.*?;</script>' # 用正则大体匹配一下范围 match = re.search(pat, rr.text, re.S) if match != None: result = re.findall(r'img src=\\"(.*?)\\"', match.group(), re.S) # print(i.encode('utf-8').decode('unicode_escape') # 转换编码方式 把\u之类的改掉 yield { 'title': title, 'image': result }
这里获取的网页连接都是Unicode格式的,在后面的下载部分,我给了修改方案,这也是一个暗坑。
def save_image(content): path = 'D://今日头条美女//' # 目录 if not os.path.exists(path): # 建立目录 os.mkdir(path) os.chdir(path) else: os.chdir(path) # ------------------------------------------ if not os.path.exists(content['title']): # 建立单个文件夹 if '\t' in content['title']: # 以title为标题建立单个文件夹 title = content['title'].replace('\t', '') # 去除特殊符号 否则建立不了文件名称 os.mkdir(title + '//') os.chdir(title + '//') print(title) else: title = content['title'] os.mkdir(title + '//') # 建立文件夹 os.chdir(title + '//') print(title) else: # 若是存在 if '\t' in content['title']: # 以title为标题建立单个文件夹 title = content['title'].replace('\t', '') # 去除特殊符号 否则建立不了文件名称 os.chdir(title + '//') print(title) else: title = content['title'] os.chdir(title + '//') print(title) for q, u in enumerate(content['image']): # 遍历图片地址列表 u = u.encode('utf-8').decode('unicode_escape') # 先编码在解码 得到须要的网址连接 # 开始下载 r = requests.get(u, headers=headers) if r.status_code == 200: # file_path = r'{0}/{1}.{2}'.format('美女', q, 'jpg') # 文件的名字和地址,用三目运算符来调试文件夹的名字 # hexdisgest() 返回十六进制图片 with open(str(q) + '.jpg', 'wb') as fw: fw.write(r.content) print(f'该系列----->下载{q}张')
在U变量的时候进行了编码在解码操做,而后网址就正常不少了。
# -*- coding '':'' utf-8 -*-'' # @Time '':'' 2020/5/1 9:34'' # @author '':'' 沙漏在下雨'' # @Software '':'' PyCharm'' # @CSDN '':'' https://me.csdn.net/qq_45906219'' import requests from urllib.parse import urlencode # 构造url import time import os from hashlib import md5 from lxml import etree from bs4 import BeautifulSoup import re from multiprocessing.pool import Pool def get_page(offset): global headers headers = { 'cookie': 'tt_webid=6821518909792273933; WEATHER_CITY=%E5%8C%97%E4%BA%AC; SLARDAR_WEB_ID=b4a776dd-f454-43c6-81cd-bd37cb5fd0ec; tt_webid=6821518909792273933; csrftoken=4a2a6afcc9de4484af87a2ff8cba0638; ttcid=8732e6def0484fae975c136222a44f4932; s_v_web_id=verify_k9o5qf2w_T0dyn2r8_X6CE_4egN_9OwH_CCxYltDKYSQj; __tasessionId=oxyt6axwv1588341559186; tt_scid=VF6tWUudJvebIzhQ.fYRgRk.JHpeP88S02weA943O6b6-7o36CstImgKj1M3tT3mab1b', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Edg/81.0.416.68', 'referer': 'https://www.toutiao.com/search/?keyword=%E7%BE%8E%E5%A5%B3', 'x-requested-with': 'XMLHttpRequest' } # 头信息 加入参数 params = { 'aid': ' 24', 'app_name': ' web_search', 'offset': offset, 'format': ' json', 'keyword': ' 美女', 'autoload': ' true', 'count': ' 20', 'en_qc': ' 1', 'cur_tab': ' 1', 'from': ' search_tab', 'pd': ' synthesis', 'timestamp': int(time.time()) } url = 'https://www.toutiao.com/api/search/content/?' + urlencode(params) # 构造url url = url.replace('=+', '=') # 网址根本不同 # print(url) try: r = requests.get(url, headers=headers, params=params) r.content.decode('utf-8') if r.status_code == 200: return r.json() # 返回json格式 由于全是字典类型 except requests.ConnectionError as e: print(e) def get_image(json): # 获取图片 if json.get('data'): # 若是这个存在 for item in json.get('data'): if item.get('title') is None: continue # 若是标题是空值 title = item.get('title') # 获取标题 # if item.get('image_list') is None: # 进行判空 # continue # urls = item.get('image_list') # 得到图片网址 # for url in urls: # 遍历这个urls # url = url.get('url') # # 使用正则拼接网址 # url = 'http://p1.pstatp.com/origin/' + 'pgc-image/' + url.split('/')[-1] if item.get('article_url') == None: continue url_page = item.get('article_url') # print(url_page) rr = requests.get(url_page, headers=headers) if rr.status_code == 200: pat = '<script>var BASE_DATA = .*?articleInfo:.*?content:(.*?)groupId.*?;</script>' match = re.search(pat, rr.text, re.S) if match != None: result = re.findall(r'img src=\\"(.*?)\\"', match.group(), re.S) # for i in result: # print(i.encode('utf-8').decode('unicode_escape') # 转换编码方式 把\u之类的改掉 yield { 'title': title, 'image': result } # 格式出错,这里产生了十六进制的数值, 网址获取不了,明天看 # yield { # 'title': title, # 'image': url # } # 返回标题和网址 def save_image(content): path = 'D://今日头条美女//' # 目录 if not os.path.exists(path): # 建立目录 os.mkdir(path) os.chdir(path) else: os.chdir(path) # ------------------------------------------ if not os.path.exists(content['title']): # 建立单个文件夹 if '\t' in content['title']: # 以title为标题建立单个文件夹 title = content['title'].replace('\t', '') # 去除特殊符号 否则建立不了文件名称 os.mkdir(title + '//') os.chdir(title + '//') print(title) else: title = content['title'] os.mkdir(title + '//') # 建立文件夹 os.chdir(title + '//') print(title) else: # 若是存在 if '\t' in content['title']: # 以title为标题建立单个文件夹 title = content['title'].replace('\t', '') # 去除特殊符号 否则建立不了文件名称 os.chdir(title + '//') print(title) else: title = content['title'] os.chdir(title + '//') print(title) for q, u in enumerate(content['image']): # 遍历图片地址列表 u = u.encode('utf-8').decode('unicode_escape') # 先编码在解码 得到须要的网址连接 # 开始下载 r = requests.get(u, headers=headers) if r.status_code == 200: # file_path = r'{0}/{1}.{2}'.format('美女', q, 'jpg') # 文件的名字和地址,用三目运算符来调试文件夹的名字 # hexdisgest() 返回十六进制图片 with open(str(q) + '.jpg', 'wb') as fw: fw.write(r.content) print(f'该系列----->下载{q}张') def main(offset): json = get_page(offset) get_image(json) for content in get_image(json): try: # print(content) save_image(content) except FileExistsError and OSError: print('建立文件格式错误,包含特殊字符串:') continue if __name__ == '__main__': pool = Pool() groups = [j * 20 for j in range(8)] pool.map(main, groups) # 传offset偏移量 pool.close() pool.join()
这是我第一个爬虫项目,以前都是很简单的,这一次有点麻烦,总之,对于困难咱们仍是别怕,不会就百度,一直百度必定出结果!
2020年,没啥作了,只剩加油了。