声明:此篇文章主要是观看静觅教学视频后做的笔记,原教程地址https://cuiqingcai.com/

实现流程介绍

1.抓取索引页内容:利用requests请求目标站点,得到索引网页HTML代码,返回结果

2.抓取详情页内容:解析返回结果,得到详情页的链接,并进一步抓取详情页信息

3.下载图片与保存数据库:将图片下载到本地,并把页面信息及图片URL保存至MongoDB

4.开启循环及多线程:对多页内容遍历,开启多线程提高抓取速度

具体实现

1. 首先访问今日头条网站输入关键字来到索引页,我们需要通过分析网站来拿到进入详细页的url

经过观察可以发现每次滑动鼠标滚轮,新的标题链接就会被显示,所以可以发现其后台为Ajax请求,通过浏览器Network选项卡的XHR可以找到Ajax的链接,其为一个json数据,以搜索词街拍为例,其链接地址如下:

https://www.toutiao.com/search_content/?offset=0&format=json&keyword=%E8%A1%97%E6%8B%8D&autoload=true&count=20&cur_tab=1&from=search_tab
2.通过点击查看Query String Parameters中的内容,可以看到一些类似字典的数据,所以这是一会需要通过urlencode来转码拼接成最终访问的地址

offset: 0
format: json
keyword: 街拍
autoload: true
count: 20
cur_tab: 1
from: search_tab

3.随着向下滑动滚动条显示更多的图片索引,会发现刷出了很多新的ajax请求,通过这个我们可以知道我们之后可以通过改变offset参数来获取不同的拿到不同的索引界面,从而获得不同的图集详细页url。开始只需实现一个offset参数的爬取,最后通过进程池Pool来创建实现多进程爬取不同offset参数的URL,加快爬取速度

4.接下来就是分析查找图集详细页的代码,来找到图片的url,这个图片url隐藏的比较深,都在JS代码中,所以不能使用BeautifulSoup和PyQuery来解析了,只能通过正则解析,使用正则解析要注意匹配规则一定要写对。刷新页面后,自己基础比较差,找了好久换了火狐浏览器,又换回谷歌,最后在Network选项卡的Doc发现下面这个链接,而图片地址就藏在gallery: JSON.parse里

https://www.toutiao.com/a6585311263927042573/
5.代码实现

代码直接进行展示吧,需要的注释我已经写在代码里了,先编辑一个config.py的文件,里面设置了代码中用到的变量

MONGO_URL = 'localhost'
MONGO_DB = 'toutiao'
MONGO_TABLE = 'toutiao'GROUP_START = 1
GROUP_END = 20
KEYWORD='街拍'
#!/usr/bin/env python
# coding=utf-8from urllib.parse import urlencode
from requests.exceptions import ConnectionError
from bs4 import BeautifulSoup
from json.decoder import JSONDecodeError
from hashlib import md5
from config import *
from multiprocessing import Pool
import requests
import json
import re
import os
import pymongoclient = pymongo.MongoClient(MONGO_URL, connect=False)
db = client[MONGO_DB]def get_page_index(url, headers):"""作用:返回页面源码url:请求地址headers:请求头信息"""try:response = requests.get(url, headers=headers)# 判断是否访问成功if response.status_code == 200:return response.textexcept ConnectionError:print('Erroe occured')return Nonedef parse_page_index(html):"""作用:解析出标题URL地址html:网页源码"""try:# 将数据转为json格式data = json.loads(html)# print(data)# 判断data是否为空,以及data字典中是否有data这个键if data and 'data' in data.keys():for item in data.get('data'):if item.get('article_url'):yield item.get('article_url')except JSONDecodeError:passdef get_page_detail(url, headers):"""作用:返回标题URL网页源码url:标题URL地址headers:请求头信息"""try:response = requests.get(url, headers=headers)# 判断是否访问成功if response.status_code == 200:return response.textexcept ConnectionError:print('Error occured')return Nonedef parse_page_detail(html, url):"""作用:解析标题URL地址的每个图片链接html:标题URL网页源码url:标题URL地址"""# 利用BeautifulSoup找到title的文本soup = BeautifulSoup(html, 'lxml') title = soup.title.text# 利用正则找到每个下载图片的地址images_pattern = re.compile('gallery: JSON.parse\("(.*)"\)', re.S)result = images_pattern.search(html)# print(result)if result:data = json.loads(result.group(1).replace('\\', ''))# 提取出sub_images键的键值if data and 'sub_images' in data.keys():sub_images = data.get('sub_images')# 使用列表生成式拿到每个图片URLimages = [item.get('url') for item in sub_images]for image in images: # 下载图片download_image(image)# 将return的结果保存至MongoDB中return {'title': title,'url': url,'images': images}def download_image(url):"""作用:返回图片URL源码url:图片URL地址"""print('Downloading', url)try:response = requests.get(url)# 判断是否访问成功if response.status_code == 200:save_image(response.content)return Noneexcept ConnectionError:return Nonedef save_image(content):"""作用:保存图像文件content:图像二进制数据"""# 使用md5加密内容,生成图像名称file_path = '{0}/{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg')print(file_path)# 判断该文件名是否存在if not os.path.exists(file_path):with open(file_path, 'wb') as f:f.write(content)f.close()def save_to_mongo(result):"""作用:保存数据至MongoDB数据库result:包括图片标题,请求地址,图像地址"""if db[MONGO_TABLE].insert(result):print('Successfully Saved to Mongo', result)return Truereturn Falsedef jiepai_Spider(offset):"""作用:整个爬虫调度器offset:位置参数"""headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'}data = {"offset": offset,"format": "json","keyword": "街拍","autoload": "true","count": "20","cur_tab": "1","from": "search_tab"}# 通过urlencode构造请求URLurl = 'https://www.toutiao.com/search_content/' + '?' + urlencode(data)# 测试url# print(url)# 获取页面源码html = get_page_index(url, headers)# 解析HTML,获得链接地址for url in parse_page_index(html):# print(url)# 获得每个链接地址的HTMLhtml = get_page_detail(url, headers)result = parse_page_detail(html, url)# 判断result是否为空,保存至MongoDB数据库中if result: save_to_mongo(result)if __name__ == "__main__":# 创建进程池pool = Pool()groups = ([x * 20 for x in range(GROUP_START, GROUP_END + 1)])pool.map(jiepai_Spider, groups)pool.close()# 等待pool中所有子进程执行完成,必须放在close语句之后pool.join()

总结思考

1.在利用正则进行匹配的时候如果原文有‘(“ ”)',这类符号时那么你在进行正则表达式书写的时候应该在前面加'\'。按理应该也可以使用原始字符串r,可是我用完最后在匹配的时候返回的是None,留个疑问

pattern = re.compile('gallery: JSON\.parse\("(.*?)"\),', re.S)

2. db = client[MONGO_DB]这里应该是方括号而不是 ( ),否则无法正常访问数据库

3. 在Google浏览器中找不到图片url,然后使用的是火狐浏览器来回查看

4.完整源码地址:https://github.com/XiaoFei-97/toutiao_Spider-Ajax

分析Ajax抓取今日头条街拍美图相关推荐

  1. [Python3网络爬虫开发实战] --分析Ajax爬取今日头条街拍美图

    [Python3网络爬虫开发实战] --分析Ajax爬取今日头条街拍美图 学习笔记--爬取今日头条街拍美图 准备工作 抓取分析 实战演练 学习笔记–爬取今日头条街拍美图 尝试通过分析Ajax请求来抓取 ...

  2. python爬取今日头条_Python3网络爬虫实战-36、分析Ajax爬取今日头条街拍美图

    本节我们以今日头条为例来尝试通过分析 Ajax 请求来抓取网页数据的方法,我们这次要抓取的目标是今日头条的街拍美图,抓取完成之后将每组图片分文件夹下载到本地保存下来. 1. 准备工作 在本节开始之前请 ...

  3. Python3网络爬虫开发实战分析Ajax爬取今日头条街拍美图

    本节中,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法.这次要抓取的目标是今日头条的街拍美图,抓取完成之后,将每组图片分文件夹下载到本地并保存下来. 1. 准备工作 很多人学习pyt ...

  4. php抓取今日头条,分析Ajax来抓取今日头条街拍美图

    一.介绍 还是根据崔大大的视频来码的文章,不得不说,抓取文件并下载下来比抓取网页内容信息复杂多了 二.流程 目标站点分析 用浏览器打开今日头条输入'街拍',打开审查元素,点击'图集' 1.首先我们要找 ...

  5. 转:【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图

    [摘要] 本节中,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法.这次要抓取的目标是今日头条的街拍美图,抓取完成之后,将每组图片分文件夹下载到本地并保存下来. 1. 准备工作 在本节 ...

  6. 【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图

    [摘要] 本节中,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法.这次要抓取的目标是今日头条的街拍美图,抓取完成之后,将每组图片分文件夹下载到本地并保存下来. 1. 准备工作 在本节 ...

  7. python爬虫今日头条街拍美图开发背景_【Python3网络爬虫开发实战】6.4-分析Ajax爬取今日头条街拍美图...

    [摘要] 本节中,我们以今日头条为例来尝试通过分析Ajax请求来抓取网页数据的方法.这次要抓取的目标是今日头条的街拍美图,抓取完成之后,将每组图片分文件夹下载到本地并保存下来. 1. 准备工作 在本节 ...

  8. 2.分析Ajax请求并抓取今日头条街拍美图

    import requests from urllib.parse import urlencode # 引入异常类 from requests.exceptions import RequestEx ...

  9. 分析Ajax请求并抓取今日头条街拍美图

    1.抓取索引页内容 利用requests请求目标站点,得到索引网页HTML代码,返回结果 2.抓取详情页内容 解析返回结果,得到详情的链接,并进一步抓取详情页的信息 3.下载图片与保存数据库 将图片下 ...

最新文章

  1. yolov5 代码版,去掉配置文件
  2. Back button implementation in Text reuse component GSTEXT
  3. thunderbird html签名,Thunderbird中配置签名
  4. linux-buff/cache过大导致内存不足-程序异常
  5. 第一个Netty应用
  6. 游戏筑基开发之二进制文件操作的那点事儿(C语言)
  7. Python语言实现用于动物分类的产生式系统
  8. 模拟实现strlen
  9. php三D立体模拟,CSS3使用3D环境实现立体魔方效果的实例代码分享
  10. 由国内媒体的“非典”报道看信息生态问题-引文
  11. SpringBoot 前后端分离 实现验证码操作
  12. 寻求路径问题————动态规划的思想
  13. 2021-05-22 黑板异或游戏
  14. model.evaluate 和 model.predict
  15. 在微型计算机中硬件和软件的关系是_,计算机的硬件系统和软件系统的关系是什么?...
  16. RPGMAKER游戏引擎基于JavaScript的插件制作(二)——如何理解插件,以及编写代码时的注意事项
  17. 词云python_词-经典诗词宋词语大全
  18. 【Antv/Vue3】vue项目中使用antv/L7制作地图
  19. Java设计模式面试题总结
  20. 微信视频上传服务器失败,用SDK接口方法UploadForeverVideo上传视频文件报40113(unsupported file type)错误...

热门文章

  1. iOS:CALayer核心动画层
  2. 设计模式入门之原型模式Prototype
  3. 论工程结构设计的重要性
  4. java使用HttpClient传输json格式的参数
  5. Listview的点击效果
  6. leetcode位运算的题
  7. uboot、kernel和rootfs烧录
  8. 机器学习中qa测试_机器学习自动化单元测试平台
  9. 安全函数不安全-多线程慎用List.h
  10. CPU 是如何理解 01 二进制的?