首页 >> 大全

学习Ajax异步加载:爬今日头条

2024-01-08 大全 25 作者:考证青年

【项目介绍】

现在很多网址都是异步加载的,一般我们浏览一个页面返回的是网页的框架,而内容是用渲染的,一般是我们一边拖动内容网页会一边发出异步加载的请求并响应部分内容,这样子我们打开网页时响应速度会快很多,也能减小服务器的压力,使服务器支持更多的并发。但是也因为异步加载的关系,用以往直接请求网页内容的方式是找不到要爬的内容的,这个项目尝试分析今日头条的异步加载方式,爬取头条上的图片。

【项目工具】

+(主要用于获取)+

【项目流程】

1.分析今日头条加载方式:搜索街拍对应页面的url发现的是网页的框架,没有返回街拍内容。

切换到XHR,可以看到选中内容返回json数据,里面有街拍的详细内容,并且往下滑动街拍内容,可以看到XHR里有多个相似URL加载出来,对比他们的URL发现主要是不同,一般指偏移量。

如图,可以判断该URL的param比较好构造,除了其他都是固定的,另外是时间戳,可以不加。

2.发现如果直接爬对应URL,获取到的json数据里data为空,通过网上查找发现需要附带,另外可以发现直接跳转“=街拍”的URL会跳出验证,而从今日头条首页搜索“=街拍”再搜索访问页面就不会出现验证,故判断先找到请求头的才能实现后续访问。

!注意是请求头的,可以用去(),也可以直接打开网页复制,之前好几次用了另外获取的方法,得到的都是响应头的,这里存在困惑。

3.找图片。我们发现今日头条街拍的文章分为两种,一种是点击进去图片已经排列好,另一种是类似相册的方式,需要左右点击跳转下一站图片,这两种对应的图片爬取方式是不一样的。

具体分析两种:

这种是图片集的(需要左右点击切换照片),这种如果在json的里是得不到全部图片的,需要访问该文章的链接,在链接里的html里找。

另一种则可以直接在里找:

_今日头条爬虫框架_python今日头条爬虫

4.爬取图片

5.存放图片

附完整代码:

import requests,re,os
from hashlib import md5
from selenium import webdriverdef get_cookies(url):str=''options = webdriver.ChromeOptions()options.add_argument('--headless')browser = webdriver.Chrome(options=options)browser.get(url)for i in browser.get_cookies():try:name=i.get('name')value=i.get('value')str=str+name+'='+value+';'except ValueError as e:print(e)return strdef get_page(offset):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',}url='https://www.toutiao.com/api/search/content/'try:r=requests.get(url,params=params,headers=headers)if r.status_code==200:print(r.content)return r.json()else:print('requests get_page error!')except requests.ConnectionError:return Nonedef get_images(json):remove_chars = '[’!"#$%&\'()*+,-./:;<=>?@,。?★、…【】《》?“”‘’![\\]^_`{|}~]+'data=json.get('data')if data:for i in data:if i.get('title'):title=re.sub('[\t]','',i.get('title'))title = re.sub(remove_chars, '', title)  # 生成目录会有一些限制,比如有英文问号会出错,因此删减一些特殊符号防止出错url=i.get('article_url')if url:r=requests.get(url,headers=headers)#if r.status_code==200:images_pattern = re.compile('JSON.parse\("(.*?)"\),\n', re.S)result = re.search(images_pattern, r.text)if result:b_url='http://p3.pstatp.com/origin/pgc-image/'up=re.compile('url(.*?)"width',re.S)results=re.findall(up,result.group(1))if results:for result in results:yield {'title':title,'image':b_url+re.search('F([^F]*)\\\\",',result).group(1)#^匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合}#yield类似return的作用,不过return一般是返回后停止执行,这个类似迭代器,会继续执行。else:images = i.get('image_list')for image in images:origin_image = re.sub("list.*?pgc-image", "large/pgc-image",image.get('url'))  # 改成origin/pgc-image是原图yield {'image': origin_image,'title': title}def save_image(item):img_path = 'image' + os.path.sep + item.get('title')if not os.path.exists(img_path):os.makedirs(img_path) # 生成目录文件夹'''建立保存图片的目录如果目录不存在,则建立文件目录。使用os.makedirs(file_path)建立目录,而不是使用os.mkdir(file_path)。因为mkdir只能建立单级文件目录。makedirs则能建立多级文件目录,也能建立单级文件目录。单级文件目录:img多级文件目录:my/book/img'''try:'''获得图片名(包含路径)从图片url中取得图片后缀——jgp,png之类的os.path.splitext(path)将文件路径(包含文件名)拆分为:[路径\文件名, 文件后缀]拼接图片名(包含路径)filename = 目录路径 +文件分隔符+ 图片名+图片后缀使用os.sep获得系统文件分隔符,避免不同平台造成不同的文件分隔符。'''resp = requests.get(item.get('image'))if requests.codes.ok == resp.status_code:file_path = img_path + os.path.sep + '{file_name}.{file_suffix}'.format(file_name=md5(resp.content).hexdigest(),#通过哈希函数对每个文件进行文件名的自动生成:MD5加密后进行十六进制转换。file_suffix='jpg')  # 单一文件的路径if not os.path.exists(file_path):with open(file_path, 'wb') as f:f.write(resp.content)print('Downloaded image path is %s' % file_path)else:print('Already Downloaded', file_path)except Exception as e:print(e,'none123')def main(offset):a = get_page(offset)for i in get_images(a):save_image(i)cookies = get_cookies('https://www.toutiao.com')
headers = {'cookie': cookies,'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36','x-requested-with': 'XMLHttpRequest','referer': 'https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D',
}if __name__=='__main__':#p.map(main,[0]) #之所以不用Pool多进程是因为目前还没有办法实现跨进程共享Cookies#map(main,[x*20 for x in range(3)]) map没有输出,不知道为什么for i in [x*20 for x in range(3)]:main(i)

【参考材料】

图片的存放:

yield的解释:

程序参考:

生成目录去除违规符号:

【总结与反思】

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了