一、环境搭建

使用到的环境:

  • python3.8.0
  • requests库
  • re库
  • bs4库
  • pycharm

二、简介

代码实现了根据设定的关键字keyword获取相关商品的资源定位符(url),然后批量爬取相关页面的商品信息,另外之所以选择当当网是因为当当网的网页商品信息不是动态加载的,因此可以直接爬取获得,例如京东、拼多多的网页就是动态加载的,博主暂时还不会解析动态加载的页面😅😅😅

三、当当网网页分析

1、分析网页的url规律

首先是分析出当当网的搜索商品的url,浏览器进入当当网主页,在检索栏输入任意的商品关键词,可以看到打开的页面的url链接形式为如下形式:

url = 'http://search.dangdang.com/?key={}&act=input'.format(keyword)     

然后获取页面翻页可以发现这类商品的每一页的url形式为:

url = "http://search.dangdang.com/?key={}&input&page_index={}".format(keyword,page_count)     

分析出了这些规律之后,就可以根据输入的关键词自动生成相应页面的url,然后像服务器发送请求,得到每页的html信息。

2、解析网页html页面

浏览器打开任一网页,打开网页调试工具可以发现,当当网的商品网页分为两类(很奇葩),第一类是书籍类商品的网页,第二类是其他商品。

书籍商品html页面解析

经过调试发现,页面的商品信息都在ul标签下的中li标签中,每个li标签块存放一个商品的所有信息,商品的一些信息例如namepriceauthor等信息又存放在li标签下对应的p标签中,因此解析每个p标签的相关属性信息,就能获得对应的信息。值得一提的是书籍商品页面的ul标签的class属性是"bigmig"。

其他商品html页面解析

其他商品和书籍类商品的商品信息存放的标签块基本相同,唯一不同的是其ul标签的class属性是"bigimg cloth_shoplist",解析类似,只不过要区别得到的ul标签的class属性。

四、代码实现

代码主要包括四个函数:

def getMaxPageCount(keyword):
    # 爬取商品的最大页面数
    try:
        user_agent = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'}
        max_page_count = 0
        url = 'http://search.dangdang.com/?key={}&act=input'.format(keyword)
        rspon = requests.get(url, headers = user_agent)
        rspon.encoding = rspon.apparent_encoding
        rspon.raise_for_status()
    except:
        print("爬取页数失败:", rspon.status_code)
        return max_page_count
    html = BeautifulSoup(rspon.text, "html.parser")
    ul_tag = html.find('ul', {"name":"Fy"})
    for child in ul_tag.children:
        if type(child) == type(ul_tag):
            match = re.match(r"\d+",str(child.string))
            if match:
                temp_num = int(match.group(0))
                if temp_num > max_page_count:
                    max_page_count = temp_num
    return max_page_count

getMaxPageCount(keyword) 函数主要是根据输入的商品种类关键词爬取相应的网页,获取当前种类商品的最大页数。

def getOnePageMsg(product_list, url):
    # 爬取一个页面的商品数据
    try:
        user_agent = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'}
        rspon = requests.get(url, headers = user_agent)
        rspon.encoding = rspon.apparent_encoding
        rspon.raise_for_status()
    except:
        print("爬取页数失败:", rspon.status_code)
    html = BeautifulSoup(rspon.text, "html.parser")
    ul_tag = html.find('ul', {"class": "bigimg cloth_shoplist"})
    if ul_tag:
        search_type = 2
    else:
        ul_tag = html.find('ul', {"class": "bigimg"})
        if ul_tag:
            search_type = 1
        else:
            return
    if search_type ==1:
        for child in ul_tag.children:
            if type(child) == type(ul_tag):
                temp_list = []
                # 保存书名
                tag_name = (child.find('p',{"class":"name"})).find('a')
                temp_list.append(str(tag_name.attrs["title"]))
                # 保存价格
                tag_price = (child.find('p',{"class":"price"})).find("span", {"class":"search_now_price"})
                temp_list.append(str(tag_price.string))
                # 保存作者
                tag_author = child.find('p', {"class":"search_book_author"}).find('a',{"name":"itemlist-author"})
                if tag_author:
                    temp_list.append(str(tag_author.string))
                else:
                    temp_list.append(str("NULL"))
                # 保存出版社
                tag_pub = child.find('p', {"class": "search_book_author"}).find('a', {"name": "P_cbs"})
                if tag_pub:
                    temp_list.append(str(tag_pub.string))
                else:
                    temp_list.append(str("NULL"))
                #保存评价
                tag_comment = child.find('p',{"class":"search_star_line"}).find('a')
                temp_list.append(str(tag_comment.string))
                product_list.append(temp_list)
    else:
        for child in ul_tag.children:
            if type(child) == type(ul_tag):
                temp_list = []
                # 保存商品名
                tag_name = (child.find('p',{"class":"name"})).find('a')
                temp_list.append(str(tag_name.attrs["title"]))
                # 保存价格
                tag_price = (child.find('p',{"class":"price"})).find("span")
                temp_list.append(str(tag_price.string))
                #保存评价
                tag_comment = child.find('p',{"class":"star"}).find('a')
                temp_list.append(str(tag_comment.string))
                product_list.append(temp_list)

getOnePageMsg(product_list, url) 函数实现的是根据一个url爬取网页的html信息,然后解析信息得到需要的商品信息,主要是使用bs4库的BeautifulSoup解析网页结构,并且将数据存入product_list列表中。

def getAllPageMsg(keyword, product_list):
    # 爬取商品的所有页面的数据
    page_count = getMaxPageCount(keyword)
    print("find ",page_count," pages...")
    for i in range(1,page_count+1):
        url = "http://search.dangdang.com/?key={}&input&page_index={}".format(keyword,i)
        getOnePageMsg(product_list,url)
        print(">> page",i," import successfully...")

getAllPageMsg(keyword, product_list) 函数实现的是根据关键词首先获取这一商品的最大页面,然后自动化生成每一个页面的url,在调用getOnePageMsg函数解析每个url页面,得到数据列表product_list。

def writeMsgToFile(path,keyword,product_list):
    # 将爬取的数据保存到文件
    file_name = "{}.txt".format(keyword)
    file = open(path+file_name, "w", encoding='utf-8')
    for i in product_list:
        for j in i:
            file.write(j)
            file.write(' ')
        file.write("\n")
    file.close()

writeMsgToFile(path,keyword,product_list) 函数主要实现将列表的数据写入文件,当然还有根据传入的路径和关键字生成对应的文件名。

def main():
    # 函数入口
    keyword = 'python'
    path="E://"
    product_list = []
    getAllPageMsg(keyword,product_list)
    writeMsgToFile(path,keyword,product_list)

最后main()函数是实现方法的入口,包括一些参数的初始化设置。
执行main()函数就能实现网页数据的爬取,以下是以python为关键词,爬取页面得到的结果,抓取解析完所有页面花了3分钟左右。
在这里插入图片描述
在这里插入图片描述

可以看到最终生成的txt文件一共有6000行,每一行保存的就是商品的信息。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐