完整京东动态爬虫代码和注解及各变量和其数据结构数据类型分析

498 阅读3分钟

import requests
import reimport json
import time
from bs4 import BeautifulSoup
#导入所需的工具库 requests解析网页 re正则处理 json解析动态网页 time为了反反爬虫

headers={    
    'Accept': '*/*',    
    'User_Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',     
    Referer':'https://item.jd.com/100002340337.html'    
    }
#构造headers来反反爬虫 均可在Network中ProductPageComment的Headers中找到需要填入的信息
url='https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100002340337&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1'
urls=['https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100002340337&score=0&sortType=5&page={}&pageSize=10&isShadowSku=0&rid=0&fold=1'.format(str(i)) for i in range(0,100,1)]
#动态爬虫中最重要的一步 找到动态网页的url#动态网页的url不同于静态直接复制网址栏的网址 需要在检查模式下的Network的ProductPageComment中Headers找到Reuqests URL 即为动态爬虫所需的url
#连续爬取多页网站内容时 观察每一页评论对应的ProductPageComment的Reuqests URL的联系 找到url中代表页码的数字改为{} 如page={}  再利用 format函数实现表达多页

def get_reviews(url,data=None):
#构造函数方便调用爬取多页    
    response=requests.get(url,headers=headers)    
    cont=response.text    
    rex=re.compile(r'\w+[(]{1}(.*)[)]{1}')    
    content=rex.findall(cont)[0]
#由于京东url有些特别 要用正则式对其处理才能读到数据    
    con=json.loads(content)
#json解析动态网页 json.loads() 是把json数据格式转化为字典类型   
#而json.dumps()是把字典类型数据转化为json    
    news=con['comments']
#定义news为字典中的comments comments为列表类型 即news为表格类型    
    time.sleep(2)
#未防反爬虫 使得程序运行时暂停2s 这句放哪里都行    
    for n in news:
#news为列表类型 n=0:9 是列表中第一个到第十个元素(即十条评论)        
        id=n['id']        
        content=n['content']        
        creationTime=n['creationTime']        
        replyCount=n['replyCount']        
        score=n['score']        
        usefulVoteCount=n['usefulVoteCount']        
        imageCount=n['imageCount']        
        userClient=n['userClient']
#n['xx']代表第n条评论对应的xx元素 可能是字符串类型 int类型等        
        print("用户名:",id,'\n',"评论:",content,'\n',"评论时间:",creationTime,'\n',"回复次数:",replyCount,'\n',"星级:",score,'\n',"获赞:",usefulVoteCount,'\n',"图片数量:",imageCount,'\n',"客户端类型",userClient)        
        if 'afterUserComment' in n:            
            print("追加:",n['afterUserComment']['content'])
#其中afterUserComment为字典类型  由于每条评论内容用dicti存储 这里的afterUserComment为一个key 在判断有无追加评论的时候判断语句用在dict中查找元素的方式 in         
        print('\n')for 
single_url in urls:     
    get_reviews(single_url)
#调取上述构造函数多次爬取网页



  • content 动态网页传回的json格式内容 type为str
  • con 通过json.loads转化后为dict格式

      用print(con.keys())查询con字典中的元素

>>dict_keys(['productAttr', 'productCommentSummary', 'hotCommentTagStatistics', 'jwotestProduct', 'maxPage', 'testId', 'score', 'soType', 'imageListCount', 'vTagStatistics', 'csv', 'comments'])

      分析发现即为

  • news/comments 为dict中的一个key 但是type为list 即十条评论内容以列表的格式存储


>>tenth=news[9] 定义list中第十个元素为tenth 其格式为dict 即list中的十个元素均是以dict       的格式存储的

用first.keys()查看评论中的keys 如id creationTime replies afterUserCommen均为keys 但是格式各不相同str int dict等

dict_keys(['id', 'guid', 'content', 'creationTime', 'isDelete', 'isTop', 'userImageUrl', 'topped', 'replies', 'replyCount', 'score', 'imageStatus', 'title', 'usefulVoteCount', 'userClient', 'discussionId', 'imageCount', 'anonymousFlag', 'plusAvailable', 'mobileVersion', 'images', 'mergeOrderStatus', 'productColor', 'productSize', 'textIntegral', 'imageIntegral', 'afterUserComment', 'status', 'referenceId', 'referenceTime', 'nickname', 'replyCount2', 'userImage', 'orderId', 'integral', 'productSales', 'referenceImage', 'referenceName', 'firstCategory', 'secondCategory', 'thirdCategory', 'aesPin', 'days', 'afterDays'])


  • afterUserComment 为dict中的一个key 格式为dict