如何用爬虫下载中国土地市场网的土地成交数据?
作为毕业狗想研究下土地出让方面的信息,需要每一笔的土地出让数据。想从中国土地市场网的土地成交结果公告(http://www.landchina.com/default.aspx?tabid=263&ComName=default)中点击每一笔土地,在跳转后的详细页面中下载“土地用途” “成交价格” “供地方式” “项目位置”等信息,
由于共有100多万笔土地成交信息,手动查找是不可能了,想问下能不能用爬虫给下载下来?以及预计难度和耗费时间?跪谢各位。
回复内容:
#!/usr/bin/env python # -*- coding: utf-8 -*- import requests from bs4 import BeautifulSoup import time import random import sys def get_post_data(url, headers): # 访问一次网页,获取post需要的信息 data = { 'TAB_QuerySubmitSortData': '', 'TAB_RowButtonActionControl': '', } try: req = requests.get(url, headers=headers) except Exception, e: print 'get baseurl failed, try again!', e sys.exit(1) try: soup = BeautifulSoup(req.text, "html.parser") TAB_QueryConditionItem = soup.find( 'input', id="TAB_QueryConditionItem270").get('value') # print TAB_QueryConditionItem data['TAB_QueryConditionItem'] = TAB_QueryConditionItem TAB_QuerySortItemList = soup.find( 'input', id="TAB_QuerySort0").get('value') # print TAB_QuerySortItemList data['TAB_QuerySortItemList'] = TAB_QuerySortItemList data['TAB_QuerySubmitOrderData'] = TAB_QuerySortItemList __EVENTVALIDATION = soup.find( 'input', id='__EVENTVALIDATION').get('value') # print __EVENTVALIDATION data['__EVENTVALIDATION'] = __EVENTVALIDATION __VIEWSTATE = soup.find('input', id='__VIEWSTATE').get('value') # print __VIEWSTATE data['__VIEWSTATE'] = __VIEWSTATE except Exception, e: print 'get post data failed, try again!', e sys.exit(1) return data def get_info(url, headers): req = requests.get(url, headers=headers) soup = BeautifulSoup(req.text, "html.parser") items = soup.find( 'table', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1") # 所需信息组成字典 info = {} # 行政区 division = items.find( 'span', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r1_c2_ctrl").get_text().encode('utf-8') info['XingZhengQu'] = division # 项目位置 location = items.find( 'span', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r16_c2_ctrl").get_text().encode('utf-8') info['XiangMuWeiZhi'] = location # 面积(公顷) square = items.find( 'span', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r2_c2_ctrl").get_text().encode('utf-8') info['MianJi'] = square # 土地用途 purpose = items.find( 'span', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r3_c2_ctrl").get_text().encode('utf-8') info['TuDiYongTu'] = purpose # 供地方式 source = items.find( 'span', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r3_c4_ctrl").get_text().encode('utf-8') info['GongDiFangShi'] = source # 成交价格(万元) price = items.find( 'span', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r20_c4_ctrl").get_text().encode('utf-8') info['ChengJiaoJiaGe'] = price # print info # 用唯一值的电子监管号当key, 所需信息当value的字典 all_info = {} Key_ID = items.find( 'span', id="mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r1_c4_ctrl").get_text().encode('utf-8') all_info[Key_ID] = info return all_info def get_pages(baseurl, headers, post_data, date): print 'date', date # 补全post data post_data['TAB_QuerySubmitConditionData'] = post_data[ 'TAB_QueryConditionItem'] + ':' + date page = 1 while True: print ' page {0}'.format(page) # 休息一下,防止被网页识别为爬虫机器人 time.sleep(random.random() * 3) post_data['TAB_QuerySubmitPagerData'] = str(page) req = requests.post(baseurl, data=post_data, headers=headers) # print req soup = BeautifulSoup(req.text, "html.parser") items = soup.find('table', id="TAB_contentTable").find_all( 'tr', onmouseover=True) # print items for item in items: print item.find('td').get_text() link = item.find('a') if link: print item.find('a').text url = 'http://www.landchina.com/' + item.find('a').get('href') print get_info(url, headers) else: print 'no content, this ten days over' return break page += 1 if __name__ == "__main__": # time.time() baseurl = 'http://www.landchina.com/default.aspx?tabid=263' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36', 'Host': 'www.landchina.com' } post_data = (get_post_data(baseurl, headers)) date = '2015-11-21~2015-11-30' get_pages(baseurl, headers, post_data, date)
之前帮老师爬过这个信息,从1995年-2015年有170多万条,算了下时间需要40多个小时才能爬完。我爬到2000年就没有继续爬了。当时写代码的时候刚学爬虫,不懂原理,发现这个网页点击下一页以及改变日期后,网址是不会变的,网址是不会变的,网址是不会变的Orz,对于新手来说根本不知道是为什么。后来就去找办法,学了点selenium,利用它来模拟浏览器操作,更改日期、点击下一页什么的都可以实现了。好处是简单粗暴,坏处是杀鸡用牛刀,占用了系统太多资源。再到后来,学会了一点抓包技术,知道了原来日期和换页都是通过post请求的。今天下午就把程序修改了一下,用post代替了原来的selenium。废话不说,上代码了。
# -*- coding: gb18030 -*- 'landchina 爬起来!' import requests import csv from bs4 import BeautifulSoup import datetime import re import os class Spider(): def __init__(self): self.url='http://www.landchina.com/default.aspx?tabid=263' #这是用post要提交的数据 self.postData={ 'TAB_QueryConditionItem':'9f2c3acd-0256-4da2-a659-6949c4671a2a', 'TAB_QuerySortItemList':'282:False', #日期 'TAB_QuerySubmitConditionData':'9f2c3acd-0256-4da2-a659-6949c4671a2a:', 'TAB_QuerySubmitOrderData':'282:False', #第几页 'TAB_QuerySubmitPagerData':''} self.rowName=[u'行政区',u'电子监管号',u'项目名称',u'项目位置',u'面积(公顷)',u'土地来源',u'土地用途',u'供地方式',u'土地使用年限',u'行业分类',u'土地级别',u'成交价格(万元)',u'土地使用权人',u'约定容积率下限',u'约定容积率上限',u'约定交地时间',u'约定开工时间',u'约定竣工时间',u'实际开工时间',u'实际竣工时间',u'批准单位',u'合同签订日期'] #这是要抓取的数据,我把除了分期约定那四项以外的都抓取了 self.info=[ 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r1_c2_ctrl',#0 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r1_c4_ctrl',#1 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r17_c2_ctrl',#2 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r16_c2_ctrl',#3 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r2_c2_ctrl',#4 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r2_c4_ctrl',#5 #这条信息是土地来源,抓取下来的是数字,它要经过换算得到土地来源,不重要,我就没弄了 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r3_c2_ctrl',#6 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r3_c4_ctrl',#7 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r19_c2_ctrl', #8 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r19_c4_ctrl',#9 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r20_c2_ctrl',#10 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r20_c4_ctrl',#11 ## 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f3_r2_c1_0_ctrl', ## 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f3_r2_c2_0_ctrl', ## 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f3_r2_c3_0_ctrl', ## 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f3_r2_c4_0_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r9_c2_ctrl',#12 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f2_r1_c2_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f2_r1_c4_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r21_c4_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r22_c2', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r22_c4_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r10_c2_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r10_c4_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r14_c2_ctrl', 'mainModuleContainer_1855_1856_ctl00_ctl00_p1_f1_r14_c4_ctrl'] #第一步 def handleDate(self,year,month,day): #返回日期数据 'return date format %Y-%m-%d' date=datetime.date(year,month,day) # print date.datetime.datetime.strftime('%Y-%m-%d') return date #日期对象 def timeDelta(self,year,month): #计算一个月有多少天 date=datetime.date(year,month,1) try: date2=datetime.date(date.year,date.month+1,date.day) except: date2=datetime.date(date.year+1,1,date.day) dateDelta=(date2-date).days return dateDelta def getPageContent(self,pageNum,date): #指定日期和页数,打开对应网页,获取内容 postData=self.postData.copy() #设置搜索日期 queryDate=date.strftime('%Y-%m-%d')+'~'+date.strftime('%Y-%m-%d') postData['TAB_QuerySubmitConditionData']+=queryDate #设置页数 postData['TAB_QuerySubmitPagerData']=str(pageNum) #请求网页 r=requests.post(self.url,data=postData,timeout=30) r.encoding='gb18030' pageContent=r.text # f=open('content.html','w') # f.write(content.encode('gb18030')) # f.close() return pageContent #第二步 def getAllNum(self,date): #1无内容 2只有1页 3 1—200页 4 200页以上 firstContent=self.getPageContent(1,date) if u'没有检索到相关数据' in firstContent: print date,'have','0 page' return 0 pattern=re.compile(u'<td.*?class="pager".*?>共(.*?)页.*?</td>') result=re.search(pattern,firstContent) if result==None: print date,'have','1 page' return 1 if int(result.group(1))<=200: print date,'have',int(result.group(1)),'page' return int(result.group(1)) else: print date,'have','200 page' return 200 #第三步 def getLinks(self,pageNum,date): 'get all links' pageContent=self.getPageContent(pageNum,date) links=[] pattern=re.compile(u'<a.*?href="default.aspx.*?tabid=386(.*?)".*?>',re.S) results=re.findall(pattern,pageContent) for result in results: links.append('http://www.landchina.com/default.aspx?tabid=386'+result) return links def getAllLinks(self,allNum,date): pageNum=1 allLinks=[] while pageNum<=allNum: links=self.getLinks(pageNum,date) allLinks+=links print 'scrapy link from page',pageNum,'/',allNum pageNum+=1 print date,'have',len(allLinks),'link' return allLinks #第四步 def getLinkContent(self,link): 'open the link to get the linkContent' r=requests.get(link,timeout=30) r.encoding='gb18030' linkContent=r.text # f=open('linkContent.html','w') # f.write(linkContent.encode('gb18030')) # f.close() return linkContent def getInfo(self,linkContent): "get every item's info" data=[] soup=BeautifulSoup(linkContent) for item in self.info: if soup.find(id=item)==None: s='' else: s=soup.find(id=item).string if s==None: s='' data.append(unicode(s.strip())) return data def saveInfo(self,data,date): fileName= 'landchina/'+datetime.datetime.strftime(date,'%Y')+'/'+datetime.datetime.strftime(date,'%m')+'/'+datetime.datetime.strftime(date,'%d')+'.csv' if os.path.exists(fileName): mode='ab' else: mode='wb' csvfile=file(fileName,mode) writer=csv.writer(csvfile) if mode=='wb': writer.writerow([name.encode('gb18030') for name in self.rowName]) writer.writerow([d.encode('gb18030') for d in data]) csvfile.close() def mkdir(self,date): #创建目录 path = 'landchina/'+datetime.datetime.strftime(date,'%Y')+'/'+datetime.datetime.strftime(date,'%m') isExists=os.path.exists(path) if not isExists: os.makedirs(path) def saveAllInfo(self,allLinks,date): for (i,link) in enumerate(allLinks): linkContent=data=None linkContent=self.getLinkContent(link) data=self.getInfo(linkContent) self.mkdir(date) self.saveInfo(data,date) print 'save info from link',i+1,'/',len(allLinks)
1. 多线程
2. 防止封IP
3. 用Mongdb存储大型非结构化数据
了解更多可以访问探码科技大数据介绍页面:http://www.tanmer.com/bigdata 我抓过这个网站的结束合同,还是比较好抓的。抓完生成表格,注意的就是选择栏的异步地区等内容,需要对他的js下载下来队形异步请求。提交数据即可。请求的时候在他的主页有一个id。好像是这么个东西,去年做的,记不清了,我有源码可以给你分享。用java写的 我是爬虫小白,请教下,不是说不能爬取asp的页面吗?
详细内容页的地址是”default.aspx?tabid=386&comname=default&wmguid=75c725。。。“,网站是在default.aspx页读取数据库显示详细信息,不是说读不到数据库里的数据吗?

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

http狀態碼520是指伺服器在處理請求時遇到了一個未知的錯誤,無法提供更具體的資訊。用於表示伺服器在處理請求時發生了一個未知的錯誤,可能是由於伺服器配置問題、網路問題或其他未知原因導致的。通常是由伺服器配置問題、網路問題、伺服器過載或程式碼錯誤等原因導致的。如果遇到狀態碼520錯誤,最好聯絡網站管理員或技術支援團隊以取得更多的資訊和協助。

http狀態碼403是伺服器拒絕了客戶端的請求的意思。解決http狀態碼403的方法是:1、檢查身份驗證憑證,如果伺服器要求身份驗證,確保提供正確的憑證;2、檢查IP位址限制,如果伺服器對IP位址進行了限制,確保客戶端的IP位址被列入白名單或未列入黑名單;3、檢查文件權限設置,如果403狀態碼與文件或目錄的權限設置有關,確保客戶端具有足夠的權限訪問這些文件或目錄等等。

掌握HTTP301狀態碼的意思:網頁重定向的常見應用場景隨著網路的快速發展,人們對網頁互動的要求也越來越高。在網頁設計領域,網頁重定向是一種常見且重要的技術,透過HTTP301狀態碼來實現。本文將探討HTTP301狀態碼的意義以及在網頁重新導向中的常見應用場景。 HTTP301狀態碼是指永久重新導向(PermanentRedirect)。當伺服器接收到客戶端發

如何使用NginxProxyManager實現HTTP到HTTPS的自動跳轉隨著互聯網的發展,越來越多的網站開始採用HTTPS協議來加密傳輸數據,以提高數據的安全性和用戶的隱私保護。由於HTTPS協定需要SSL憑證的支持,因此在部署HTTPS協定時需要有一定的技術支援。 Nginx是一款強大且常用的HTTP伺服器和反向代理伺服器,而NginxProxy

使用http.PostForm函數發送帶有表單資料的POST請求在Go語言的http包中,可以使用http.PostForm函數發送帶有表單資料的POST請求。 http.PostForm函數的原型如下:funcPostForm(urlstring,dataurl.Values)(resp*http.Response,errerror)其中,u

HTTP狀態碼200:探索成功回應的意義與用途HTTP狀態碼是用來表示伺服器回應狀態的數字代碼。其中,狀態碼200表示請求已成功被伺服器處理。本文將探討HTTP狀態碼200的具體意義與用途。首先,讓我們來了解HTTP狀態碼的分類。狀態碼分為五個類別,分別是1xx、2xx、3xx、4xx和5xx。其中,2xx表示成功的回應。而200是2xx中最常見的狀態碼

快速應用:PHP非同步HTTP下載多個檔案的實用開發案例分析隨著互聯網的發展,檔案下載功能已成為許多網站和應用程式的基本需求之一。而對於需要同時下載多個檔案的場景,傳統的同步下載方式往往效率低且耗費時間。為此,使用PHP非同步HTTP下載多個檔案成為了越來越常見的解決方案。本文將透過一個實際的開發案例,詳細分析如何使用PHP非同步HTTP

C#中常見的網路通訊和安全性問題及解決方法在當今互聯網時代,網路通訊已成為了軟體開發中必不可少的一部分。在C#中,我們通常會遇到一些網路通訊的問題,例如資料傳輸的安全性、網路連線的穩定性等。本文將針對C#中常見的網路通訊和安全性問題進行詳細討論,並提供相應的解決方法和程式碼範例。一、網路通訊問題網路連線中斷:網路通訊過程中,可能會出現網路連線的中斷,這會導致
