爬完魔方之后,再接再厉爬取自如和链家,然后...不出意外的又失败了!在向右老师和羽恒大神的拯救下,终于把我从坑里挖了出来。虽然错的也还有点稀里糊涂的,但前事不忘,后事之师。下面把遇到的坑简单说一下。
<h4>xpath找自如</h4>
首先找到自如友家杭州站的地址,http://hz.ziroom.com/z/nl/z2.html
我觉得我也就是这个第一级的网址能找对了...
然后观察网址,找需要的标题,地址和价格
下面是我写的程序
...
infos=selector.xpath('div//li[@class="clearfix"]/div/')
list_dict=[]
for info in infos:
item={}
name=info.xpath('div/h3/a/text()')[0]
address=info.xpath('div/h4/a/text()')[0]
price=info.xpath('p/[@class="price"]/text()')[0]
当时我的逻辑是,在chrome用小箭头找到每个房源的地址,得到class=clearfix这一级,然后向下。然后标题在txt下的“h3”处,地址在“h4”处,价格在另一个标签price处。然后就试着写下来,结果是运行不出来....
大神的诊断:一个是需要请求头伪装,另外就是地址还要取高一级,点选到所有的房源。
还有定位还不够准确,div要定到第二个,所以是div[2]。价格这里,因为二级结构Infos已经定位到价格,所以不要再写class=price这些了,直接用p[1]定位。
#coding:utf-8
import requests
from lxml import etree
import random
url='http://sz.ziroom.com/z/nl/z2.html'
def getReqHeaders():
"""
功能:随机获取HTTP_User_Agent
"""
user_agents=[
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"]
user_agent = random.choice(user_agents)
req_headers={
'User-Agent':user_agent
}
return req_headers
html=requests.get(url,headers=getReqHeaders()).content
#print(html)
selector=etree.HTML(html)
infos=selector.xpath('//*[@id="houseList"]/li')
#print infos
list_dict=[]
for info in infos:
item={}
name=info.xpath('div[2]/h3/a/text()')[0]
address=info.xpath('div[2]/h4/a/text()')[0]
price=info.xpath('div[3]/p[1]/text()')[0]
print name, ' ',address, ' ',price
#item['name']=name
#item['address']=address
#item['price']=price
#list_dict.append(item)
#print list_dict
在地址向上一栏这里我纠结了很久,因为爬魔方的时候,程工教路,取值就是从clearfix这里取的,用小箭头点选单个公寓列表得到。而自如这里改为id这一级,从所有公寓列表选取。似乎逻辑不同呢,我要再好好想想...
html=requests.get(url).content
selector=etree.HTML(html)
infos=selector.xpath('//div[@class="orgs-room clearfix"]/div[2]')
for info in infos:
shop_name=info.xpath('p[@class="room-hd"]/a/text()')[0]
address=info.xpath('p[@class="address"]/text()')[0]
room_money=info.xpath('p[@class="room-money"]/strong/text()')[0].lstrip('均价:¥').rstrip('/月')
print shop_name,address,room_money
<h4>BeautifulSoup爬链家</h4>
试着用bs4爬链家,并且加上页数的循环。
其实链家的结构是公认很清晰的,用采集器爬的时候,什么跳转都不用。但是自己一写代码,就马上暴露学习的不足了...
自己写的代码,有两个问题,一个是爬出来的都是单一房源,另一个是列表,无法用text找到。 比如写成"address=lj.find_all('div',attrs={'class':'address'}).text"就会报错。
(前略)
url='http://gz.lianjia.com/ershoufang/'
for i in range(1,2):
i=str(i)
a=(url+'pg'+i+'/')
html=requests.get(url=a).text
lista=[]
lj=BeautifulSoup(html, "lxml")
infos=lj.find_all('div',attrs={'class':'info clear'})
for info in infos:
item={}
title=lj.find_all('div',attrs={'class':'title'})
print type(title)
address=lj.find_all('div',attrs={'class':'address'})
price=lj.find_all('div',attrs={'class':'totalPrice'})
(以下略)
下面是向右老师改的代码:
import requests
from bs4 import BeautifulSoup
url='http://bj.lianjia.com/ershoufang/'
for i in range(1,3):
i=str(i)
a=(url+'pg'+i+'/')
print a
html=requests.get(url=a).content
lj=BeautifulSoup(html, "html.parser")
for info in lj.find_all('div', attrs={'class': 'info clear'}):
title = info.select('div.title > a')[0].get_text()
print title
price = info.select('div.priceInfo > div > span')[0].text
print price
loc = info.select('div.flood > div')[0].text
print loc
原因是,一个是没有把爬页数和下面的每页信息形成嵌套关系,所以爬出来的结果都是一样的;第二个还是网页结构没把握好,"class:info clear"这个二级结构倒是找到了,但是向右老师建议下面应该用select,find找到的是一类标签,用来定位比较复杂。select的好处,就是可以一层一层的找到标签。
比如总价'div.priceInfo > div > span'这里,也可以写成'div.priceinfo > div.totalPrice > span',span没有属性。
这样就比attr要清楚很多。
这个周末总算把两个网站结构又弄清楚了(虽然80%都是别人的功劳!)。另外看了天善智能邱祐玮的爬虫视频。看视频的时候觉得好简单啊,自己做的时候怎么就那么复杂!
第二级结构该取哪一级,还要好好弄明白。
第三级结构的定位,每次的排列组合,搞得我都没信心了,还是人品+技术问题,要练习再练习!
网友评论