爬完魔方之后,再接再厉爬取自如和链家,然后…不出意外的又失败了!在向右老师和羽恒大神的拯救下,终于把我从坑里挖了出来。虽然错的也还有点稀里糊涂的,但前事不忘,后事之师。下面把遇到的坑简单说一下。

xpath找自如

首先找到自如友家杭州站的地址,http://hz.ziroom.com/z/nl/z2.html
我觉得我也就是这个第一级的网址能找对了…
然后观察网址,找需要的标题,地址和价格

图片.png
下面是我写的程序
...
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

BeautifulSoup爬链家

试着用bs4爬链家,并且加上页数的循环。
其实链家的结构是公认很清晰的,用采集器爬的时候,什么跳转都不用。但是自己一写代码,就马上暴露学习的不足了…

图片.png

自己写的代码,有两个问题,一个是爬出来的都是单一房源,另一个是列表,无法用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%都是别人的功劳!)。另外看了天善智能邱祐玮的爬虫视频。看视频的时候觉得好简单啊,自己做的时候怎么就那么复杂!
第二级结构该取哪一级,还要好好弄明白。
第三级结构的定位,每次的排列组合,搞得我都没信心了,还是人品+技术问题,要练习再练习!

文章来源于互联网:Python爬虫系列-Xpath自如和bs4链家

发表评论