酱菜Seven7原创,转载请注明出处。
使用的手段:数据库Mysql, 语言python,正则表达式re
在获取了评论url的情况下(获取京东评论的url方法),现在我们可以来爬取用户昵称和url了。作为一个初学者,我用的正则表达式,来对那url的数据,进行匹配获取。
一、根据内容,编写合适的正则表达式
通过分析打开的url地址的数据,我们可以找到所需的两个规律:
1、用户昵称部分:
所以,我们针对提取用户的正则表达式如下:
r'\"nickname\":\"([^",]+)\",\"replyCount2\"'
2、评论部分:
评论部分,因为会有无追评,而造成结尾不一致:
情况一:
情况二:
匹配评论的正则表达式为:
r'\"content\":\"([^"]+)\",\"(?:creationTime|vcontent)\"'
二、爬取数据的主要代码:
代码功底不好,不要嫌弃,而且赶时间,能用就行,哈哈哈哈哈
导入的库:
import requests
import re
import pymysql
第一部分
在此部分,我是组装url,循环4类评论。然后每一类,循环页码,这样就可以读取每类每页的url的数据,再调用方法来爬取了。我是创建了数据库的四个表,分别存储,要是没有这个需求的,存一个表就好了。
if __name__ == "__main__":
#每次更换商品时,记得更改所要存入的表名。
table_list = creat_table("comment33") #创建4个数据库表,并得到列表
for index in range(4): #构建4种评论的url
print("当前在的阶段为......................................................................"+ str(index))
'''全部:0,差:1, 中:2, 好:3'''
#每次更换商品,只需要修改base_url_part1部分的url。后面几部分,是无需修改的。
base_url_part1 = "https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100007651578&score="
base_url_part2 = str(index)
base_url_part3 = "&sortType=5&page="
base_url_part4 = "0" #此为评论页码
base_url_part5 = "&pageSize=10"
base_url = base_url_part1 + base_url_part2 + base_url_part3 +base_url_part4 + base_url_part5
commentCount = get_CommentCount(base_url) #获取全部的评论数
pagenum_max = int(commentCount / 10 ) #京东设置为每页10个用户的评论,计算评论页面数目(即使总评论很多,网站上也提供有限的评论)
for pagenum in range(pagenum_max):
print("current pagenum is ..............: " + str(pagenum))
'''pagenum页码,循环每页,获取数据'''
url = base_url_part1 + base_url_part2 + base_url_part3 + str(pagenum) + base_url_part5
fake_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
}
response = requests.get(url, headers = fake_headers)
print(response.status_code)
try:
page_connent = response.content.decode('gbk')
except UnicodeDecodeError as err:
print("catch UnicodeDecodeError.....!")
continue
# page_connent = response.content.decode('gbk')
currentPage_user , currentPage_comment = get_comment(page_connent)
if currentPage_user == [] or currentPage_comment == []: #如果用户昵称不存在,则可认为已经没有评论了,终止执行
break
input_database(currentPage_user , currentPage_comment, table_list[index]) #存入数据库
第二部分:代码自动创建四个数据库表 。
主要是想偷懒,当时一个商品的评论放一类,所以会建很多数据库表,所以就让代码来创建了。当然,如果没有需求的,一个表存个几万几十万数据也是可以的。
def creat_table(table_baseName):
'''实现自动创建数据库表(4个),避免手动创建,table_name是表名'''
table_list = []
#组装sql语句,创建4个表
sql_part1 = "CREATE TABLE IF NOT EXISTS `"
# sql_part2 = "comment6"
sql_part3 = "`( `id` INT UNSIGNED AUTO_INCREMENT,\
`product` VARCHAR(100) ,\
`username` VARCHAR(40),\
`comment` LONGTEXT,\
PRIMARY KEY ( `id` )\
)ENGINE=InnoDB DEFAULT CHARSET=gbk;"
for i in range(4):
db = pymysql.connect(host="localhost",user="root",password="123456",db="jdcomment",charset="utf8")
cur = db.cursor()
#每次创建表记得修改
sql_part2 = table_baseName
if i ==0 :
sql_part2 = sql_part2
elif i== 1:
sql_part2 = sql_part2 + '_bad'
elif i== 2:
sql_part2 = sql_part2 + '_middle'
elif i== 3:
sql_part2 = sql_part2 + '_good'
table_list.append(sql_part2)
sql = sql_part1 + sql_part2 + sql_part3
cur.execute(sql) #执行sql语句创建4个表
print('table creat......!')
db.commit()
cur.close()
db.close()
return(table_list) #返回一个包含4个数据库表名的列表
第三部分:获取评论总数目
当时,以为看到一个商品几十万条,以为可以爬取下来。没想到,最多可见100页,也就是1千条评论。只不过有些评论只有几百条,还是需要来给循环一个参考值吧。评论条数,在请求url返回的数据里面是有的,我用的是正则表达式匹配出来。
def get_CommentCount(base_url):
'''获取评论总数'''
fake_headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
}
response = requests.get(base_url, headers = fake_headers)
all_content = response.content.decode('gbk')
# "commentCount":698813,
re_model = re.compile(r'\"commentCount\":([^,]+),')
result_list = re_model.findall(all_content)
commentCount = int(result_list[0])
return(commentCount)
第四部分:匹配出用户昵称和评论
使用正则表达式匹配,得到的是存储这两类数据的列表。
def get_comment(page_connent):
'''匹配获取用户昵称和评论,'''
remodel_user = re.compile(r'\"nickname\":\"([^",]+)\",\"replyCount2\"') #匹配用户昵称
username_list = remodel_user.findall(page_connent)
remodel_comment = re.compile(r'\"content\":\"([^"]+)\",\"(?:creationTime|vcontent)\"') #匹配评论
comment_list = remodel_comment.findall(page_connent)
# print(username_list)
# print(len(comment_list))
# print(comment_list)
return username_list, comment_list
第五部分:存入数据库
将用户昵称和对于的评论,存入我们的MySQL数据库制造。
def input_database(currentPage_user , currentPage_comment, table_name):
db = pymysql.connect(host="localhost",user="root",password="123456",db="jdcomment",charset="utf8")
cur = db.cursor()
for i in range(10):
'''将每页用户和评论的list,单条取出,一一对应存入数据库'''
try:
username = currentPage_user[i]
comment = currentPage_comment[i]
#组装sql语句
sql_part1 = 'INSERT INTO '
sql_part2 = table_name
sql_part3 = '(username, comment) VALUES ("'"%s"'", "'"%s"'");'
sql = sql_part1 + sql_part2 + sql_part3 #组装sql语句,存入不同数据库中
sql = sql%(username, comment)
cur.execute(sql)
print('data input ......ok!')
db.commit()
except IndexError as err:
print("list index out of range")
continue
cur.close()
db.close()
print("to next pagenum.......!")
第六部分:数据库中存入的结果
数据库自动创建的表,每次四个,由基础表名决定名称。
表内数据:
(product,这部分,我自己注释了一个,并没有用代码写入)
总结:对于上面的代码,运行使用是没有问题的,如果网络不好,可能在后期请求url会很慢,这是你网络问题。。我设计的是不同商品不同类别评论存入不同表,在使用代码时,也只需要修改“第一部分”代码里面的 creat_table(“comment33”)函数传入的基础表名,和“base_url_part1”的url片段。