今天爬取一个网站时发现翻页URL不变,估计是做了重定向,不过没关系,再艰难的网站也能爬下来。 刚开始没什么思路,查看了网页的源代码,发现它的翻页是通过JS控制的,不像一些普通网站直接把下一页的URI写
今天爬取一个网站时发现翻页URL不变,估计是做了重定向,不过没关系,再艰难的网站也能爬下来。
刚开始没什么思路,查看了网页的源代码,发现它的翻页是通过JS控制的,不像一些普通网站直接把下一页的URI写在当前页面中,后来想到这种情况有可能是通过XHR传数据实现的,于是打开开发者工具,发现压根就没有用到这种技术,但我却有别的收获——我发现主页面POST了很多数据,原来是通过这种方式,于是我开始研究这些数据的来源。
这个网站的URL是:http://ris.szpl.gov.cn/bol/index.aspx,这是政府的网站,所以各位在爬取时不要太过频繁,只当练手即可。
注意!POST的数据只有翻页后才能看到。
通过开发者工具可以看到它POST了很多数据,请看下图(右击图片,选择“在新标签页中打开图片”可查看大图):
多翻几次页可发现这几个值的变化规律如下:
“__EVENTTARGET”的值保持不变,一直都是“AspNetPager1”。
“__EVENTARGUMENT”的值是当前页的页码。
“__VIEWSTATE”的值很长,而且是变化的,看起来像是加密过的字符串,暂时看不出有什么规律。
“__VIEWSTATEGENERATOR"的值保持不变,一直都是“248CD702”。
”__VIEWSTATEENCRYPTED“的值保持为空。
”__EVENTVALIDATION“的值也是变化的,暂时看不出有什么规律。
”tep_name“、”organ_name“、”site_address“这三个的值也保持为空。
”AspNetPager1_input“的值是翻页前的页面的页码。
为找出”__VIEWSTATE“和”__EVENTVALIDATION“的规律,我动用了”Fiddler“这个工具,因为我觉得这两个的值可能在上一个页面的源代码中找到,用”Fiddler“可以轻松地查看上一个页面的源代码。
通过搜索关键字发现源代码中有个隐藏表单,那两个的值也正好在源代码中。
就这样,把所有POST的值的来源都搞清楚了,可以开始爬数据了。
下面是我写的爬虫代码:
#!/usr/bin/env python# -*- coding: utf-8 -*-"""作者:昨夜星辰创建时间:2017年6月23日脚本描述:爬取翻页URL不变的网站。"""import reimport sysimport requestsfrom bs4 import BeautifulSoupreload(sys)sys.setdefaultencoding('utf-8')def update_data_dict(soup): data_dict['__VIEWSTATE'] = soup.find(id='__VIEWSTATE')['value'] data_dict['__EVENTVALIDATION'] = soup.find(id='__EVENTVALIDATION')['value'] data_dict['__EVENTARGUMENT'] += 1 data_dict['AspNetPager1_input'] += 1def save_data(soup): with open('result.txt', 'a') as f: for tr in soup('tr', bgcolor='#F5F9FC'): f.write(' '.join([td.text for td in tr('td')]) + '/n')def get_next_page_data(): html2 = requests.post(url, data=data_dict).text soup2 = BeautifulSoup(html2, 'lxml') update_data_dict(soup2) save_data(soup2)url = 'http://ris.szpl.gov.cn/bol/index.aspx'html1 = requests.get(url).textsoup1 = BeautifulSoup(html1, 'lxml')text = soup1.find('div', 'PageInfo').texttotal_page_num = re.search(u'共(/d+)页', text).group(1)data_dict = dict( __EVENTTARGET='AspNetPager1', __EVENTARGUMENT=1, __VIEWSTATE='', __VIEWSTATEGENERATOR='248CD702', __VIEWSTATEENCRYPTED='', __EVENTVALIDATION='', tep_name='', organ_name='', site_address='', AspNetPager1_input=0,)update_data_dict(soup1)save_data(soup1)for i in range(int(total_page_num)): get_next_page_data()
这个爬虫跑起来大约要30-40秒,跑完后生成的文件如下: