爬虫的一般思路:
- 抓取网页、分析请求
- 解析网页、寻找数据
- 储存数据、多页处理 -
分析具体网页请求:
1. 观察以下网址翻页后的URL:
http://www.zkh360.com/zkh_catalog/3.html
可以看到,有些网址翻页后URL是不变的,那该怎么爬取,请看下文。
2. 使用谷歌浏览器分析网页的真实请求
- 谷歌浏览器——检查——Network
- 首先清空请求列表,点击下一页(第2页)
- 在请求列表里查找真实的请求,可发现包含商品信息的真实请求为: http://www.zkh360.com/Product/SearchProduct?catalogueId=3&pageIndex=2&pageSize=20
箭头所指的地方就是真实请求
-
以下是第2、3、4页的请求,通过对比可以发现网站是通过pageIndex参数控制翻页的,并且pageSize参数删去之后并不会对请求产生影响
- 有关参数的信息可以在Hearders的Query String Parameters里查找到
- 翻页后URL不发生变化的网站的数据一般都是通过Ajax或者JavaScript加载的,可以在过滤器的XHR或者JS中找到真实请求
3. 寻找真实请求的三个步骤
- 分析:使用谷歌浏览器开发者工具分析网页的请求
- 测试:测试URL请求中每个参数的作用,找出控制翻页等功能的参数
- 重复:多次重复寻找符合爬虫需要的真实请求
实战:爬取知乎
通过爬取知乎“轮子哥”——vczh关注的人分析Ajax或者JavaScript加载的数据的真实请求并展示这种爬取方法的具体过程。
1. 寻找真实请求的测试
- 首先,进入“轮子哥——vczh”关注的人的页面(注意:需要先登录个人知乎账号)
- 通过禁止JavaScript加载的方法发现页面不能正常加载,确认该页面的翻页是通过JavaScript加载数据实现的
- 使用谷歌浏览器开发者工具寻找包含关注人信息的真实请求,可以发现真实请求是以“followees”开头的请求,其返回一个JSON格式的数据,该数据对应下一页的“他关注的人”:
- 双击这个请求,返回一个JSON格式的数据,可以通过安装JSONView插件在浏览器中更好地显示该数据
- 接下来便可以尝试爬取该请求的数据
2. 尝试爬取真实请求的数据
- 首先使用requests.get()尝试爬取数据
# -*- coding:utf-8 -*-
import requests
url = 'https://www.zhihu.com/api/v4/members/excited-vczh/followees?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset=20&limit=20'
response = requests.get(url).text
print(response)
<html><body><h1>500 Server Error</h1>
An internal server error occured.
</body></html>
- 可以发现返回了“500 Server Error”,即由于网站反爬虫的原因,服务器返回了“500服务错误”
- 该问题可以通过添加hearders请求头信息解决
3. 添加hearders请求头信息模拟浏览器访问
- 请求头信息承载了关于客户端浏览器、请求页面、服务器等相关的信息,用来告知服务器发起请求的客户端的具体信息
- 知乎的反爬虫机制是通过核对请求头信息实现的,所以需要在使用requests请求数据的时候加上所需的请求头
- 对比知乎的请求头信息和常见的请求头信息,发现知乎请求头多了authorization和X-UDID的信息
- 在爬虫程序中添加请求头信息,即添加headers
# -*- coding:utf-8 -*-
import requests
headers = {
'authorization':'Bearer 2|1:0|10:1519311205|4:z_c0|92:Mi4xeVFXVEF3QUFBQUFBVUd2WmJrTXJEU2NBQUFDRUFsVk5aV2EyV2dBdzY2cTlRY0JHTkc0TkpMalZwOXBkRkowby13|d5a54e1ffbdf3097b4c79eb2dbf297e9c6b55971566d830ce33f8852601375ee ', #括号中填上你的authorization
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36',#括号中填上你的User-Agent
}
url = 'https://www.zhihu.com/api/v4/members/excited-vczh/followees?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset=20&limit=20'
response= requests.get(url, headers = headers).json()
##print(response)
注:刚才写的时候出问题了,说是User-Agent问题,查了半天,发现是在最前面多了个空格。。
- 运行程序,成功返回数据
4. 使用pandas把数据保存入库
- pandas DataFrame的from_dict()方法可以很方便地把爬取到的数据保存为DataFrame格式的结构化数据
import pandas as pd
response= requests.get(url, headers = headers).json()['data'] #添加上['data']是因为关注人的信息是保存在data下面的,只需要这一部分的数据
df = pd.DataFrame.from_dict(response)
df.to_csv('user.csv')
5. 定义函数实现翻页爬取
- 定义一个get_user_data()函数,实现翻页爬取功能,并添加上爬取时间间隔以免由于爬取太频繁给服务器造成负担
import time
user_data = []
def get_user_data(page):
for i in range(page):
url = 'https://www.zhihu.com/api/v4/members/excited-vczh/followees?include=data%5B*%5D.answer_count%2Carticles_count%2Cgender%2Cfollower_count%2Cis_followed%2Cis_following%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics&offset={}&limit=20'.format(i*20)
response = requests.get(url, headers=headers).json()['data']
user_data.extend(response) #把response数据添加进user_data
print('正在爬取第%s页' % str(i+1))
time.sleep(1) #设置爬取网页的时间间隔为1秒
if __name__ == '__main__':
get_user_data(10)
df = pd.DataFrame.from_dict(user_data)
df.to_csv('users2.csv')
正在爬取第1页
正在爬取第2页
正在爬取第3页
正在爬取第4页
正在爬取第5页
正在爬取第6页
正在爬取第7页
正在爬取第8页
正在爬取第9页
正在爬取第10页
ok,成功解决