以下内容转载自:https://www.makcyun.top/web_scraping_withpython4.html

文章关于网站使用Ajaxj技术加载页面数据,进行爬取讲的很详细

大致步骤如下:

(1)爬取索引页数据

(2)解析索引页面数据

(3)爬取详情页数据

(4)解析详情页数据

(5)保存图片

澎湃网文章的质量不错,它的”美数课”栏目的信息图做得也很好。图片干货多还能带来ppt和图表制作的技巧。为了更方便浏览所有文章图片,通过分析Ajax爬取栏目至今所有信息图的图片。

摘要: 上一篇文章介绍了单页图片的爬取,但是当爬取多页时,难度会增加。同时,前几篇爬虫文章中的网站有一个明显的特点是:可以通过点击鼠标实现网页的翻页,并且url会发生相应的变化。除了此类网站以外,还有一类非常常见的网站特点是:没有”下一页”这样的按钮,而是”加载更多”或者会不断自动刷新从而呈现出更多的内容,同时网页url也不发生变化。这种类型的网页通常采用的是Ajax技术,要抓取其中的网页内容需要采取一定的技巧。本文以信息图做得非常棒的澎湃”美数课”为例,抓取该栏目至今所有文章的图片。
栏目网址:https://www.thepaper.cn/list_25635


本文知识点:

  • Ajax知识
  • 多页图片爬取

1. Ajax知识

在该主页上尝试不断下拉,会发现网页不断地加载出新的文章内容来,而并不需要通过点击”下一页”来实现,而且网址url也保持不变。也就是说在同一个网页中通过下拉源源不断地刷新出了网页内容。这种形式的网页在今天非常常见,它们普遍是采用了Ajax技术。

Ajax 全称是 Asynchronous JavaScript and XML(异步 JavaScript 和 XML)。
它不是一门编程语言,而是利用 JavaScript 在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。

Ajax更多参考:
https://germey.gitbooks.io/python3webspider/content/6.2-Ajax%E5%88%86%E6%9E%90%E6%96%B9%E6%B3%95.html

采用了Ajax的网页和普通的网页有一定的区别,普通网页的爬虫代码放在这种类型的网页上就行不通了,必须另辟出路。下面我们就来尝试一下如何爬取网易”数读”所有的文章。

主页右键-检查,然后按f5刷新,会弹出很多链接文件。鼠标上拉回到第一个文件:list_25635,在右侧按ctrl+f搜索一下第一篇文章的标题:”娃娃机生意经”,可以看到在html网页中找到了对应的源代码。

接着,我们拖动下拉鼠标,显示出更多文章。然后再次搜索一篇文章的标题:”金砖峰会”,会发现搜不到相应的内容了。是不是感觉很奇怪?

其实,这里就是用了Ajax的技术,和普通网页翻页是刷新整个网页不同,这种类型网页可以再保持url不变的前提下只刷新部分内容。这就为我们进行爬虫带来了麻烦。因为,我们通过解析网页的url:https://www.thepaper.cn/list_25635只能爬取前面部分的内容而后面通过下拉刷新出来的内容是爬取不到的。这显然不完美,那么怎么才能够爬取到后面不断刷新出来的网页内容呢?

2. url分析

我们把右侧的选项卡从ALL切换到Network,然后按再次按f5刷新,可以发现Name列有4个结果。选择第3个链接打开并点击Response,通过滑动可以看到一些文本内容和网页中的文章标题是一一对应的。比如第一个是:娃娃机生意经|有没有好奇过抓娃娃机怎么又重新火起来了?,一直往下拖拽可以看到有很多篇文章。此时,再切换到headers选项卡,复制Request URL后面的链接并打开,会显示一部分文章的标题和图片内容。数一下的话,可以发现一共有20个文章标题,也就是对应着20篇文章。

这个链接其实和上面的list_25635链接的内容是一致的。这样看来,好像发现不了什么东西,不过不要着急。

接下来,回到Name列,尝试滚动下拉鼠标,会发现弹出好几个新的开头为load_index的链接来。选中第一个load_index的链接,点击Response查看一下html源代码,尝试在网页中搜索一下:十年金砖峰这个文章的标题,惊奇地发现,在网页中找到了对于的文章标题。而前面,我们搜索这个词时,是没有搜索到的。

这说明了什么呢?说明十年金砖峰这篇文章的内容不在第一个list_25635链接中,而在这个load_index的链接里。鼠标点击headers,复制Request URL后面的链接并打开,就可以再次看到包括这篇文章在内的新的20篇文章。

是不是发现了点了什么?接着,我们继续下拉,会发现弹出更多的load_index的链接。再搜索一个标题:地图湃|海外港口热,可以发现在网页中也同样找到了文章标题。

回到我们的初衷:下载所有网页的图片内容。那么现在就有解决办法礼:一个个地把出现的这些url网址中图片下载下来就大功告成了。

好,我们先来分析一下这些url,看看有没有相似性,如果有很明显的相似性,那么就可以像普通网页那样,通过构造翻页页数的url,实现for循环就可以批量下载所有网页的图片了。复制前3个链接如下:

https://www.thepaper.cn/load_index.jsp?nodeids=25635&topCids=&pageidx=2&isList=true&lastTime=1533169319712  
https://www.thepaper.cn/load_index.jsp?nodeids=25635&topCids=&pageidx=3&isList=true&lastTime=1528625875167
https://www.thepaper.cn/load_index.jsp?nodeids=25635&topCids=&pageidx=4&isList=true&lastTime=1525499007926

发现pageidx键的值呈现规律的数字递增变化,看起来是个好消息。但同时发现后面的lastTime键的值看起来是随机变化的,这个有没有影响呢? 来测试一下,复制第一个链接,删掉&lastTime=1533169319712这一串字符,会发现网页一样能够正常打开,就说明着一对参数不影响网页内容,那就太好了。我们可以删除掉,这样所有url的区别只剩pageidx的值了,这时就可以构造url来实现for循环了。构造的url形式如下:

https://www.thepaper.cn/load_index.jsp?nodeids=25635&pageidx=2
https://www.thepaper.cn/load_index.jsp?nodeids=25635&pageidx=3
https://www.thepaper.cn/load_index.jsp?nodeids=25635&pageidx=4

同时,尝试把数字2改成1并打开链接看看会有什么变化,发现呈现的内容就是第1页的内容。这样,我们就可以从第一页开始构造url循环了。
https://www.thepaper.cn/load_index.jsp?nodeids=25635&pageidx=1

既然确定了首页,那么也要相应地确定一下尾页。很简单,我们把数字改大然后打开链接看是否有内容即可。比如改为10 ,打开发现有内容显示,很好。接着,再改为30,发现没有内容了。说明该栏目的页数介于这两个数之间,尝试几次后,发现25是最后一个有内容的网页,也意味着能够爬取的页数一共是25页。

确定了首页和尾页后,下面我们就可以开始构造链接,先爬取第一篇文章网页里的图片(这个爬取过程,我们上一篇爬取网易”数读”已经尝试过了),然后爬取这一整页的图片,最后循环25页,爬取所有图片,下面开始吧。

3. 程序代码

import os
import re
from multiprocessing import Pool
from urllib.parse import urlencode import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'
} # 1 获取索引界面网页内容
def get_page_index(i):
# 下载1页
# url = 'https://www.thepaper.cn/newsDetail_forward_2370041' # 2下载多页,构造url
paras = {
'nodeids': 25635,
'pageidx': i
}
url = 'https://www.thepaper.cn/load_index.jsp?' + urlencode(paras) response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
# print(response.text) # 测试网页内容是否提取成功ok # 2 解析索引界面网页内容
def parse_page_index(html):
soup = BeautifulSoup(html, 'lxml') # 获取每页文章数
num = soup.find_all(name='div', class_='news_li')
for i in range(len(num)):
yield {
# 获取title
'title': soup.select('h2 a')[i].get_text(),
# 获取图片url,需加前缀
'url': 'https://www.thepaper.cn/' + soup.select('h2 a')[i].attrs['href']
# print(url) # 测试图片链接
} # 3 获取每条文章的详情页内容
def get_page_detail(item):
url = item.get('url')
# 增加异常捕获语句
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.text
# print(response.text) # 测试网页内容是否提取成功
except RequestException:
print('网页请求失败')
return None # 4 解析每条文章的详情页内容
def parse_page_detail(html):
soup = BeautifulSoup(html, 'lxml')
# 获取title
if soup.h1: # 有的网页没有h1节点,因此必须要增加判断,否则会报错
title = soup.h1.string
# 每个网页只能拥有一个<H1>标签,因此唯一
items = soup.find_all(name='img', width=['100%', ''])
# 有的图片节点用width='100%'表示,有的用600表示,因此用list合并选择
# https://blog.csdn.net/w_xuechun/article/details/76093950
# print(items) # 测试返回的img节点ok
for i in range(len(items)):
pic = items[i].attrs['src']
# print(pic) #测试图片链接ok
yield {
'title': title,
'pic': pic,
'num': i # 图片添加编号顺序
} # 5 下载图片
def save_pic(pic):
title = pic.get('title')
# 标题规范命名:去掉符号非法字符| 等
title = re.sub('[\/:*?"<>|]', '-', title).strip() url = pic.get('pic')
# 设置图片编号顺序
num = pic.get('num') if not os.path.exists(title):
os.mkdir(title) # 获取图片url网页信息
response = requests.get(url, headers=headers)
try:
# 建立图片存放地址
if response.status_code == 200:
file_path = '{0}\{1}.{2}'.format(title, num, 'jpg')
# 文件名采用编号方便按顺序查看,而未采用哈希值md5(response.content).hexdigest()
if not os.path.exists(file_path):
# 开始下载图片
with open(file_path, 'wb') as f:
f.write(response.content)
print('文章"{0}"的第{1}张图片下载完成'.format(title, num))
else:
print('该图片%s 已下载' % title)
except RequestException as e:
print(e, '图片获取失败')
return None def main(i):
# get_page_index(i) # 测试索引界面网页内容是否获取成功ok html = get_page_index(i)
data = parse_page_index(html) # 测试索引界面url是否获取成功ok
for item in data:
# print(item) #测试返回的dict
html = get_page_detail(item)
data = parse_page_detail(html)
for pic in data:
save_pic(pic) # 单进程
# if __name__ == '__main__':
# for i in range(1, 26):
# main(i) # 多进程
if __name__ == '__main__':
pool = Pool()
pool.map(main, [i for i in range(1, 26)])
pool.close()
pool.join()

结果:

文章代码和栏目从2015年至今437篇文章共1509张图片资源,可在下方链接中得到。
https://github.com/makcyun/web_scraping_with_python

本文完。

使用ajax爬取网站图片()的更多相关文章

  1. Python:爬取网站图片并保存至本地

    Python:爬取网页图片并保存至本地 python3爬取网页中的图片到本地的过程如下: 1.爬取网页 2.获取图片地址 3.爬取图片内容并保存到本地 实例:爬取百度贴吧首页图片. 代码如下: imp ...

  2. Day11 (黑客成长日记) 爬取网站图片

    #导入第三方库# coding:utf-8import requests,re #找到需要爬取的网站'http://www.qqjia.com/sucai/sucai1210.htm' #1>获 ...

  3. webmagic 二次开发爬虫 爬取网站图片

    webmagic的是一个无须配置.便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫. webmagic介绍 编写一个简单的爬虫 webmagic的使用文档:http://w ...

  4. 使用Jsoup爬取网站图片

    package com.test.pic.crawler; import java.io.File; import java.io.FileOutputStream; import java.io.I ...

  5. jsoup爬取网站图片

    package com.ij34.JsoupTest; import java.io.File; import java.io.FileOutputStream; import java.io.Inp ...

  6. Ajax爬取百度图片

    目标网址 分析网址:http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2& ...

  7. 【Python】爬取网站图片

    import requests import bs4 import urllib.request import urllib import os hdr = {'User-Agent': 'Mozil ...

  8. PHP 结合前端 ajax 爬取网站信息后, 向指定用户发送指定短信;

    <?php /** * Description * @authors Your Name (you@example.org) * # 根据时时彩的最新一期的号码, 判断如果为首尾同号则发送短信 ...

  9. Python爬虫学习(6): 爬取MM图片

    为了有趣我们今天就主要去爬取以下MM的图片,并将其按名保存在本地.要爬取的网站为: 大秀台模特网 1. 分析网站 进入官网后我们发现有很多分类: 而我们要爬取的模特中的女模内容,点进入之后其网址为:h ...

随机推荐

  1. UI层自动化测试框架(一)-简介和环境搭建

    http://blog.csdn.net/ToBeTheEnder/article/details/52302777

  2. 《从零開始学Swift》学习笔记(Day 52)——Cocoa错误处理模式

    原创文章,欢迎转载. 转载请注明:关东升的博客 Swift错误处理模式,在Swift1.x和Swift 2.0是不同的两种模式. Swift 1.x代码错误处理模式採用Cocoa框架错误处理模式,到如 ...

  3. oc27--synthesize,省略getset实现

    // // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject { @public int _a ...

  4. Linux gadget驱动分析1------驱动加载过程

    为了解决一个问题,简单看了一遍linux gadget驱动的加载流程.做一下记录. 使用的内核为linux 2.6.35 硬件为芯唐NUC950. gadget是在UDC驱动上面的一层,如果要编写ga ...

  5. poj--1753--Flip Game(dfs好题)

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37201   Accepted: 16201 Descr ...

  6. 什么是 less? 如何使用 less?

    什么是 Less? Less 是一门 CSS 预处理语言,它扩充了 CSS 语言,增加了诸如变量.混合(mixin).嵌套.函数等功能,让 CSS 更易编写.维护等. 本质上,Less 包含一套自定义 ...

  7. idea使用svn

    一.在idea中配置svn 二.导出maven项目 连接svn 点击checkout 点击ok就可以 到Commit Changes 这里有几个选项需要了解的: Auto-update after c ...

  8. idea UML快捷键

  9. 1.0 windows10系统安装步骤(1)

    1.0 windows10系统安装步骤(1) 根据自己对笔记本系统的折腾,为了方便他人系统的安装,故总结笔记本系统的安装步骤 目录: 1.0 [windows10系统安装步骤(1)] 2.0 Linu ...

  10. nginx负载均衡及反向代理

    1.启动,重启,关闭 启动:/usr/local/nginx/sbin/nginx (/usr/local/nginx/sbin/nginx -t 查看配置信息是否正确) 重启:/usr/local/ ...