前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >爬取58同城二手手机

爬取58同城二手手机

作者头像
溪初桾
发布2020-03-12 16:21:10
5660
发布2020-03-12 16:21:10
举报
文章被收录于专栏:溪溪技术专栏溪溪技术专栏
  1. 在开始编写代码前需要将Python3.7安装并配置于环境变量中(windows一般安装python环境后会自动添加进环境变量),以及使用pip命令安装上面提到的3个python库,这些都准备好以后开始使用PyCharm或者Sublime Text 3编写代码,这里我习惯于使用PyCharm编写python代码。
  2. 进入58同城的二手手机页面https://gy.58.com/shouji/ ,使用浏览器的开发者工具(直接按F12键即可)寻找页面规律。爬去58同城二手手机的数据。
  • 使用shift+ctrl+c选取页面标题元素,获取选中的url链接,查找页面规律 点击标题后右边会跳转到对应的代码位置,通过点击多个列表得出结论,所有我们需要的url列表都在class为t的td标签下,而且对于的还有2种不同的地址,得到了页面规律后,我们就可以使用
  • 得到了上述的规律后,第一步我们需要先获取页面的html源代码,这里需要使用requests类,通过开发者工具的Network(网络),选中当前页面的Headers选项卡获取当前页面的HTTP请求头 获取http请求头以后使用python构造headers,并通过requests携带请求头headers访问https://gy.58.com/shouji/页面以及商品详情页面如https://hhpcpost.58.com/shouji/37346885041936x.shtm 等地址,这里我为了使用方便写了一个方法get_web_data()用于获取网页html代码
  • 获取url列表,通过上面的分析我们找到了url的规律,然后可以使用soup的select方法筛选元素,获取所有class为t的td标签下的a标签。示例如下 urls = soup.select('td.t > a') 然后使用get()方法获取href属性,在获取链接的时候由于url有2种,并且页面布局完全不同,所以需要使用字符串分片的方式判断url链接的类型并且将2种url分为2个list存放,便于下一步的爬去
  • 获取页面数据标题、价格、描述信息、图片地址,由于58同城商品详情页面分为2种,需要分别为2种页面写不同的方法来获取页面信息。获取https://gy.58.com/shouji/37378994974604x.shtml 页面数据 同样通过开发者工具选取页面元素选取标题得到对应的位置, div.detail-info-hd > div.detail-info-tit并且使用strip()方法去除文本两边的空格以及换行符,使用同样的方法得到价格、区域以及描述信息。获取图片地址,在描述信息下方有商品的图片,使用开发者工具选取一张图片获得图片地址,寻找图片规律,所有图片在li标签下面的span标签中
  • 另一种页面的内容获取方式与上面的方法一致,只需要修改select方法选择对应元素。
  • 最后写一个main()方法遍历两个list中的地址分别访问对应的页面,并将获取到的数据存入MongoDb数据库

源代码

代码语言:javascript
复制
 from bs4 import BeautifulSoup
import requests
import pymongo
import re


# 封装requests,获取WEB页面数据
def get_web_data(url):
    # 构造请求头
    headers = {
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'max-age=0',
        'user-agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
    }
    data = requests.get(url, headers=headers)
    return data


# 通过页面爬去所有的详情页url
def get_urls(page_url):
    try:
        data = get_web_data(page_url)
        # 保存地址
        url_hhpcpost = []
        url_gy = []
        # 判断网页是否访问成功
        if data.status_code == 200:
            soup = BeautifulSoup(data.text, 'lxml')
            urls = soup.select('td.t > a')
            # urls = soup.select('div.ac_linkurl > a')
            for url in urls:
                # 获取a标签中的href属性
                url = url.get('href')
                # 判断url类型并且保存到列表中
                if url[2:10] == 'hhpcpost':
                    url_hhpcpost.append('https:' + url)
                if url[8:10] == 'gy':
                    url_gy.append(url)
        else:
            print(page_url + 'access failed!' + 'status_code:' + str(data.status_code))
    except Exception as e:
        print(e)
    finally:
        return url_gy, url_hhpcpost


# 获取二手商品信息
def get_shouji_info_gy(url):
    info = []
    try:
        # 判断网页内容是否获取成功若状态码为200则页面访问成功
        data = get_web_data(url)
        if data.status_code == 200:
            soup = BeautifulSoup(data.text, 'lxml')
            # 获取标题 并去除2边的换行符以及空白符
            title = soup.select('div.detail-title > h1')[0].get_text().strip()

            # 获取价格
            price = soup.select('div.infocard__container__item__main > span')[0].get_text().strip()

            # 使用正则表达式提取价格数字
            prices = re.search('\\d+', price)[0]

            # 区域
            areas = soup.select(
                'div.infocard__container.haveswitch > div:nth-of-type(2) > div.infocard__container__item__main>a')
            area = ''
            for i in areas:
                area = area + i.get_text().strip()

            # 描述信息
            description = soup.select('div.foldingbox > article.description_con')[0].get_text().strip()

            # 获取图片
            imgs = soup.select('li > span > img')
            pics = []
            for pic in imgs:
                pics.append('https:' + pic.get('src'))

            info = {
                'title': title,
                'prices': prices,
                'area': area,
                'description': description,
                'pics': pics
            }
    except Exception as e:
        print(e)
        print(url)
    finally:
        return info


# 获取二手商品信息
def get_shouji_info_hhpcpost(url):
    info = []
    try:
        # 判断网页内容是否获取成功若状态码为200则页面访问成功
        data = get_web_data(url)
        if data.status_code == 200:
            soup = BeautifulSoup(data.text, 'lxml')
            # 获取标题 并去除2边的换行符以及空白符
            title = soup.select('div.detail-info-hd > div.detail-info-tit')[0].get_text().strip()

            # 获取价格
            price = soup.select('div.detail-info-hd > div.detail-info-price > span.info-price-money')[
                0].get_text().strip()
            # 使用正则表达式提取价格数字
            prices = re.search('\\d+', price)[0]

            # 区域
            area = soup.select('ul > li:nth-of-type(3) > span.info-bd-text')[0].get_text().strip()

            # 描述信息
            description = soup.select('div.hh-detail-desc-box > div.hh-detail-desc')[0].get_text().strip()

            # 获取图片
            imgs = soup.select('div.hh-detail-small-pic > ul > li')
            pics = []
            for pic in imgs:
                pics.append('https:' + pic.get('data-src'))

            info = {
                'title': title,
                'prices': prices,
                'area': area,
                'description': description,
                'pics': pics
            }
    except Exception as e:
        print(e)
        print(url)
    finally:
        return info


def main():
    try:
        # 连接MongoDB数据库
        myclient = pymongo.MongoClient("mongodb://localhost:27017/")
        mydb = myclient['rs']
        collection = mydb['data_58']

        uri = 'https://gy.58.com/shouji/pn'
        for i in range(1, 29, 1):
            page_url = uri + str(i)
            (url_gy, url_hhpcpost) = get_urls(page_url)
            for url in url_gy:
                data = get_shouji_info_gy(url)
                # 保存数据到MongoDB
                if len(data) > 0:
                    collection.insert_one(data)
                print(data)
            for url in url_hhpcpost:
                data = get_shouji_info_hhpcpost(url)
                if len(data) > 0:
                    collection.insert_one(data)
                print(data)
    except Exception as e:
        print(e)


# print(get_shouji_info_gy('https://gy.58.com/shouji/37378994974604x.shtml?iuType=p_1&PGTID=0d300024-007d-f012-64a4-30fe82910e2d&ClickID=14'))
# print(get_shouji_info_hhpcpost('https://hhpcpost.58.com/shouji/37350593977988x.shtml?iuType=p_1&PGTID=0d300024-007d-f012-64a4-30fe82910e2d&ClickID=12'))
main()

运行结果

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源代码
  • 运行结果
相关产品与服务
云开发 CLI 工具
云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档