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