Python3爬虫(2)xpath模块代替re正则模块的使用

时间:2022-03-30 22:32:59

前言


最近学习了一下python3.5中爬虫的原理套路!

之前写demo的时候,获取html源码后一直在使用python自带的re模块来用正则表达式匹配数据。

不得不说!正则很强大!(强大的.*?,笑),各种复杂的情况下都可以匹配的到,但是写法非常灵活,每个人的思维模式不一样,写出来也就不一样,对于没有接触过正则表达的同学来说,学习成本还是需要一写的!


所以今天来说一下对于我这种正则小白的福音!python下提供的一个基于正则的模块,xpath,使用节点的概念来匹配你所获取到的页面源码!超级好用!

[xpath菜鸟教程学习传送门]:点击打开链接


今天用xpath写了一发get 58同城租房信息的demo,下面附上流程和code




A.实现思路


58同城首页->租房->北京出租

首先我们得到的是一个这样的页面

Python3爬虫(2)xpath模块代替re正则模块的使用



点进去之后得到这样一个页面

Python3爬虫(2)xpath模块代替re正则模块的使用


那么我们爬取信息的套路就可以初步确定下来了!

1.首先在房源信息列表页面循环分页获取到每篇独立的房源帖子url,也就是a标签中的href。

2.接着我们需要循环向这些帖子的url发起网络请求(使用requests模块或自带urllib模块都可以啦~)获取每篇帖子的html源码

3.获取每篇帖子的源码后!我们就可以分析源码的结构,然后使用xpath(代码中实际引用的是lxml这个文件)进行匹配数据,获取到我们需要的信息了!

4.获取每个房源的信息,并把图片都存储下来!




B.获取到的数据


1.房源json信息

Python3爬虫(2)xpath模块代替re正则模块的使用

2.房源图片的存储

Python3爬虫(2)xpath模块代替re正则模块的使用




C.实现代码


from urllib import request
#lxml就是xpath的模块
from lxml import etree
import requests,json,time

#爬取一级列表网页信息
def get_pages(page_num):
    #确认目标
    target = 'http://bj.58.com/chuzu/?PGTID=0d3090a7-0000-1299-6863-0094cd8364e7&ClickID={}'.format(page_num)
    #发起网络请求
    response = requests.get(target)
    response.encoding = 'utf-8'
    #获取html源码
    html = response.text

    #使用lxml进行数据匹配
    html = etree.HTML(html)

    #获取房源信息,进入单个帖子的url
    url_lists = html.xpath('//div[@class="listBox"]//h2//@href')

    for url in url_lists:
        get_page_info(url)
        time.sleep(2)

#爬取二级详情页面信息
def get_page_info(url):
    response = requests.get(url)
    response.encoding = 'utf-8'
    page_code = response.text

    #储存房源信息dict house_info
    house_info = {}
    html = etree.HTML(page_code)

    #房源信息标题
    title = html.xpath('//div[@class="house-title"]/h1/text()')
    if title:
        house_info['title'] = title[0]
    #月租
    pay_month = html.xpath('//div[@class="house-pay-way f16"]//b/text()')
    if pay_month:
        house_info['pay_month'] = pay_month[0]
    #租赁方式
    pay_type = html.xpath('//ul[@class="f14"]/li[1]/span[2]/text()')
    if pay_type:
        house_info['pay_type'] = pay_type[0]
    #房屋类型
    house_type = html.xpath('//ul[@class="f14"]/li[2]/span[2]/text()')
    if house_type:
        house_info['house_type'] = house_type[0].strip()
    #朝向楼层
    house_dxnb = html.xpath('//ul[@class="f14"]/li[3]/span[2]/text()')
    if house_dxnb:
        house_info['house_dxnb'] = house_dxnb[0]
    #所属区域
    house_location = html.xpath('//ul[@class="f14"]/li[4]/span[2]/text()')
    if house_location:
        house_info['house_location'] = house_location[0]
    #详细地址
    house_adress = html.xpath('//ul[@class="f14"]/li[6]/span[2]/text()')
    if house_adress:
        house_info['house_adress'] = house_adress[0].strip()
    #销售员名称
    agent_name = html.xpath('//p[@class="agent-name f16 pr"]//text()')
    if agent_name:
        house_info['agent_name'] = agent_name[0].strip()
    #销售员电话
    agent_phone = html.xpath('//span[@class="house-chat-txt"]/text()')
    if agent_phone:
        house_info['agent_phone'] = agent_phone[0]
    #房屋特点
    house_special = html.xpath('//ul[@class="introduce-item"]/li[1]//span[2]/em/text()')
    if house_special:
        house_info['house_special'] = house_special
    #房源描述
    house_des = html.xpath('//ul[@class="introduce-item"]/li[2]//p/span/text()')
    if house_des:
        house_info['house_des'] = house_des
    #房屋描述图片
    pic_urls = html.xpath('//ul[@id="housePicList"]/li/img/@lazy_src')

    #循环截取出图片的名称
    img_list = []
    for url in pic_urls:
        first_url = url.split('?')
        pic_name = first_url[0].split('/')[-1] + '.jpg'
        img_list.append(pic_name)

        #图片名称存入house_info中
        house_info['house_imgs'] = img_list

        #下载图片
        request.urlretrieve(url,'./images/'+ pic_name)

    with open('./house.json','a',encoding='utf-8') as f:
        #json.dumps()-> dict转json
        f.write(json.dumps(house_info,ensure_ascii=False) + '\n')


    #打印结果
    print(house_info)

if __name__ == '__main__':
    #循环页数
    for page_num in range(1,2):
        get_pages(page_num)




D.注意事项


1.demo中只爬取了一页的房源信息,如需更改请修改主进程中的for in循环range值

2.如果有使用fiddler或者Charless这样抓包工具的同学,在跑demo的时候请先关闭一下,否则会报一个http error 504的错误

[http error 504 大神错误解决方案传送门]:点击打开链接