爬取鏈家網租房資訊(萬級資料的簡單實現)
阿新 • • 發佈:2019-02-18
這不是一個很難的專案,沒有ajax請求,也沒有用框架,只是一個requests請求和BeautifulSoup的解析
不過,看這段程式碼你會發現,BeautifulSoup不止只有find和fing_all用於元素定位,還有fing_next等其他的更簡單的,你如果某事覺得xpath比BeautifulSoup更簡單,那你真的應該結合我這個再把BeautifulSoup文件再看一遍,你會發現基於lxml解析的BeautifulSoup更強大
當然程式碼中還有一些小的細節,可以讓你學到一些東西。比如,物件的傳入,如何避免頻繁的IO操作
那接下來就貼程式碼了,程式碼中有註釋,沒有什麼好解釋的,所以接下來就只剩下程式碼和程式碼的註釋了! 如果有不懂得可以私信。
# _*_ coding:utf-8 _*_
import time,csv
from random import uniform,choice
import requests
from bs4 import BeautifulSoup
cities = ['bj', 'sh', 'nj', 'wh', 'cd', 'xa','hf']
# 一個我們將要爬取城市的列表
def get_city():
global cities
try:
city = choice(cities)
cities.remove(city)
# 隨機選取一個城市進行爬取,然後再列表中刪除這個城市
print(cities)
except IndexError:
return None
# 當沒有城市了,就返回一個None
return city
def get_url(index,city):
if city == None:
return
# 城市值為None時,我們就跳出
else:
if index == 1:
url = 'https://{city}.lianjia.com/zufang/'.format(city=city)
return url
# 這是首頁連結
else:
url = 'https://{city}.lianjia.com/zufang/pg{index}'.format(index=index,city=city)
return url
def get_ressponse(url,file,headers):
html = requests.get(url=url,headers=headers,verify=False)
Soup = BeautifulSoup(html.text,'lxml')
house_list = Soup.find(attrs={'id':'house-lst'}).find_all('li')
for li in house_list:
detail_mes = li.a['href']
img_house = li.img['src']
title = li.h2.a.get_text(strip=True)
region = li.find_next(attrs={'class':'where'}).a.get_text(strip=True)
zone = li.find_next(attrs={'class':'zone'}).span.get_text(strip=True)
meters = li.find_next(attrs={'class':'meters'}).get_text(strip=True)
directory = li.find_next(attrs={'class':'meters'}).find_next_sibling('span').get_text()
other = li.find_next(attrs={'class':'other'}).find('div').get_text(strip=True)
chanquan = li.find_next(attrs={'class':'chanquan'}).get_text(strip=True)
file.writerow([detail_mes,img_house,title,region,zone,meters,directory,other,chanquan])
# 我們將傳進一個csv的寫的物件,對檔案進行寫操作
def main(city):
for index in range(1, 101):
try:
if index == 1 or index == 2:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Referer': 'https://{city}.lianjia.com/zufang/pg3'.format(city=city),
# 我們動態的調換跳轉的頁面,覺得更像人的點選行為
'Host': '{city}.lianjia.com'.format(city=city),
# 這裡我們動態的調換要訪問的主機
}
else:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Referer': 'https://{city}.lianjia.com/zufang/pg3'.format(city=city,index=index-1),
'Host': '{city}.lianjia.com'.format(city=city),
}
# 注意這裡的請求頭我們在不同的情況下值是不一樣的
# 當然請求頭你不換也許並不會導致出錯,但是這也是一種反爬蟲的方法,學習一下?
url = get_url(index,city)
get_ressponse(url=url, file=writer,headers=headers)
# 將請求頭傳入
# 傳進連結和寫物件
t = uniform(1, 3)
time.sleep(t)
# 強制要求請求休息一下,我們這裡用1,3之間的隨機數
except AttributeError:
print('我發現了一個錯誤')
except UnicodeEncodeError:
print('有一個編碼錯誤')
# 兩個錯誤檢查
if __name__ == '__main__':
with open('D:/scrapy的message/lianjia.csv','a',encoding='utf-8') as f:
# 因為預設的讀寫操作是gbk,所以最好還是改成utf-8
# 在這裡開啟檔案而不是在迴圈中開啟,我們就可以避免頻繁的IO操作
writer = csv.writer(f)
# 建立一個寫物件
writer.writerow(['detail_mes','img_house','title','region','zone,meters','directory','other','chanquan'])
# 寫入表頭
for x in range(0,100):
city = get_city()
time.sleep(10)
# 城市間的跳轉等待時間稍微長一點,畢竟我們要更友好對不對!
print('正在爬取的城市是:%s' % city)
if city == None:
break
# 如果沒有城市了,那就跳出迴圈停止了。
main(city)
按照慣例,我應該貼一下我的成果:
可以看到一共6千多資料除以2,哈哈哈哈哈哈哈!!!!!
改進之後就可以實現萬級資料的爬取了,當然我並沒有然他執行完成,還會更多哦