Python练习爬取中国作物种质信息网作物数据
前言
这段时间都不知道在干什么,想反编译抖音吧,反编译成功了,可是自己能力不足没能找到加密参数的代码……算是知道自己有多菜了
补一篇爬取中国作物种植信息网的(可以练习post传参),下一篇就写写怎么反编译抖音的,至于**加密…有知道的大牛还请指导指导!
目标
本次我们爬取的目标是–中国作物种植信息网(仅做练习),这是我在找练习爬虫的时候,找到的爬取网站,于是就自己写了写,结果发现自己还是有点不足,也算是帮自己练了一道好题,以下正式开始:
这是作物界面的链接:http://www.cgris.net/query/croplist.php
可以看到有很多的作物,我们在开发者工具下重新加载一下该页面,就可以发现这些作物也是通过异步加载出来的:
这里我们可以看到是一个post请求,需要传递的参数为 action 以及 _,所以要想获取全部作物的信息的话,需要带上这两个参数向服务器发送一个post请求,在得到的响应中遍历操作
由于数量偏多,我就以第一个小麦为例!
我们点击小麦后,可以看到弹出一个网页来:
在这里我们直接点击显示结果窗口,可以看到光是小麦就有13944多个种质类别,然而通过我的测试,这也仅是一部分,应该有两万多个
具体关系与 显示结果窗口右边的那串编码有关,若是以编码形式显示那么这里的结果有13944个,而若以中文显示粮食作物,小麦则有2万多个;细心的各位也已经发现这里的粮食作物,小麦即是url中的参数
接着我们通过开发者工具可以看到:
这些便是其加载的一部分类别的编号代码如:01-00005
看到这里你可能还疑问加载这些干嘛,别急接着看:
这些就是在我们点击了第一页后加载的内容,同样也是post请求,不得不说几乎都是post啊…这里的编号就作为了p参数传递,以及croptype其实就是粮食作物,小麦,还有action也是在变化的,之前是menu,具体的作物请求时参数变为了item;
别以为这就完了,根据测试,一页带有100条记录,而请求第一页时就只有这些参数,当请求后面的页数时又会多出一个参数:
就是这里的s,s就是常见的偏移量了,我们算一算,13944/100,139余44,而这是从第二页开始计数,所以这样的小麦应该有139页;
分析到这里我们也渐渐清晰了:
这里还有一个最明显的地方,就是post请求的url都是:
http://www.cgris.net/query/o.php
那么一步步来,首先传递action为menu的参数,post可以得到所有的种质的种类(这里我有post但是由于数据量较大所以我没有获取,而是直接将粮食作物,小麦作为参数写入程序)即可遍历循环作为corptype的参数值
接着我们首先获取第一页的作物编号的数据,因为第一页包含有总的记录条数,所以我们一定要获取,然后对记录数做处理,得到总页数,以便循环
接着就是加入编号参数去post以得到详细的数据 在第一页处理完后根据总页数再加上s去获取更多页的数据
还需要注意的是,在爬取的过程中一开始我只能获取不到40条的数据,于是添加了随机的代理以及请求头就可以解决;
若有需要改进的地方,欢迎指点!
代码我就直接放出来了,另外我的github上也更新了,获取网易云指定歌曲的评论的代码,有兴趣的同学可以去看下点颗小星星哦–传送门
这是这篇的git地址:传送门2
什么开始动刀?直接上菜!
import random
import time
import requests
import math
import pymongo
import socket
socket.setdefaulttimeout(20)
postUrl = 'http://www.cgris.net/query/o.php'
user_agent = [
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
"Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
"Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
"Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
"Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
"Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
"Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
]
headers = {
'User-Agent':user_agent[random.randint(0,20)],
'Accept-Language': 'zh-CN',
'Connection': 'keep-alive',
'X-Requested-With': 'XMLHttpRequest'
}
start_url = 'http://www.cgris.net/query/o.php'
proxies = [
{'https': '118.190.145.138:9001'},
{'https': '106.8.17.23:60443'},
{'https': '101.236.60.48:8866'},
{'https': '101.236.21.22:8866'},
{'https': '222.94.23.50:53281'},
{'https': '221.228.17.172:8181'},
{'https': '101.236.18.101:8866'},
{'https': '118.31.220.3:8080'},
{'https': '183.48.89.227:8118'},
{'https': '101.236.60.225:8866'},
{'https': '106.75.71.122:80'},
{'https': '27.184.124.252:8118'},
{'https': '101.236.60.52:8866'},
{'https': '101.236.19.165:8866'},
{'https': '106.56.102.185:8070'},
{'https': '106.56.102.3:8070'},
{'https': '60.255.186.169:8888'},
{'https': '106.56.102.213:8070'},
{'https': '101.236.22.141:8866'},
{'https': '121.225.26.7:3128'},
{'https': '36.33.25.209:808'},
{'https': '106.56.102.98:8070'},
]
# proxy = proxies[random.randint(0,21)]
def getHtml(formdata):
try:
response = requests.post(url=start_url, data=formdata, headers=headers, proxies=proxies[random.randint(0, 21)])
response.close()
time.sleep(random.randint(1, 4))
return response
except TimeoutError as e:
print(e)
def startHtml():
#第一页
token = 1
response = getHtml(make_form_data(0))
all_record = eval(response.text)[0]
s_max = math.floor(all_record / 100)
# eval将字符串形式转换为等功能的数据形式,获取总条数
number_list = eval(response.text)[1]
print(all_record)
print(s_max)
getDetail(number_list,token)
for i in range(1, s_max + 1):
parse_record_next(i,token)
def getDetail(number_list,token):
for number in number_list:
print(number)
form_data = {
'action': 'item',
'p': number[0],
'croptype': '["粮食作物", "小麦"]',
'_': ''
}
r = getHtml(form_data)
result = r.json()
print(result)
print('第' + str(token) + '条...')
token += 1
time.sleep(random.randint(1,4))
toMongoDB(result)
print('第一页已爬取完毕...\n 开始爬取下一偏移量的100条数据...')
'''
#获取更多的作物
def getAllCroptype():
form_data = {
'action': 'menu',
'_': ''
}
r = getHtml(form_data)
result = r.text
print(result)
'''
def make_form_data(fd_num):
if fd_num == 0:
# 获取总记录条数的post参数,针对不同页的数据,第一页与其他页的post参数不同,croptype决定查询的种质
form_data = {
'action': 'query',
'p': '{}',
'croptype': '["粮食作物", "小麦"]',
'_': ''
}
else:
form_data = {
'action': 'queryp',
'p': '{}',
's': str(fd_num),
'croptype': '["粮食作物", "小麦"]',
'_': ''
}
return form_data
#获取下几页的数据
def parse_record_next(i,token):
token = token + 1
response = getHtml(make_form_data(i))
m = 2
next_page_number_list = eval(response.text)
getDetail(next_page_number_list,token)
m += 1
print('第'+str(m)+'页已爬取完毕...\n 开始爬取下一偏移量的100条数据...')
#保存到MongoDB
def toMongoDB(result):
client = pymongo.MongoClient(host='localhost',port=27017)
db = client['cgris']
cgris = db['first']
cgris.insert(result)
if __name__ == '__main__':
startHtml()