zoukankan      html  css  js  c++  java
  • 多进程爬取58同城二手市场

    github网址:

    https://github.com/factsbenchmarks/58-.git

    58同城二手市场官网,以北京为例:http://bj.58.com/sale.shtml

    通过查看前端代码,可以看出,每一类商品都是在 http://bj.58.com/ 后面加上相关英文字符。比如查找苹果手机,其url是 http://bj.58.com/iphonesj/

    拼接的字符可以从前端查到。

    <span>
                        <a href="/iphonesj/">苹果</a>
                        <a href="/sanxing/">三星</a>
                        <a href="/xiaomi/">小米</a>
                        <a href="/huaweisj/">华为</a>
                        <a href="/oppo/">OPPO</a>
                        <a href="/vivo/">VIVO</a>
                        <a href="/meizu/">魅族</a>
                        <a href="/kupaisj/">酷派</a>
                        <a href="/lianxiang/">联想</a>
                        <a href="/zhongxingshouji/">中兴</a>
                        <a href="/motuoluola/">摩托罗拉</a>
                        <a href="/nuojiya/">诺基亚</a>
                        <a href="/ailixin/">索尼</a>
                        <a href="/heimei/">黑莓</a>
                      <span>
                    </span></span>

    函数一:

      分析前端代码,爬取所有的二手商品的主页,保存到mongodb中。

    import requests
    from bs4 import BeautifulSoup
    import time
    import pymongo
    client = pymongo.MongoClient('localhost',27017)
    db = client['58city']
    col = db['base_url']
    base_url = 'http://bj.58.com/sale.shtml'
    headers = {
            'Referer':'http://bj.58.com/',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
    }
    
    def get_type_base_url(url):
        '''
        爬取每类商品的主页,存储在mongodb中。
        :param url: 58同城首页
        :return: None
        '''
        r = requests.get(url, headers=headers)
        soup = BeautifulSoup(r.text, 'lxml')
        item_lists = soup.select('ul.ym-submnu > li > span > a')
        for item in item_lists:
            item_type_base_url = 'http://bj.58.com' + item.get('href')
            item_type_name = item.get_text()
            col.insert_one({'item_type_name': item_type_name,'item_type_base_url':item_type_base_url})  # 插入字典格式
    
    get_type_base_url(base_url)

      mongodb中存储的数据如下:

      

    函数二:获取某类商品某个页码中的所有商品的的url。

      每一类商品,都有好几页来显示,有的甚至有数十页码。

      比如。http://bj.58.com/iphonesj/pn2/,区分之处在于每一类商品后加 pn,pn后的数字表示页码数。

      在每页中,都有数十个商品。

      这个函数需要的参数是:某类商品的主页,某个page页码。

    import requests
    from bs4 import BeautifulSoup
    import pymongo
    import hashlib
    flag = '很抱歉,没有找到相关信息'
    client = pymongo.MongoClient('localhost',27017)
    db = client['58city']
    col = db['base_url']
    col_detail_url = db['detail_url']
    col_detail_info = db['detail_info']
    
    headers = {
            'Referer':'http://bj.58.com/',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
    }
    
    def get_detail_url(base_url,page):
        '''
        传入base_url,传入某个页码,返回当前这个页码的所有的detail的url,并保存到mongodb中。
        :param base_url:
        :param page:
        :return:
        '''
        url = base_url + 'pn{}'.format(page)
        r = requests.get(url)
        if flag in r.text:   # 某类商品的某页,可能不存在。判断,58同城服务器有没有这个页面。
            pass
        else:
            soup = BeautifulSoup(r.text,'lxml')
            detail_as = soup.select('td.t > a')
            for item in detail_as:
                detail_url = item.get('href')
                if detail_url.startswith('http://zhuanzhuan.58.com'):  # 排除干扰项
                    col_detail_url.insert_one({'detail_url':detail_url})

    函数三 :拿到具体某个商品的url,爬取想要的信息。比如,价格,区域,标题,描述等等

        这个函数需要的参数,某个商品的url。

    import requests
    from bs4 import BeautifulSoup
    import pymongo
    import hashlib
    flag = '很抱歉,没有找到相关信息'
    client = pymongo.MongoClient('localhost',27017)
    db = client['58city']
    col = db['base_url']
    col_detail_url = db['detail_url']
    col_detail_info = db['detail_info']
    
    headers = {
            'Referer':'http://bj.58.com/',
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
    }
    
    def get_detail_info(url):
        '''
        爬取某个商品的想象信息,并保存到mongodb中,
        :param url:
        :return:
        '''
        r = requests.get(url, headers=headers)
        soup = BeautifulSoup(r.text, 'lxml')
        title = soup.find('h1', class_='info_titile').get_text() if soup.find('h1', class_='info_titile') else None
        price = soup.select('span.price_now > i')[0].get_text() if soup.select('span.price_now > i') else None
        zone = soup.select('div.palce_li > span > i')[0].get_text() if soup.select('div.palce_li > span > i') else None
        desc = soup.select('div.baby_kuang > p')[0].get_text() if soup.select('div.baby_kuang > p') else None
        detailurl = url
        if title or price or zone or desc:
            col_detail_info.insert_one({'title': title, 'price': price, 'zone': zone, 'desc': desc, 'detailurl': detailurl})

    函数四:利用多进程加快爬取。

      以上三个函数,该有的都有了。为了更快速的爬取,需要用到多进程Pool的map方法。

      注意,函数二  get_detail_url ,仅仅只是爬取到了某类商品某一页 显示的所有的商品的url,而这很明显是不够的。我们需要爬取的是所有类商品的,很多页的商品的详细信息。

      所有商品,其主页url,函数一已经拿到了。很多页,多少页,可以自己确定。想爬20页就20页,想100页就100页。

      

      map方法的官方说明:

        def map(self, func, iterable, chunksize=None):
            '''
            Apply `func` to each element in `iterable`, collecting the results
            in a list that is returned.
            '''
            return self._map_async(func, iterable, mapstar, chunksize).get()

      第一个参数是一个函数,第二个参数是一个可迭代对象。基于此,我们构建一个函数和一个可迭代对象。

      这个函数是爬取某类商品的全部前N页,这个可迭代对象是将函数一get_type_base_url爬下来的 所有类商品的主页,构成的列表。

    from multiprocessing import Pool
    import os
    from get_itembaseurl import get_type_base_url
    from parse import get_detail_info,get_detail_url
    client = pymongo.MongoClient('localhost',27017)
    db = client['58city']
    col = db['base_url']
    base_urls = []
    for item in col.find():
        base_urls.append(item['item_type_base_url'])
    
    
    def get_all_detail_url(base_url):
        '''
        调用get_detail_url函数,爬取某种商品的的前N页所有商品的url。
        :param base_url: 
        :return: 
        '''
        for i in range(1,10):
            get_detail_url(base_url,i)
    
    if __name__ == '__main__':
        p = Pool()
        p.map(get_all_detail_url,base_urls)
        p.close()
        p.join()

    函数五

      定义一个函数,实时监测爬取的保存到mongodb中的的数据的数量。

    import pymongo
    import time
    client = pymongo.MongoClient('localhost',27017)
    db = client['58city']
    col = db['detail_url']
    while True:
        print(col.find().count())
        time.sleep(5)

      

  • 相关阅读:
    E
    牛客比赛—身体训练
    前缀和例题
    欧拉函数模板
    3.30训练题
    poj1321棋盘问题
    记set学习
    B. K-th Beautiful String
    codeforces1293C
    LightOJ 1370 Bi-shoe and Phi-shoe
  • 原文地址:https://www.cnblogs.com/654321cc/p/8778196.html
Copyright © 2011-2022 走看看