Python爬虫:requests库学习笔记

一、导入常用库:

import requests # 网络请求模块
from bs4 import BeautifulSoup # HTML代码解析模块
import json                    # json数据解析模块
import re                      # 正则表达式模块
from lxml import html        #Xpath表达式

二、随机User-Aget(反爬手段之一,选用):

from fake_useragent import UserAgent
import random

headers={"User-Aget": UserAgent().random}

三、requests库场景:

1、请求静态网页,请求中无参数,返回html格式的内容后用BeautifulSoup解析:

    def get_rankings(self, url):
        # 创建头部信息
        #headers = {'User-Agent': 'OW64; rv:59.0) Gecko/20100101 Firefox/59.0'}#原代码
        headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
        self.book_name_list = []  # 保存图书名称的列表
        self.press_list = []  # 保存出版社的列表
        self.item_url_list = []  # 保存排行中每本图书的地址
        self.jd_id_list = []  # 保存京东id的列表
        # 网页的页数
        page = 1
        # 100个京东id的字符串,该字符串是前100名的京东商品id
        self.jd_id_str_100 = ''
        # 因为前100名,每个网页显示20名,所以发送5次 网页请求,每次请求不同的页数
        while True:
            if page == 6:
                break
            response = requests.get(url.format(page=page),headers= headers)  # 发送网络请求,获取服务器响应
            response.encoding = 'gb2312'  # 设置编码方式
            # 创建一个BeautifulSoup对象,获取页面正文
            html = BeautifulSoup(response.text, "html.parser")
            try:
                #因为热评排行榜的页数是动态变化的,有时不足5页,不足5页的时候拼出来的
                #网址访问后会找不到div节点,再用selcect会抛异常
                book_list = html.find('div', {'class', 'm m-list'}).select('li')  # 获取图书所有信息
            except:
                break
            # print('book_list',len(book_list))
            # 页数价1
            page += 1
            # 每页20个京东id
            jd_id_str_20 = ''
            for i in book_list:
                # 获取图书id
                jd_id = i.find('a', {'class', 'btn btn-default follow'}).get('data-id')
                # 获取图书名称
                book_name = i.find('a', {'class', 'p-name'}).text
                # 获取图书出版社
                press = i.find('div', {'class', 'p-detail'}).find_all('dl')[1].dd.text
                item_url = i.find('div', {'class', 'p-img'}).find('a').get('href')
                item_url = 'http:' + item_url
                self.book_name_list.append(book_name)  # 将图书名称添加至列表
                self.press_list.append(press)  # 将出版社添加至列表
                self.item_url_list.append(item_url)  # 将排行中每本书地址添加至列表
                self.jd_id_list.append(jd_id)  # 将排行中每本书的京东id添加至列表
                # 京东商品id
                jd_id_str = 'J_' + jd_id + ','
                jd_id_str_20 = jd_id_str_20 + jd_id_str
            # 将获取到的100个京东id连接成字符串作为获取价格的请求参数
            self.jd_id_str_100 = self.jd_id_str_100 + jd_id_str_20
        return self.jd_id_str_100

2、请求静态网页,请求中无参数,返回html格式的内容后用Xpath解析:

    def get_heml(self, url):
        #用fake_useragent库产生随机的User-Aget,目的是反爬
        rep = requests.get(url, headers={"User-Aget": UserAgent().random}).text
        # 开始解析,把lxml+Xpath表达式,将结果存入li_lists
        p = html.etree.HTML(rep)
        # li_lists是xpath匹配内容的结果集,保存了符合规则的信息
        #每个li标签节点保存了一个房源的完整信息
        li_lists = p.xpath('//ul[@class="sellListContent"]/li[@class="clear LOGVIEWDATA LOGCLICKDATA"]')
        items = {}
        for li in li_lists:
            # 房名xpath,要判断是否为空,因为后续可能会做数据持久化处理,比如存入数据库
            li_name = li.xpath('.//div[@class="positionInfo"]/a/text()')
            if li_name:
                items["name"] = li_name[0]
            else:
                items["name"] = None
            # 地址xpath
            li_address = li.xpath('.//div[@class="positionInfo"]/a[2]/text()')
            if li_address:
                items["address"] = li_address[0]
            else:
                items["address"] = None
            # 房子详细信息xpath
            li_info = li.xpath('.//div[@class="houseInfo"]/text()')
            if li_info:
                items["info"] = li_info[0]
            else:
                items["info"] = None
            # 房子总价
            li_total = li.xpath('.//div[@class="totalPrice"]/span/text()')
            if li_total:
                items["total"] = li_total[0] + '万'
            else:
                items["total"] = None
            li_unitPrice = li.xpath('.//div[@class="unitPrice"]/span/text()')
            # 房子单价
            if li_total:
                items["unitPrice"] = li_unitPrice[0]
            else:
                items["unitPrice"] = None
            # 打印结果
            print(items)

3、请求的url中需要将参数拼接进去,返回json数据:

    def get_price(self, id):
        rankings_list.clear() # 清空排行数据的列表
        price_url = 'http://p.3.cn/prices/mgets?type=1&skuIds={id_str}' # 获取价格的网络请求地址
        response = requests.get(price_url.format(id_str=id))  # 将京东id作为参数发送获取前100名图书价格
        price = response.json()  # 获取价格json数据,该数据为list类型
        for index, item in enumerate(price):
            # 书名
            book_name = self.book_name_list[index]
            # 出版社
            press = self.press_list[index]
            # 京东价格
            jd_price = item['op']
            # 定价
            ding_price = item['m']
            # 每本书的地址
            item_url = self.item_url_list[index]
            # 每本书的京东id
            jd_id = self.jd_id_list[index]
            # 将所有数据添加到列表中
            rankings_list.append((index+1,book_name, jd_price, ding_price, press, item_url,jd_id))

4、请求包含参数params,返回的内容需要用正则表达式提取json数据:

    def get_evaluation(self, score, id):
        # 好评率
        self.good_rate_show = None
        # 评价请求地址参数,callback为对应书名json的id,
        # productId书名对应的京东id
        # score评价等级参数差评为1、中评为2、好评为3,0为全部
        # sortType类型,6为时间排序,5为推荐排序
        # pageSize每页显示评价10条
        # page页数
        params = {
            'callback': 'fetchJSON_comment98vv10635',
            'productId': id,
            'score': score,
            'sortType': 6,
            'pageSize': 10,
            'isShadowSku': 0,
            'page': 0,
        }
        # 评价请求地址
        url = 'https://club.jd.com/comment/skuProductPageComments.action'
        '''
        完整的请求url是:https://club.jd.com/comment/skuProductPageComments.action
        ?callback=fetchJSON_comment98&productId=11936238&score=0&sortType=6&page=0&pageSize=10&isShadowSku=0&fold=1
        其中?起的是请求参数用&拼接起来,自动完成的,不需要我们自己操作
        '''
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36',
            'Referer': 'https://item.jd.com/12353915.html'}
        # 发送请求
        evaluation_response = requests.get(url, params=params,headers=headers)
        if evaluation_response.status_code == 200:
            evaluation_response = evaluation_response.text
            try:
                # 去除json外层的括号与名称
                #fetchJSON_comment98vv10635({提取后的内容});
                #把“{提取后的内容}”以外的内容去除了
                t = re.search(r'({.*})', evaluation_response).group(0)
            except Exception as e:
                print('评价的json数据匹配异常!')
            j = json.loads(t)  # 加载json数据
            commentSummary = j['comments']
            if self.good_rate_show == None:
                self.good_rate_show = j['productCommentSummary']['goodRateShow']
            for comment in commentSummary:
                # 评价内容
                c_contetn = comment['content']
                # 时间
                c_time = comment['creationTime']
                # 京东昵称
                c_name = comment['nickname']
                # 通过哪种平台购买
                #c_client = comment['userClientShow']
                # 会员级别
                #c_userLevelName = comment['userLevelName']
                # 好评差评 1差评 2-3 中评 4-5好评
                c_score = comment['score']
                # print(
                #     '\n{} {} {} {}  {}\n{}\n'.format(c_name, c_userLevelName, c_time, str(c_score) + '颗星', c_client,
                #                                         c_contetn))
            # 判断没有指定的评价内容时
            if len(commentSummary)==0:
                # 返回好评率与无
                return self.good_rate_show,'无'
            else:
                # 根据不同需求返回不同数据,这里仅返回好评率与最新的评价时间
                return self.good_rate_show, commentSummary[0]['creationTime']

四、其他:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值