python3通过Beautif和XPath分别爬取“小猪短租-北京”租房信息,并对比时间效率(附源代码)

爬虫思路分析:

1. 观察小猪短租(北京)的网页

首页:http://www.xiaozhu.com/?utm_source=baidu&utm_medium=cpc&utm_term=PC%E6%A0%87%E9%A2%98&utm_content=pinzhuan&utm_campaign=BDPZ

选择“北京”,然后点“搜索小猪”,获取北京市的首页url:http://bj.xiaozhu.com/

观察右侧详情,页面最下面有分页,点击第2、第3页观察url的变化

http://bj.xiaozhu.com/search-duanzufang-p2-0/

http://bj.xiaozhu.com/search-duanzufang-p3-0/

验证首页是否可以写作:http://bj.xiaozhu.com/search-duanzufang-p1-0/(答案是ok的,大部分分页行的网站首页都是可以与其他分页统一化的)

因此,分页的URL可以这么构造:http://bj.xiaozhu.com/search-duanzufang-p{}-0/.format(number),其中number是几就是第几页

 

2. 观察右侧的信息,发现每个房源的信息不全,需要手动点击进去才能看到详情

因此需要获取每个房源的详情页面的URL

 

3. 观察某一房源的详细信息,这里我们提取“标题、地址、价格、房东名字、性别”等

 

使用BeautifulSoup实现

 1 """
 2 典型的分页型网站——小猪短租
 3 使用Beautifulsoup解析网页,并对比时间效率
 4 
 5 """
 6 
 7 import requests
 8 from bs4 import BeautifulSoup as bs
 9 import time
10 
11 headers = {
12     'User-Agent':'User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
13 }
14 
15 #--Beautifulsoup--
16 
17 """获取每一个房源的网址,参数是分页url"""
18 def get_link(url):
19     html_data = requests.get(url, headers = headers)
20     soup = bs(html_data.text, 'lxml')#bs4推荐使用的的解析库
21     #print(soup.prettify())   #标准化输出url中的源代码(有可能跟网页查看中的不一致,网页中有可能标签书写不规范)以此为基础抓取,如果抓取失败,用此命令查看源代码
22     links = soup.select('#page_list > ul > li > a')#注意循环点!!!直接粘贴过来的是“#page_list > ul > li:nth-child(1) > a > img”,需要去掉:nth-child(1),注意每个标签前后有空格
23     #print(links)
24     for link in links:
25         link = link.get('href')
26         #print(link)
27         get_info(link)
28 
29 """判断房东性别"""
30 def sex_is(member):
31     if member == 'member_ico':
32         return ""
33     else:
34         return ""
35 
36 """获取每一个房源的详细信息,参数url是每个房源的网址"""
37 def get_info(url):
38     html_data = requests.get(url, headers = headers)
39     soup = bs(html_data.text, 'lxml')#bs4推荐使用的的解析库
40     # print(soup.prettify())   #标准化输出url中的源代码(有可能跟网页查看中的不一致,网页中有可能标签书写不规范)以此为基础抓取,如果抓取失败,用此命令查看源代码
41     title = soup.select('div.wrap.clearfix.con_bg > div.con_l > div.pho_info > h4 > em')[0].string
42     # 用网页copy过来的全部是“body > div.wrap.clearfix.con_bg > div.con_l > div.pho_info > h4 > em”,但是使用这个爬不出来数据(我也不知道why),把body去掉或者用下面最简短的方式(只使用最近的且唯一的div)
43     # title = soup.select('div.pho_info > h4 > em ')
44     # 查询结果title格式是一维列表,需要继续提取列表元素(一般就是[0]),列表元素是前后有标签需要继续提取标签内容,使用get_text()或者string
45 
46     address = soup.select('div.wrap.clearfix.con_bg > div.con_l > div.pho_info > p > span')[0].string.strip()
47     price = soup.select('#pricePart > div.day_l > span')[0].string.strip()  # div中的id=pricePart是唯一性的,因此不用写前面的div
48     name = soup.select('#floatRightBox > div.js_box.clearfix > div.w_240 > h6 > a')[0].string.strip()
49     img = soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > a > img')[0].get('src').strip()  # 获取标签的属性值
50     sex = sex_is(soup.select('#floatRightBox > div.js_box.clearfix > div.member_pic > div')[0].get('class')[0].strip())  # 获取标签的属性值
51 
52     #将详细数据整理成字典格式
53     data = {
54         '标题':title,
55         '地址':address,
56         '价格':price,
57         '房东姓名':name,
58         '房东性别':sex,
59         '房东头像':img
60     }
61     print(data)
62 
63 
64 """程序主入口"""
65 if __name__=='__main__':
66     start = time.time()
67     for number in range(1,4):
68         url = 'http://bj.xiaozhu.com/search-duanzufang-p{}-0/'.format(number)   #构造分页url(不是房源详情的url)
69         get_link(url)
70         time.sleep(5)
71     end = time.time()
72     print('运行时长:',end-start)

 

使用Xpath实现

 

 1 """
 2 典型的分页型网站——小猪短租
 3 使用Xpath解析网页,并对比时间效率
 4 """
 5 
 6 import requests
 7 from lxml import etree
 8 import time
 9 
10 headers = {
11     'User-Agent':'User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
12 }
13 
14 #--Xpath--
15 
16 """获取每一个房源的网址,参数是分页url"""
17 def get_link(url):
18     html_data = requests.get(url, headers=headers)
19     selector = etree.HTML(html_data.text)
20     infos = selector.xpath('//*[@id="page_list"]/ul/li')
21     for info in infos:
22         link = info.xpath('a[1]/@href')[0].strip()#获取a标签中的href使用@,注意写法
23         #link = link.get('href')
24         #print(link)
25         get_info(link)
26 
27 """判断房东性别"""
28 def sex_is(member):
29     if member == 'member_ico':
30         return ""
31     else:
32         return ""
33 
34 """#获取每一个房源的详细信息,参数url是每个房源的网址"""
35 def get_info(url):
36     html_data = requests.get(url, headers=headers)
37     selector = etree.HTML(html_data.text)
38     # title = selector.xpath('//div[3]/div[1]/div[1]/h4/em')#直接使用copyxpath的结果为空,原因未知,address字段同样情况
39     title = selector.xpath('//div[@class="wrap clearfix con_bg"]/div[1]/div[1]/h4/em/text()')[0].strip()
40     # title = selector.xpath('//div[@class="pho_info"]/h4/em/text()')[0].strip()
41     address = selector.xpath('//div[@class="pho_info"]/p/span/text()')[0].strip()
42     price = selector.xpath('//*[@id="pricePart"]/div[1]/span/text()')[0].strip()
43     #name = selector.xpath('//*[@id="floatRightBox"]/div[3]/div[2]/h6/a/@title')[0].strip()#此段是直接copy xpath的,某些房源会报错,因为有些房东认证了“超棒房东”,会多一行div
44     name = selector.xpath('//*[@id="floatRightBox"]/div[3]/div[@class="w_240"]/h6/a/@title')[0].strip()
45     #img = selector.xpath('//*[@id="floatRightBox"]/div[3]/div[1]/a/img/@src')[0].strip()#原因同name
46     img = selector.xpath('//*[@id="floatRightBox"]/div[3]/div[@class="member_pic"]/a/img/@src')[0].strip()
47 
48     sex = sex_is(selector.xpath('//*[@id="floatRightBox"]/div[3]/div[1]/div/@class')[0].strip())
49     #将详细数据整理成字典格式
50     data = {
51         '标题':title,
52         '地址':address,
53         '价格':price,
54         '房东姓名':name,
55         '房东性别':sex,
56         '房东头像':img
57     }
58     print(data)
59 
60 
61 """程序主入口"""
62 if __name__=='__main__':
63     start = time.time()
64     for number in range(1,4):
65         url = 'http://bj.xiaozhu.com/search-duanzufang-p{}-0/'.format(number)   #构造分页url(不是房源详情的url)
66         get_link(url)
67         time.sleep(5)
68     end = time.time()
69     print('运行时长:',end-start)

 

对比时间效率

爬取1-3页数据,每页延时5s

BeautifulSoup用时27.9475s

XPath用时24.0693s

 

综上所述

XPath用时更短一些,并且XPath写法更简洁。对比而言,更推荐使用XPath进行网页解析。

值得注意的是,copy XPath的方法虽然好用,但是某些情况有可能抓取失败,比如本例中的title、name和img,此时需要手写(可以尝试明确class和id的写法提高抓取效率)

 

posted @ 2018-11-12 17:37  aby321  阅读(983)  评论(0编辑  收藏  举报