首页 > 技术文章 > 爬虫基础知识-利用beautifulsoup&xpath爬取房源信息

pythonbird 2018-09-07 17:49 原文

闲暇之余,写一些关于爬虫方面的知识,顺便也巩固下自己的知识,也欢迎大神给我点建议:

  1. 爬虫的定义(直接套用百度百科上的定义):网络爬虫(又被称为网页蜘蛛,网络机器人,网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。
  2. 爬虫所用的语言以及一些好用的第三方库:
    1. 语言:python,因为学的就是Python,其他的语言也不会啊,环境配置强烈要求anaconda+pycharm,不然在安装第三方库的过程中各种报错会让你崩溃的(本人深受其害)。
    2.  第三方库以及本地库:访问指定url 时候需要用到的requests库,本人觉得它比Python自带的urllib2好用太多,强烈要求用requests,解析过程中一般会用到beautifulsoup和xpath,正则表达式其实也可以,但是对于小白来说有点不太友好,而且以上两个库对于一般的来说已经足够了。

目的:本文用的是链家网站来做例子,旨在爬取出链家网站北京地区的所有二手房源基本信息以及总价。

 

一 :对指定网站进行访问:

不建议用urllib2,比较繁琐,直接用第三方库requests.

       requests库:

如何安装:由于是第三方库,直接用进入cmd终端,然后 pip install requests。

官方文档:http://www.python-requests.org/en/master/

对指定url 进行基本的get请求:

import requests
url = "https://bj.lianjia.com/ershoufang/"#链家网址的二手房界面
response = requests.get(url)#对网址进行get请求
print(response.text)

另外关于get请求,还有额外一个小知识点,可以先将参数填写在dict中,发起请求时params参数指定为dict

import requests

data = {
    'name': 'tom',
    'age': 20
}

response = requests.get('http://httpbin.org/get', params=data)
print(response.text)

 

二: 对指定网站进行解析以及把内容读写进csv文件中

 

关于浏览器,我推荐用chrome浏览器,对于解析源码十分方便。

进入调试界面: f12,然后点下调试界面左上角的带箭头的标记。

 

第一种方法:

利用beautifulsoup来进行解析:

官方文档:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/(粗浅看一下即可,我认真看完也忘的差不多了)

崔庆才关于beautifulsoup的整理:https://cuiqingcai.com/1319.html(推荐看崔大神这个,条理清晰,没有官方文档那么啰嗦@_@,说完我又看了一遍压压惊)

另外你需要了解一点关于前端的知识,不需要太精通,否则会入前端的坑。。。。。

 

解析正文: 

 

 我们看到总共有一百页,所以先生成一个一百页的url地址来.

观察url :第一页:https://bj.lianjia.com/ershoufang/

    第二页:https://bj.lianjia.com/ershoufang/pg2/

    第三页:https://bj.lianjia.com/ershoufang/pg3/

好的,看出规律来了,所以第n页应该是https://bj.lianjia.com/ershoufang/pgn/, 代码直接用for循环来生成100个就行

 

        for i in range(1, 101):   #生成100页
            page_url = url + "pg" + str(i)    #这就生成了100页的url地址

 

 

 

接下来就解析每一页的内容:

现在我们因该明确我们想要提取的信息,此处我们提取的第一个信息是房源基本信息:

 可以看到所有信息都在属性为houseInfo的div标签中:

生成beautifulsoup 对象

sp = BeautifulSoup(page_html.text, "lxml") #beautifulsoup固定用法,文档里面有

 

接下里提取房源信息:

        houseinfoes = sp.find_all("div", class_="houseInfo")
        L1 = []
        for i in houseinfoes:
            houseinfo = i.get_text() # get_text()方法旨在获取标签内的文本内容
            L1.append(houseinfo)

 

 这样的话基本房源信息被存储在L1列表中。

 

第二个要提取的信息是房子的总价:

在属性为priceInfo的div标签中

接着用上面创建好的beautifulsoup 对象

        L2 = []
        priceinfoes = sp.find_all("div",class_="priceInfo")
        for a in priceinfoes:
            priceinfo = float(a.span.string)
            L2.append(priceinfo)

 

 

到此我们需要的信息就提取完毕,但是我们怎么样把两个列表一对一放在一起?不用担心,直接用zip()来解决:

d = dict(zip(L1, L2))

 所有信息被存储在字典d中,接下来将这些信息写入csv文件中:

创建csv文件需要用到csv模块,指定路径需要用到os模块

import csv
import os
path = "D:\数据分析\草稿\测试"    #指定电脑里面的一个路径
os.chdir(path)    # 切换工作路径为指定的path
with open("lianjia.csv", "a", newline="") as myfile: #需要设置newline,否则csv文件中会出现空行
    mywriter = csv.writer(myfile)
    for k in d:
        mywriter.writerow([k, d[k]]) # 将指定信息逐行写入csv文件中

好了,至此大功告成,整体源码如下,我对原代码封装了一下,又加了一些提示语,使其更显的条理些,更清楚些:

import requests
from bs4 import BeautifulSoup
import os
import csv

class Lianjia():
    def __init__(self):
      #设置下UA代理,简单伪装下自己的爬虫 self.headers
= {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"} def all_page_url(self, url): for i in range(1, 101): #生成100页 page_url = url + "pg" + str(i) #这就生成了100页的url地址 print("开始下载第%d"%i) self.one_page(page_url) print("Done") def request(self, page_url): content = requests.get(page_url,headers=self.headers) return content def one_page(self, page_url): page_html = self.request(page_url) sp = BeautifulSoup(page_html.text, "lxml") #beautifulsoup固定用法,文档里面有 houseinfoes = sp.find_all("div", class_="houseInfo") L1 = [] for i in houseinfoes: houseinfo = i.get_text() L1.append(houseinfo) L2 = [] priceinfoes = sp.find_all("div",class_="priceInfo") for a in priceinfoes: priceinfo = float(a.span.string) L2.append(priceinfo) d = dict(zip(L1, L2)) self.save(d) def save(self,d): path = "D:\数据分析\草稿\测试" # 指定电脑里面的一个路径 os.chdir(path) # 切换工作路径为指定的path with open("lian.csv", "a", newline="") as file: # 需要设置newline,否则csv文件中会出现空行 mywriter = csv.writer(file) for k in d: mywriter.writerow([k, d[k]]) # 将指定信息逐行写入csv文件中 lianjia = Lianjia() lianjia.all_page_url("https://bj.lianjia.com/ershoufang/")

总共有3000条房源信息以及它们的价格,爬虫果然很强大。

第二种方法:

利用xpath对页面进行解析,提取我们所需要的信息,前后代码大同小异,我就懒的再重新写,只把中间提取信息的代码重新用xpath来写一下。

官方文档:http://www.w3school.com.cn/xpath/index.asp

关于xpath提取页面内容,chrome浏览器的一个插件xpath helper(需要登陆谷歌商店,百度上搜索下文件,很多),此插件可以随意调试你的xpath表达式,很方便。

而且你不会写xpath语法的,chrome上有个copy xpath的功能,对新手小白很友好。。。。。。。。。。。。。。。。。

解析网页以及提取指定信息的步骤(不想写了,直接上代码):

        page_html = self.request(page_url)
        selector = etree.HTML(page_html.text)  #解析网页
        houseinfoes = selector.xpath("//li[@class='clear LOGCLICKDATA']")#提取所有的li标签
        d = {}
        for each in houseinfoes:
            d["name"] = each.xpath(".//div[@class='houseInfo']/a/text()")[0]
            d["price"] = each.xpath('.//div[@class="totalPrice"]/span/text()')[0]

 

下面是源码:

import requests
from lxml import etree
import csv
import os


class Lianjia():
    def __init__(self):
        self.headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"}

    def all_page_url(self, url):
        for i in range(1, 101):   #生成100页
            page_url = url + "pg" + str(i)    #这就生成了100页的url地址
            print("开始下载第%d"%i)
            self.one_page(page_url)
        print("Done")

    def request(self, page_url):
        content = requests.get(page_url,headers=self.headers)
        return content

    def one_page(self, page_url):
        page_html = self.request(page_url)
        selector = etree.HTML(page_html.text)  #利用xpath解析网页
        houseinfoes = selector.xpath("//li[@class='clear LOGCLICKDATA']")#提取所有的li标签
        d = {}
        for each in houseinfoes:
            d["name"] = each.xpath(".//div[@class='houseInfo']/a/text()")[0]
            d["price"] = each.xpath('.//div[@class="totalPrice"]/span/text()')[0]
        self.save(d)

    def save(self,d):

        path = "D:\数据分析\草稿\测试"  # 指定电脑里面的一个路径
        os.chdir(path)  # 切换工作路径为指定的path
        with open("lian1.csv", "a",newline="") as file:  # 需要设置newline,否则csv文件中会出现空行
            mywriter = csv.writer(file)
            for k in d:
                mywriter.writerow([k, d[k]])  # 将指定信息逐行写入csv文件中

lianjia = Lianjia()
lianjia.all_page_url("https://bj.lianjia.com/ershoufang/")

 

 结语:也希望自己能在Python的道路上走下去,代码的优化以及不足也希望看到的有缘人提出来吧。。。。。

下一篇博客用scrapy爬虫框架来爬取链家房源信息(链家官网好可怜。。。。。。)

推荐阅读