爬虫初学

您所在的位置:网站首页 京东商城的ip地址 爬虫初学

爬虫初学

2023-11-23 01:24| 来源: 网络整理| 查看: 265

原创,转载请注明出处。

使用的手段:数据库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片段。

今天在原基础上,稍微修改了一下代码,应该可以修改的更好,但是实在是没有时间,暂时就先放着,代码如下:

import requests import re import pymysql def creat_table(table_baseName): '''实现自动创建数据库表(4个),避免手动创建,table_name是表名''' bad_tableName = table_baseName + '_bad' middle_tableName = table_baseName + '_middle' good_tableName = table_baseName + '_good' tableNames = [table_baseName,bad_tableName,middle_tableName,good_tableName] for tableName in tableNames: createTableSql = "CREATE TABLE IF NOT EXISTS `{}`( `id` INT UNSIGNED AUTO_INCREMENT,`product` VARCHAR(100) ,`username` VARCHAR(40),`comment` LONGTEXT,PRIMARY KEY ( `id` ))ENGINE=InnoDB DEFAULT CHARSET=gbk;".format(tableName) changeDataFromDatabase(createTableSql) return(tableNames) #返回一个包含4个数据库表名的列表 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) commentCoun = 0 if result_list !=[]: 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 def getDatabaseConn(): #建立数据库的连接 conn = pymysql.connect(host="localhost",user="root",password="123456",db="jdcomment",charset="utf8") return conn def changeDataFromDatabase(sql): #执行sql语句的函数 conn = getDatabaseConn() cursor = conn.cursor() cursor.execute(sql) conn.commit() cursor.close() conn.close() def createInsertSql(table, insertValDict): #用来构造插入数据的sql语句(表名,插入的数据) keylist = [] valuelist = [] for key,value in insertValDict.items(): keylist.append(key) valuelist.append(value) sql = 'INSERT INTO {} {} VALUES {}'.format(table, str(tuple(keylist)).replace('\'',''),str(tuple(valuelist))) return sql def getCommentList(currentPage_user , currentPage_comment): curLen = min(len(currentPage_user),len(currentPage_comment)) commentList = [] for i in range(curLen): '''将每页用户和评论的list,单条取出,一一对应存入数据库''' commentList.append({"username":currentPage_user[i], "comment":currentPage_comment[i]}) return commentList def input_database(currentPage_user , currentPage_comment, table_name): #将数据存入到数据库 commentList = getCommentList(currentPage_user , currentPage_comment) for commentDict in commentList: insertSql = createInsertSql(table_name, commentDict) try: changeDataFromDatabase(insertSql) except IndexError as err: print("list index out of range") continue print("to next pagenum.......!") if __name__ == "__main__": #每次更换商品时,记得更改所要存入的表名。 table_list = creat_table("comment34") #创建4个数据库表,并得到列表 for index in range(4): #循环爬取4种评论,全部:0,差:1, 中:2, 好:3。循环爬取 print("当前在的阶段为......................................................................"+ str(index)) base_url = "https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100007651578&score={}&sortType=5&page=0&pageSize=10".format(str(index)) commentCount = get_CommentCount(base_url) #获取全部的评论数 if commentCount != 0: pagenum_max = int(commentCount / 10 ) #京东设置为每页10个用户的评论,计算评论页面数目(即使总评论很多,网站上也提供有限的评论) for pagenum in range(pagenum_max): #d对每个页面爬取 print("current pagenum is ..............: " + str(pagenum)) '''pagenum页码,循环每页,获取数据''' 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'} url = "https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100007651578&score={}&sortType=5&page={}&pageSize=10".format(str(index),str(pagenum)) 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 currentPage_user , currentPage_comment = get_comment(page_connent) if currentPage_user == [] or currentPage_comment == []: #如果用户昵称不存在,则可认为已经没有评论了,终止执行 break input_database(currentPage_user , currentPage_comment, table_list[index]) 酱菜Seven7 注:转载请注明出处


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3