学习爬虫Part5-动态爬取解决方案 之 手动分析

动态爬取解决方案 之 手动分析

动态的标志

进入一个网页,鼠标到处点,滑轮上下滚,各种框框各种信息都蹦出来了,但是网页链接没变过,网页也没重新刷新过

比如:逛网页版的网易云音乐的评论时,无论评论翻到第几页,网址也不会改变;逛知乎时,鼠标不停往下滚,只要下面还有回答,就会不断的加载出来,同样网址也不会改变

类似这样能不转跳不刷新就能加载新信息的网页,就是用了动态加载

分析什么

首先记住——所有信息在理论上都可以通过请求(链接)获得
然后记住——有些请求需要提交参数,检查headers什么的来防爬
附加一点——大多数动态加载的信息,通常都是json数据

有了这些指引提示我们就能描绘出大概的分析思路

  • 首先我们要找到json数据请求链接,通过F12捉包获得,这种包属于xhr或js里
  • 然后我们通过分析多个json数据的请求链接的参数,规律,推出所有链接的结构
  • 如果json数据是一个post包,我们还要分析要post的参数的内容,规律(加密的另谈)
  • 分析服务器是否检查请求的headers,如是,需要哪些额外headers(指user-agent外)

完成以上四步通常就能获得目标json数据,剩下的就是分析json数据本身,把目标提取出来

引导实例

以某宝为例,随便搜一个商品进去。打开F12,换到Network捉js的包,点到评论那里,很快就弹出很多个包,逐个查看其response,很快就确定了目标包,然后评论换页,捉多几个供链接分析用。
1

这是一个包的请求链接
1

通过对比刚才捉到的多个包的链接,和多次试验性发送请求,我们可以分析出链接结构——ua(包括ua)之后参数是不影响请求结果的,currentPageNum是评论页数,auctionNumId是商品id,userNumId可以不要,这样就足以构造所有json数据的请求链接,至于一些决定排序的参数这里就不再多分析。

多次试验后发现这个请求链接不需要提交数据,headers加个user-agent就可以返回数据

但是taobao返回的json数据有坑,注意一下
1

然后提取json数据,这样动态问题就解决了,可以完整的写出爬虫。jd评价的爬取和淘宝类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import requests
import re
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36'
}
def get_ids(keyword,psort):
ids = []
pages = int(input("爬商品前几页,每页30个商品"))
for i in range(1,pages+1):
url = 'https://search.jd.com/Search?keyword={}&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&psort={}&click=0&page={}&s={}'.format(keyword,psort,str(i*2-1),str(60*i-59))
r = requests.get(url,headers=headers)
response = r.content.decode('utf-8')
ids.extend(re.findall(r'li data-sku="(\d+)"',response))
print(len(ids),ids)
if input('是否只爬前几件商品yes/no')=='yes':
nums = int(input('只爬前n件商品,n<={}'.format(len(ids))))
else:
nums = len(ids)
return ids,nums

def get_comment(ids_and_nums):
pages = int(input('爬评论的前几页,10个评论每页'))
for num in range(ids_and_nums[1]):
comments = [];types = [];scores = []
f.write('https://item.jd.com/{}.html '.format(ids_and_nums[0][num])+'\n\n')
for i in range(pages):
url = 'https://club.jd.com/productpage/p-{}-s-0-t-1-p-{}.html'.format(ids_and_nums[0][num],str(i))
r = requests.get(url,headers=headers)
for each in r.json()['comments']:
f.write('得分:{}\n'.format('*' *int(each['score'])))
f.write('评论:'+each['content']+'\n')
f.write('类型:'+each['productColor']+'\n\n')
#列表储存,需要时使用
#comments.append(each['content'])
#types.append(each['productColor'])
#scores.append(each['score'])
f.write('\n\n\n\n')


keyword = input("请输入商品名")
psort = input("请输入排序的数字代号,0:默认综合 3:按销量 4:按评论")
ids_and_nums=get_ids(keyword,psort)
with open(keyword+'.txt','w',encoding='utf-8') as f:
get_comment(ids_and_nums)

#通用json,但是只按时间排序
#https://club.jd.com/productpage/p-1982079424-s-0-t-1-p-0.html
#通用json但是只按推荐排序
#https://sclub.jd.com/comment/productPageComments.action?productId=3281156&score=0&sortType=5&page=1&pageSize=10&isShadowSku=0&rid=0&fold=1
Donate? comment?