一只简单的多线程爬虫,爬取京东网站

时间:2022-02-09 02:59:57
#多线程爬取京东页面
#-*-encoding:utf-8-*-

#导入线程池
from multiprocessing.dummy import Pool as Threadpool
import sys#解决编码问题
import requests
import time
from lxml import etree#解析网页
import json
import pymongo

#手机价格链接
phone_u='https://p.3.cn/prices/mgets?&skuIds=J_'

#获取手机首页内容
def get_html_response(url):
    count=1
    html=requests.get(url,headers=headers)
    #解析网页
    selector=etree.HTML(html.text)
    #每个手机的连接,xpath解析网页只要会写路径就能得到连接 //*[@id="J_goodsList"]/ul/li[1]
    phone_list=selector.xpath('//*[@id="J_goodsList"]/ul/li')#这样就得到了包含手机链接数字的li列表
    for i in phone_list:
        try:
            sku_id=i.xpath('@data-sku')[0]#li标签中获取属性为data-sku的值,即链接的数字值
            #得到真实的每一个手机的url链接
            phone_url='https://item.jd.com/{}.html'.format(str(sku_id))
            # print(phone_url)
            get_phone_data(phone_url,count)
            count+=1
        except Exception as e:
            print(e)
            continue  time.sleep(2)

#获取每一个手机的详细信息
def get_phone_data(phone_url,count):
    #用一个字典来保存手机数据
    phone_dict={}
    html=requests.get(phone_url,headers=headers)
    # 解析网页
    selector = etree.HTML(html.text)
    #通过xpath得到包含手机各种产品信息的ul列表
    phone_infos=selector.xpath('//ul[@class="parameter2 p-parameter-list"]')#找到class是。。。的ul标签
    #获取手机的信息

    for phone in phone_infos:

        #获取商品价格
        phone_number=phone.xpath('li[2]/@title')[0]
        phone_price=get_phone_price(phone_number)


        phone_dict['商品名称']=phone.xpath('li[1]/@title')[0]
        phone_dict['商品编号'] =phone_number
        phone_dict['商品价格']=phone_price
        phone_dict['商品毛重'] = phone.xpath('li[3]/@title')[0]
        phone_dict['商品运存'] = phone.xpath('li[10]/@title')[0]
        print('',count,'条数据提取完毕')
    print(phone_dict)
    save(phone_dict)

#爬取手机的价格信息,价格信息JS动态加载
def get_phone_price(sku_id):
    #获取手机价格的url链接
    phone_url=phone_u+str(sku_id)
    #爬取页面,这是一个js页面
    r=requests.get(phone_url,headers=headers).content
    #页面内容转为json数据格式
    r_json=json.loads(r)
    # # #遍历循环得到json数据格式中的价格
    for i in r_json:
        return (i.get('p'))
    # print(r)
    # print(phone_url)

#将爬取的信息保存到mongodb数据库中
def save(list):
    client=pymongo.MongoClient('localhost')
    db=client['phone_dict']#数据库
    content=db['jd']#数据表
    content.insert(list)#将数据插入保存到数据库中

if __name__=='__main__':

    #全局变量headsers
    headers={
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.108 Safari/537.36 2345Explorer/8.7.0.16013'
    }
    urls=[]
    #初始化十个页面
    for i in range(1,7,2):#页数不为2,全部是单数页
        urls.append('https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=%E6%89%8B%E6%9C%BA&cid2=653&cid3=655&page={}&s=58&click=0'.format(str(i)))

    #创建线程池
    pool=Threadpool(2)
    #线程开始时间
    start_time=time.time()
    #线程开始并将urls列表中的链接一一映射到get_html_response函数中
    pool.map(get_html_response,urls)
    #线程池关闭
    pool.close()
    #主线程等待子线程
    pool.join()
    #结束时间
    end_time=time.time()
    tt=end_time-start_time
    print('共用了',tt,'秒的时间爬取网页')