python爬取全国标准信息平台

python爬取全国标准信息平台

前言

目标网页

http://www.std.gov.cn/db

帮大地做个毕业论文的数据爬取,粗略看了一下,不用注册填写表单但是是动态加载页面的,不知道有无反爬的机制,那就直接上python一探究竟。

解决问题

将上面的各个省地方标准的相关资料都爬到xlsx上。

解决动态加载页面

一开始很困惑啊,怎么首页明明谷歌F12里面能找到的,get下来的数据里面没有啊?
后来又回去看看教程,一般出现这种情况是因为这种网页是用JS加载部分资源的,所以直接get该页面看不见JS的具体资源。想要验证的同学可以到谷歌商店下一个插件名叫Toggle JavaScript,它可以禁用JS,如果禁用后你想爬的数据消失了,那么就证明了该页面是动态页面.解决方法有两个:

1.手动去找你要的文件的地址

2.用selenium

这次用方法1解决了,所以也没有用到2.下面讲一讲如何实现1的。

我用的是chrom,先说明一下。在目标页面按F12,打开控制台。跳转到Networ的XHR标签。然后刷新一下页面。会发现加载了一些文件出来,我这个首页就一个文件,省的我去找了.如果有多个文件,可以依次访问他们,看看哪个是自己需要的。

点进去一看,哦吼,这不就是一个json吗,要的资料都在了,看一下url

http://www.std.gov.cn/db/search/dbPage?searchText=&op=%E6%96%B0%E7%96%86&ISSUE_DATE=&sortOrder=asc&pageSize=15&pageNumber=1&_=1554805618710

pageSize代表当前页面显示多少,pageNumber代表当前页数,如果要都访问遍历页数即可

下面直接贴代码了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#注意网页是动态加载数据
#有些地方没有分类,直接写无

import os
import os.path
import bs4
import requests
from bs4 import BeautifulSoup
import sys
import random
import re
import json
import openpyxl
import time
import random
searchlist = ["北京","天津","河北","山西","内蒙古","上海","江苏","浙江","安徽","福建","江西","山东",
"辽宁","吉林","黑龙江","河南","湖北","湖南","广东","广西","海南","重庆","四川","贵州","云南",
"西藏","陕西","甘肃","青海","宁夏","新疆"]

login_head = {
'Host': 'www.std.gov.cn',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
}

list_path = os.path.join(os.getcwd(),'test.txt')
#
filename = os.path.join(os.getcwd(),'test.xlsx')
wb = openpyxl.load_workbook(filename)
#
search_number = 400
sheet_number = 1
for i in searchlist:
print(i)
wb.create_sheet(i,index = sheet_number)
sheet_number += 1
ws = wb.get_sheet_by_name(i)
pagenumber = 1
row = 2 #定义行号
cnt = 1 #计数
flag = True
while(flag == True):
u_p = "http://www.std.gov.cn/db/search/dbPage?searchText=&op="+i+"&ISSUE_DATE=&sortOrder=asc&pageSize="+str(search_number)+"&pageNumber="+str(pagenumber)+"&_=1554781074367"
time_check = 0
print(pagenumber)
while(time_check<100):
try:
response = requests.get(u_p,headers=login_head,timeout = 10)
break
except:
time.sleep(random.randint(0,2)+random.random())
print("time_check=",time_check)
time_check+=1

json_data = json.loads(response.text)
rows_list = json_data['rows']
total_number = json_data['total']
if(pagenumber*search_number>total_number):
#如果超出总数,跳出
u_p = "http://www.std.gov.cn/db/search/dbPage?searchText=&op="+i+"&ISSUE_DATE=&sortOrder=asc&pageSize="+str(total_number-(pagenumber-1)*search_number)+"&pageNumber="+str(pagenumber)+"&_=1554781074367"
flag = False
for z in rows_list:
#判断日期是否符合
iss_time = z['ISSUE_DATE']
if(iss_time[0:4]>'2017'):
cnt+=1
continue
elif(iss_time[0:4]<'2014'):
cnt = 1
flag = False #如果日期开始小了,跳出while循环
break
else:
None
#第二列记录序列
ws.cell(row = row,column = 2).value = cnt
#第三列记录标准号
ws.cell(row = row,column = 3).value = z['C_STD_CODE']
#第四列记录名字
ws.cell(row = row,column = 4).value = z['C_C_NAME']
#第五列记录类型,注意错误
try:
ws.cell(row = row,column = 5).value = z['TRADE_CLASSIFIED']
except:
ws.cell(row = row,column = 5).value = '无'
else:
None
#第六列记录发行时间
ws.cell(row = row,column = 6).value = z['ISSUE_DATE']
#第七行记录实施时间
ws.cell(row = row,column = 7).value = z['ACT_DATE']
#第八行记录地名
ws.cell(row = row,column = 8).value = i
row += 1
cnt += 1
pagenumber+=1
wb.save('aa.xlsx')

#for i in rows_list:
# category_list.add(i['TRADE_CLASSIFIED'])
#print(category_list)

#soup = BeautifulSoup(response.text,"lxml")
#with open(list_path,'w',encoding = 'UTF-8-sig') as f:
# f.write(response.text)

因为我是要写到xlsx里面去,所以调了一个openpyxl的库

反爬

爬了一下发现,一直在中途就报错

1
2
warning 10060
主机无法访问

自己手动访问又没问题,那就是反爬机制了。
解决的方法就是用while加上try去get,一共循环100次,如果访问到了退出循环,没访问到停顿随机的时间,然后重新访问。注意timeout要写,有些时候它不报错,但是就是一直卡在那儿,所以要设置一个时限.
具体都写在上面的代码里了

注意

这个json的资源有些地方会有空白,比如访问[‘TRADE_CLASSIFIED’]的时候,偶尔一两个会报错,去看的时候发现的确没有这个key,原因是有些行业的分类是无,他就有些不写了,这地方要注意一下。

完结撒花