今天我们说说动态页面的抓取,动态页面的概念不是说网页上的内容是活动的,而是刷新的内容由Ajax加载,页面的URL没有变化,具体概念问度娘。

就以男人都喜欢的美女街拍为例,对象为今日头条。

chrome打开今日头条 ->搜索

开发者工具->network选项卡

图2-1

很多条目,各种请求,但Ajax其实有其特殊的请求类型,它叫作xhr。在图6-3中,我们可以发现一个名称以getIndex开头的请求,其Type为xhr,这就是一个Ajax请求。用鼠标点击这个请求,可以查看这个请求的详细信息。

图2-2

选中这个xhr请求后,我们可以看到Request Headers中X-Requested-With:XMLHttpRequest,这就标记了此请求是Ajax请求。

点击一下Preview,即可看到响应的内容,它是JSON格式的。这里Chrome为我们自动做了解析,点击箭头即可展开和收起相应内容,初步分析这里返回的是页面上显示出来的前二十条信息。

图2-3

切换回第一个请求,我们发现Response中的信息是这样的

图2-4

这就是原始链接 https://www.toutiao.com/search/?keyword=街拍 所返回的内容,只有六十多行代码,执行了一些JavaScript,所以我们最终看到的页面不是由初始页面返回的,而是后来执行的JavaScript向服务器发送了Ajax请求,收到返回的真实数据后才显示出来的。这就是动态页面渲染的流程。

明白了整个流程后,我们要做的最重要的事就是分析返回数据的内容,用python模拟Ajax请求,拿到我们所希望抓取的数据。

def get_page(offset):

params = {

'offset': offset,

'format': 'json',

'keyword': '街拍',

'autoload': 'true',

'count': '20',

'cur_tab': '1',

'from': 'search_tab',

}

url = 'https://www.toutiao.com/search_content/?'

try:

response = requests.get(url, params=params)

if response.status_code == 200:

return response.json()

except requests.ConnectionError:

return None

下滑几次后,发现只有offset参数变化,所以,构造url,requests获得数据

这里拿到的数据是json格式的

def download_image(jsonData):

if jsonData.get('data'):

for item in jsonData.get('data'):

if item and 'article_url' in item.keys():

title = item.get('title')

article_url = item.get('article_url')

result = get_real_image_path(article_url)

if result: save_to_mongo(result)

'''

另外一种数据格式cell,cell type太多,主要分析上面一种

else:

#original_page_url

data = item.get('display')

#print(display)

#data = json.loads(display)

#print(data)

if data and 'results' in data.keys():

results = data.get('results')

original_page_urls = [item.get('original_page_url') for item in results]

# .get('results').get('original_page_url')

#title = item.get('display').get('title')

#print(title)

#print(original_page_urls)'''

取出数据中的data段,发现只有前四张图片的地址可以取到,剩下的图片必须进入文章页才能获得,我们取出文章页的url,requests获得文章页数据

def get_real_image_path(article_url):

headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}

response = requests.get(article_url, headers=headers)

soup = BeautifulSoup(response.text, "lxml")

title = soup.select('title')[0].get_text()

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

result = re.search(image_pattern, response.text)

if result:

result = result.group(1).replace('\\', '')

data = json.loads(result)

if data and 'sub_images' in data.keys():

sub_images = data.get('sub_images')

images_urls = [item.get('url') for item in sub_images]

for image_url in images_urls: download_real_image(image_url)

return {

'title': title,

'url' : article_url,

'image_urls': images_urls

}

这里需要加入UA头,否则返回不了数据,拿到数据后,发现图片地址位于

图2-5

这里用正则表达式

gallery: JSON.parse\("(.*?)"\),

匹配符合条件的,gallery: JSON.parse("")中的数据\(\)这里在正则中表达的是转义字符,有兴趣的可以学习一下正则表达式,这里就不赘述了

我们从sub_images中拿到了所有图片地址,下载过程就很简单了

requests图片地址,获得的response中的content就是图片的数据

def download_real_image(url):

print('downloading---', url)

try:

response = requests.get(url)

if response.status_code == 200:

save_image(response.content)

return None

except RequestException:

print('request image fail---', url)

return None

def save_image(content):

files_path = '{0}/{1}'.format(os.getcwd(), 'tupian')

if not os.path.exists(files_path):

os.mkdir(files_path)

file_path = '{0}/{1}.{2}'.format(files_path, md5(content).hexdigest(), 'jpg')

if not os.path.exists(file_path):

with open(file_path, 'wb') as f:

f.write(content)

我们还可以把图片的标题和地址写入数据库

def save_to_mongo(result):

if db[MONGO_TABLE].insert(result):

print('save success', result)

return True

return False

完整代码:jjrt.py

import requests

import re

import json

from hashlib import md5

import os

from bs4 import BeautifulSoup

import pymongo

from config import *

import time

client = pymongo.MongoClient(MONGO_URL, connect=False)

db = client[MONGO_DB]

def get_page(offset):

params = {

'offset': offset,

'format': 'json',

'keyword': '街拍',

'autoload': 'true',

'count': '20',

'cur_tab': '1',

'from': 'search_tab',

}

url = 'https://www.toutiao.com/search_content/?'

try:

response = requests.get(url, params=params)

if response.status_code == 200:

return response.json()

except requests.ConnectionError:

return None

def save_to_mongo(result):

if db[MONGO_TABLE].insert(result):

print('save success', result)

return True

return False

def download_real_image(url):

print('downloading---', url)

try:

response = requests.get(url)

if response.status_code == 200:

save_image(response.content)

return None

except RequestException:

print('request image fail---', url)

return None

def save_image(content):

files_path = '{0}/{1}'.format(os.getcwd(), 'tupian')

if not os.path.exists(files_path):

os.mkdir(files_path)

file_path = '{0}/{1}.{2}'.format(files_path, md5(content).hexdigest(), 'jpg')

if not os.path.exists(file_path):

with open(file_path, 'wb') as f:

f.write(content)

def get_real_image_path(article_url):

headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}

response = requests.get(article_url, headers=headers)

soup = BeautifulSoup(response.text, "lxml")

title = soup.select('title')[0].get_text()

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

result = re.search(image_pattern, response.text)

if result:

result = result.group(1).replace('\\', '')

data = json.loads(result)

if data and 'sub_images' in data.keys():

sub_images = data.get('sub_images')

images_urls = [item.get('url') for item in sub_images]

for image_url in images_urls: download_real_image(image_url)

return {

'title': title,

'url' : article_url,

'image_urls': images_urls

}

def download_image(jsonData):

if jsonData.get('data'):

for item in jsonData.get('data'):

if item and 'article_url' in item.keys():

title = item.get('title')

article_url = item.get('article_url')

result = get_real_image_path(article_url)

if result: save_to_mongo(result)

'''

另外一种数据格式cell,cell type太多,主要分析上面一种

else:

#original_page_url

data = item.get('display')

#print(display)

#data = json.loads(display)

#print(data)

if data and 'results' in data.keys():

results = data.get('results')

original_page_urls = [item.get('original_page_url') for item in results]

# .get('results').get('original_page_url')

#title = item.get('display').get('title')

#print(title)

#print(original_page_urls)'''

def main():

STARTPAGE = 1

ENDPAGE = 2

for i in range(STARTPAGE, ENDPAGE):

time.sleep(1)

offset = i * 20

jsonData = get_page(offset)

download_image(jsonData)

if __name__ == "__main__":

main()

config.py

MONGO_URL = 'localhost'

MONGO_DB = 'jiepai'

MONGO_TABLE = 'jiepai'

GROUP_START = 0

GROUP_END = 20

KEYWORD = '街拍'

python动态爬取知乎_python爬虫从小白到高手 Day2 动态页面的爬取相关推荐

  1. python爬虫爬取今日头条_Python爬虫实战入门五:获取JS动态内容—爬取今日头条...

    之前我们爬取的网页,多是HTML静态生成的内容,直接从HTML源码中就能找到看到的数据和内容,然而并不是所有的网页都是这样的. 有一些网站的内容由前端的JS动态生成,由于呈现在网页上的内容是由JS生成 ...

  2. python 数据分析 书籍推荐 知乎_Python 爬取知乎 9674 个问答,揭秘最受欢迎的 98 本书!...

    原标题:Python 爬取知乎 9674 个问答,揭秘最受欢迎的 98 本书! 作者 | Yura 责编 | 胡巍巍 高尔基这话有没有道理我不知道, 咱也不敢问, 主要是现在也问不了. 那对我来说,读 ...

  3. python爬取公交车站数据_Python爬虫实例_城市公交网络站点数据的爬取方法

    爬取的站点:http://beijing.8684.cn/ (1)环境配置,直接上代码: # -*- coding: utf-8 -*- import requests ##导入requests fr ...

  4. python爬取cctalk视频_python爬虫urllib使用和进阶 | Python爬虫实战二

    python爬虫urllib使用和进阶 上节课已经介绍了爬虫的基本概念和基础内容,接下来就要开始内容的爬取了. 其实爬虫就是浏览器,只不过它是一个特殊的浏览器.爬取网页就是通过HTTP协议访问相应的网 ...

  5. python爬取数据步骤_Python爬虫爬取数据的步骤

    爬虫: 网络爬虫是捜索引擎抓取系统(Baidu.Google等)的重要组成部分.主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份. 步骤: 第一步:获取网页链接 1.观察需要爬取的多 ...

  6. python爬百度贴吧_Python爬虫实战之爬取百度贴吧帖子

    大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 本篇目标对百度贴吧的任意帖子进行抓取 指定是否只抓取楼主发帖内 ...

  7. python爬取微博内容_Python 爬虫如何机器登录新浪微博并抓取内容?

    最近为了做事件分析写了一些微博的爬虫,两个大V总共爬了超70W的微博数据. 官方提供的api有爬取数量上限2000,想爬取的数据大了就不够用了... 果断撸起袖子自己动手!先简单说一下我的思路: 一. ...

  8. 微博爬取显示全文_Python爬虫---chrome driver爬取微博(教你几十行代码爬取财宝宝微博长文)...

    0.学习路径示意图 各位小伙伴大家好,这次博主分享的是利用虚拟浏览器ChromeDriver去爬取微博大V--财宝宝的微博长文. 1.ChromeDriver简介 WebDriver是一个开源工具,用 ...

  9. python实用脚本 知乎_Python 爬虫模拟登陆知乎

    在之前写过一篇使用python爬虫爬取电影天堂资源的文章,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...

最新文章

  1. 服务器架设笔记——多模块和全局数据
  2. MySQL中truncate误操作后的数据恢复案例
  3. python 添加新元素时如果有重复的不进行添加_清华毕业大佬整理的Python基础22大知识点,自备热水,这货有点干...
  4. 姚文详(Joseph Yiu):《ARM Cortex-M0权威指南》中文版目录
  5. BZOJ 1085 [SCOI2005]骑士精神 【A*启发式搜索】
  6. 收集一些非常实用的Linux命令
  7. CSDN转载别人文章的操作
  8. js页面初始化方法只调用一次_跟我学 “Linux” 小程序 Web 版开发(三):云开发相关数据调用
  9. “SQL对象名无效”的解决过程
  10. arcgis导入坐标点转面_arcgis矢量化建筑数据
  11. (秒杀项目) 4.7 缓存商品与用户
  12. 周期性任务计划: Crontab
  13. unity打包出来的exe带有dll文件
  14. oracle如何做定时任务,oracle实现定时任务
  15. 使用System.setOut()
  16. [java]轻量级隔离化的excel导入导出的导入导出,解放导入导出冗余代码(有github源码)
  17. 【基础知识】多标签分类CrossEntropyLoss 与 二分类BCELoss
  18. MySQL-用户管理
  19. 大连理工大学GlobalProtect使用方法
  20. SSM实现物流管理系统快递

热门文章

  1. SSM整合框架实现发送邮件功能
  2. php取商,PHP获取百度关键词排名
  3. svn中项目管理中ec_Mac中使用svn进行项目管理
  4. 修改固态硬盘的物理序列号_买固态怕踩坑?收下这些软件,轻松鉴别好坏
  5. Linux 实操 —— Linux 系统性能分析
  6. document.createelement如何绑定点击事件_番外篇-EXCEL如何使用宏(VBA)
  7. Apprentissage du français partie 1
  8. 双极结型三极管的结构、特性、参数
  9. 利用DHT22和Arduino测量温湿度并显示在串口和OLED显示屏上
  10. orchard mysql_Orchard Core创建CMS/Blog站点