B站地址:https://www.bilibili.com/video/av70702610
侵权请联系删除
这一块的难点在于数据的异步加载,以汽车之家的官网为例:
通过查看源代码会发现,汽车品牌后面的车型数目,例如阿斯顿的82是获取不到的,因为这一部分数据是异步加载的,所以采用传统的requests+beautifulsoup的静态解析技术路线已经不能解决问题。随之,有两种解决方案:
1、模拟浏览器。
2、HTTP请求分析,利用分析出来的路径进行异步数据加载。
相比较于第二种方案,模拟浏览器是比较容易上手的方法,具体可以采用request_html或者selenium的技术路线。两种方法都是可行的,本次实验采用selenium的技术路线,来模拟Chrome浏览器行为抓取数据。Selenium支持通过Xpath、CSS样式来进行标签数据的选择。
一、数据分析
首先对要爬取的数据做一个归纳,下层的数据通过上层传递的url来爬取,框起来的数据是导入数据时,构建关系的条件(相等)。
品牌Bank: 例如 阿斯顿·马丁
车系Series: 例如 阿斯顿·马丁DB11
车型Entity: 例如 阿斯顿·马丁DB11 2019款 AMR
配置Configuration: 例如 能耗、功率等信息
数据链分析
二、代码分析
2.1品牌信息获取
爬虫代码很简单,首先通过selenium的css选择器,给出品牌信息的css路径,然后逐步解析出品牌、车型总数、车系链接地址即可,代码和结果如下图。
2.2 车系数据获取
利用上面爬取的数据,把每个品牌对应的url抛给浏览器,通过下图的css路径可以爬取相应的车系数据、每个车系对应的车型数目和车型列表url。
2.3 车型信息获取
2.4 配置信息
拿到车系(type)表中的数字,附到https://car.autohome.com.cn/config/series/后面加.html。这一块的爬取是最困难的,这个困难不是技术上,而是细节处理:
1、数据量大
2、数据结构复杂
3、反扒机制,需要人工干涉(主要是修正参数名称)
4、普通汽车和新能源汽车scheme不一样(增加电动机参数)
另外要注意释放缓存:driver.delete_all_cookies()
def Entity_Config():
current_dir = os.path.abspath('.')
print(current_dir)
file_series = os.path.join(current_dir, "data\\type.csv")
entity_column = ['series', 'Count', 'entity']
config_colomn = ['series', 'entity', 'price', 'base_para', 'body', 'motor',
'gearbox', 'base_plate', 'wheel_breaking', 'safe_equip', 'operation',
'anti_stolen', 'inner', 'seat', 'media', 'light', 'mirror', 'air_con']
#读取并获得所有URL地址,同时记录品牌名称
with open(file_series, 'r') as csvfile_series: # 源文件
reader = csv.reader(csvfile_series)
for row in reader:
try:
# 01:读取整行
# column1 = row[0] # 品牌
series = row[1] # 车系
series_counts = row[2] # 车型数目
# column4 = row[3] # url
# #################################
temp = re.findall('\d+.html', row[3])[0]
num = temp.split('.html')[0]
# #################################
# 逐个URL 爬取 批量车型
except:pass
Entity_List = []
try:
spider_Entity(num, Entity_List)
print(series, Entity_List) # 车系 + 车型
for entity in Entity_List:
df = pd.DataFrame([[series, series_counts, entity]], columns=entity_column)
df.to_csv("Entity.csv", mode='a', sep=',', index=0,header=0)
except:pass
# 逐个URL 爬取 配置
if len(Entity_List) > 0:
Config_List = []
try:
Config_List = spider_configurations(num) # 车系从表中拿,车型从Entity_List拿
if len(Entity_List) == len(Config_List): # 确保信息正确后填写
# print(Config_List)
if not test:
for i in range(len(Entity_List)):
Config_List[i].insert(0, Entity_List[i])
Config_List[i].insert(0, series)
df = pd.DataFrame([Config_List[i]], columns=config_colomn)
df.to_csv("Config.csv", sep=',', mode='a', index=0, header=0)
# else:
# print(len(Config_List), Config_List)
except:
pass
print('+++++++++++++++++++++++++ 批量车型分割符 +++++++++++++++++++++++++++++')
结果截图:部分参数
三、数据导入:
把数据放到import文件夹下,导入方法:
3.1 互联网or本地化的导入操作
# 导入品牌节点
load csv with headers from "file:///bank_origin.csv" as line
create(b:BANK{name:line.bank,count:line.count,info:line.url})
结果:
Added 234 labels, created 234 nodes, set 702 properties.
# 导入车系节点
load csv with headers from "file:///type_origin.csv" as line
create(s:SERISE{bank:'line.bank',name:line.series,count:line.Count,info:line.url})
结果:
Added 2205 labels, created 2205 nodes, set 6615 properties。
# 创建关系
load csv with headers from "file:///bank_origin.csv" as line
match(b:BANK{name:line.bank}),(entity:SERISE{bank:line.bank})
create (b)-[:Subtype{type:'车系'}]->(entity)
结果:
Set 2205 properties, created 2205 relationships, completed after 3411 ms.
# 创建索引 断言是:名字的唯一性。
create constraint on (b:BANK) assert b.name is unique
属性描述信息可以通过‘就绪’即在表机构中来选择不同字段导入,后面还要抓车型信息。可以把厂商、地域全部就绪进来。
代码获取qq(备注知识图谱):2747471416