用Python的request库爬取某当书城数据

        最近读了一本书叫大明第一清官海瑞,所以打算再买一本书,所以就去当当网看了一些和张居正的数据,但是数据太多,所以就想用爬虫爬取一下。

页面分析

首先对我们需要访问的url进行访问

由响应码可知请求数据成功,当当书城中不加请求头,也能请求成功,接着可以打印一些响应内容看看页面是否有我们想要的数据,

 由响应的内容可以知道,响应回来的页面数据,有我们需要的,那么接下来需要的就是解析

页面解析

像这种ul下面的数据,就是先获取所有的li标签然后再逐一拿取li中的数据,这里我们使用的是lxml库中的xpath语法规则

et = etree.HTML(rep.text)
        li_list = et.xpath("//ul[@class='bigimg']/li")
        # print(len(li_list)) #检查数据条数
        for li in li_list:
            # 书籍序号
            book_no = li.xpath("./@ddt-pit")
            # 书籍名称
            book_name = ''.join(li.xpath("./p[1]/a//text()"))
            # 书籍url
            book_img_src = li.xpath("./a[1]/img/@src")
            book_img = li.xpath("./a[1]/img/@data-original")
            if len(book_img)==0:
                book_img = book_img_src
            # 书籍作者
            book_author = li.xpath("./p[@class='search_book_author']/span[1]/a/text()")
            # 出版时间
            book_time = li.xpath("./p[@class='search_book_author']/span[2]/text()")
            # 出版社
            book_press = li.xpath("./p[@class='search_book_author']/span[3]/a/text()")
            # 书籍价格
            book_price = li.xpath("./p[@class='price']/span[1]/text()")
            # 书籍介绍
            book_detail = li.xpath("./p[@class='detail']/text()")

这样就能拿到数据了,但是我们不止爬取一个页面,需要爬取多个页面,那么我们就需要去发现一个规律看看页面怎么变化的。

当点击第二页的时候,发现url多了一个请求参数,再多点几个页面的时候发现,就是这个参数在控制页面,那么我们就可以利用for循环来改变请求的url

for i in range(1,100):
            t.submit(get_dang_dang,f"https://search.dangdang.com/?key=%D5%C5%BE%D3%D5%FD&act=input&page_index={i}",i).add_done_callback(count_page)

为了提高速度我们采用了多线程把请求url放到线程池中去,add_done_callback(count_page)是为了得到解析过后的返回值

#输出每页数据
def count_page(res):
    print(res.result())
    return res.result()

 我们对解析后的数据做了封装,解析完一个书籍就封装成字典类型添加到一个列表中,这样解析完一个页面就会将这个页面的所有数据返回。

#发送网络请求
def get_dang_dang(url,page_num):
    book_list=[]
    book_list.append(f"第{page_num}页")
    rep=requests.get(url)
    if rep.status_code==200:    
        # print(rep.status_code)
        # 打印响应内容
        # print(rep.text) #爬取内容存在返回数据中
        et = etree.HTML(rep.text)
        li_list = et.xpath("//ul[@class='bigimg']/li")
        # print(len(li_list)) #检查数据条数
        for li in li_list:
            # 书籍序号
            book_no = li.xpath("./@ddt-pit")
            # 书籍名称
            book_name = ''.join(li.xpath("./p[1]/a//text()"))
            # 书籍url
            book_img_src = li.xpath("./a[1]/img/@src")
            book_img = li.xpath("./a[1]/img/@data-original")
            if len(book_img)==0:
                book_img = book_img_src
            # 书籍作者
            book_author = li.xpath("./p[@class='search_book_author']/span[1]/a/text()")
            # 出版时间
            book_time = li.xpath("./p[@class='search_book_author']/span[2]/text()")
            # 出版社
            book_press = li.xpath("./p[@class='search_book_author']/span[3]/a/text()")
            # 书籍价格
            book_price = li.xpath("./p[@class='price']/span[1]/text()")
            # 书籍介绍
            book_detail = li.xpath("./p[@class='detail']/text()")
            # 书籍信息封装
            dic ={
                "book_name":book_name,
                "book_img" :"http:"+book_img[0],
                "book_author" : ';'.join(book_author),
                "book_time" : "".join(book_time),
                "book_press" : "".join(book_press),
                "book_price" : "".join(book_price),
                "book_detail" : "".join(book_detail)
            }
            book_list.append(dic)
            # print(dic)
    else:
        print("url不存在请求失败")
    return book_list

爬取成功

完整代码展示 

 

#发送网络请求
def get_dang_dang(url,page_num):
    book_list=[]
    book_list.append(f"第{page_num}页")
    rep=requests.get(url)
    if rep.status_code==200:    
        # print(rep.status_code)
        # 打印响应内容
        # print(rep.text) #爬取内容存在返回数据中
        et = etree.HTML(rep.text)
        li_list = et.xpath("//ul[@class='bigimg']/li")
        # print(len(li_list)) #检查数据条数
        for li in li_list:
            # 书籍序号
            book_no = li.xpath("./@ddt-pit")
            # 书籍名称
            book_name = ''.join(li.xpath("./p[1]/a//text()"))
            # 书籍url
            book_img_src = li.xpath("./a[1]/img/@src")
            book_img = li.xpath("./a[1]/img/@data-original")
            if len(book_img)==0:
                book_img = book_img_src
            # 书籍作者
            book_author = li.xpath("./p[@class='search_book_author']/span[1]/a/text()")
            # 出版时间
            book_time = li.xpath("./p[@class='search_book_author']/span[2]/text()")
            # 出版社
            book_press = li.xpath("./p[@class='search_book_author']/span[3]/a/text()")
            # 书籍价格
            book_price = li.xpath("./p[@class='price']/span[1]/text()")
            # 书籍介绍
            book_detail = li.xpath("./p[@class='detail']/text()")
            # 书籍信息封装
            dic ={
                "book_name":book_name,
                "book_img" :"http:"+book_img[0],
                "book_author" : ';'.join(book_author),
                "book_time" : "".join(book_time),
                "book_press" : "".join(book_press),
                "book_price" : "".join(book_price),
                "book_detail" : "".join(book_detail)
            }
            book_list.append(dic)
            # print(dic)
    else:
        print("url不存在请求失败")
    return book_list
#下载书籍
def download_img(res):
    for dic in res.result()[1:]:
        print(dic["book_img"])

#输出每页数据
def count_page(res):
    print(res.result())
    return res.result()

#第一页测试
def test_page():
    book_list = get_dang_dang("https://search.dangdang.com/?key=%D5%C5%BE%D3%D5%FD&act=input&page_index=1",1)
    for dic in book_list[1:]:
        print(dic["book_img"])

if __name__ =="__main__":
    # test_page()
    with ThreadPoolExecutor(50) as t:
        for i in range(1,100):
            t.submit(get_dang_dang,f"https://search.dangdang.com/?key=
            %D5%C5%BE%D3%D5%FD&act=input&page_index={i}",i).add_done_callback(count_page)

         代码还有可以完善的地方,页面数量是由我们自己定的其实页还有其他办法,比如去获取最后一页数值,作为循环的参数,也可以加入协程,还有就是数据没有保存,按照我返回的这种数据格式建议保存为json数据格式。

欢迎关注微信公众号,定期推送干货

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值