当前位置:   article > 正文

python爬虫之静态网页(以当当网图书畅销榜榜为例)_爬虫实例当当网

爬虫实例当当网

在编写爬虫代码时,将网页分为静态网页和动态网页两种,不同类型的网页数据有着不同的处理办法,这篇文章简述爬取静态网页的方法,以当当网的图书销量为例,使用爬虫技术可以获得网页的页面数据并且自动生成excel表格保存,下面开始讲解

http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-recent7-0-0-1-1

首先我们判断一下当当网的页面数据加载是静态的还是动态的,有很多种方法,这里小编教大家一个,我们使用python中的requests库先对网页进行爬取,观察内容,如下图

  1. import requests
  2. '''User-Agent使代码伪装成浏览器进行网页访问,获取方法自行百度,不伪装可能无法获取数据'''
  3. head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36\
  4. (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}
  5. '''创造一个字典,将我们需要的信息作为键,后接空列表作为值,等待写入'''
  6. dataset = {'图书排行': [], '图书名称': [], '图书作者': [], '出版社': [], '出版时间': [],'价钱': []}
  7. url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-recent7-0-0-1-{}'.format(1)
  8. data = requests.get(url=url,headers=head)#利用get进行请求
  9. data.encoding=data.apparent_encoding#设置编码格式
  10. content = data.text#将对网站访问的信息保存在content变量中
  11. print(content)

上述代码为最最最简单的爬虫,稍微学过的小伙伴看起来会很容易,这里不过多讲解。

我们将变量content打印出来看看,并且搜索任意一本书的内容,发现可以搜索到,这就说明网页是静态的,如果搜索不到,则说明是动态的。如下图

在爬取的网页信息内,可以找到页面上的数据。

针对静态网页,利用python中的requests,re库即可,如果需要生成excel表格,需要导入xlwings

另外大家也可以学习一下BeautifulSoup,它可以解析网页结构,更好地对数据进行抓取。

本文使用requests、re、xlwings三个库

我们先打印一页内容看看,找找数据都在什么位置,打开浏览器的F12,单击左上角的箭头,点击到图书的地方,这需要我们对html结构有所了解,不然到这里就一脸懵

我们发现每个图书都是在class = ’bang_list clearfix bang_list_mode‘的ul标签下,并且每个图书块都在li标签中,我们打开一个li标签进行分析

可以发现所有的页面信息都可以在这些代码中找到,我们爬虫爬取的信息也是这些东西

接下来我们需要将这些东西挑出来,这时候就需要我们使用re模块,正则表达式,它能够按照一定的规则匹配字符串,读者可以自行学习这部分

我们以图书名称为例,使用re模块主要使用其中的findall函数,该函数必须设置两个参数,第一个是匹配规则,第二个是需要匹配的字符串,并以列表的形式返回

我们观察到书名的html都是这样的,我们匹配红圈里的文字,编写规则设定一个变量p_name

  1. p_name = '<div class="name"><a href=".*?" target="_blank" title=".*?">(.*?)</a></div>'
  2. dataset['图书名称'] = re.findall(p_name,content)

p_name中的.*?表示任意内容,而加上 括号(.*?)则会被提取出来

dataset['图书名称']是列表,里面保存着提取出来的信息

findall函数中,p_name为第一个参数,content为第二个参数

上图是匹配的结果,存在两个问题,第一,有的字符串匹配出来<span class='dot'>...</span>,需要删除;第二有的书名太长,建议把左括号(后的内容删除,下面我们可以利用for循环解决此问题

我们发现每一个有<span class='dot'>...</span>的字符串都是在左括号(后 或者 冒号:后,所以我们将( 或者:前的内容提取出来, 就可以同时解决存在<span class='dot'>...</span>和书名太长两个问题

  1. for i in book_name:
  2. if '(' in i:
  3. i = re.findall('(.*?)(',i)#提取中文左括号前的内容
  4. if ':' in i:
  5. i = re.findall('(.*?):',i)#提取冒号前的内容
  6. if '(' in i:
  7. i = re.findall('(.*?)\(',i)#提取英文左括号前的内容
  8. i = ''.join(i)#将列表转变为字符串
  9. i = '《' + i + '》'#在字符串前后加上书名号
  10. dataset['图书名称'].append(i)#将处理后的书名添加到book_name_list中
  11. print(dataset['图书名称'])

接下来我们看看处理后的书名

可以看到,处理后的书名相比之前,即准确又简洁

此时,字典dataset中图书名称就爬取出来了。

其他的图书排行、图书作者、出版社、出版时间、价钱都可以使用此方法进行数据抓取。这里仅简要介绍

匹配图书排行

  1. p_num = '<div class="list_num.*?">(.*?).</div>'
  2. dataset['图书排行'] = re.findall(p_num,content)
  3. print(dataset['图书排行'])

匹配出版社

  1. p_publish = '<div class="publisher_info"><span>.*?</span>&nbsp;<a href=".*?" target="_blank">(.*?)</a></div>'
  2. dataset['出版社'] = re.findall(p_publish,content)
  3. print(dataset['出版社'])

匹配出版时间

  1. p_time = '<div class="publisher_info"><span>(.*?)</span>&nbsp;<a href=".*?" target="_blank">.*?</a></div>'
  2. dataset['出版时间'] = re.findall(p_time,content)
  3. print(dataset['出版时间'])

匹配现价

  1. p_price = ''' <span class="price_n">&yen;(.*?)</span>'''
  2. dataset['价钱'] = re.findall(p_price,content)
  3. print(dataset['价钱'])

匹配作者时,在页面有两种不同的格式,小编想了很久,没法利用正则表达式提取,原因是它会将不同的格式跳过,那小编就没有办法了吗??当然不是,我们还是使用以下BeautifulSoup吧

在代码最前端增加from bs4 import BeautifulSoup

  1. soup = BeautifulSoup(content,'html.parser')#将content解析,赋予变量soup
  2. li_list = soup.select('.bang_list li')#与前文中的class = ’bang_list clearfix bang_list_mode‘对应
  3. for li in li_list:
  4. '''下面的搜寻方法为BeautifulSoup的匹配规则'''
  5. try: # 因图书作者存在两种html标签格式,故采try和except方法
  6. author = li.select('.publisher_info')[0].select('a')[0].text
  7. except:
  8. author = li.select('.publisher_info')[0].text
  9. dataset['图书作者'].append(author)
  10. print(dataset['图书作者'])

到此我们的dataset中就保存了第一页网页的所有信息,将dataset打印看看

这是第一页的数据,如果获取所有页的数据,对网站进行for循环即可,这里不再叙述

接下来讲述,如何写入excel,代码如下

在代码最前端导入xlwings  即import xlwings as xw  将其简写为xw

  1. '''将上述内容写入excel'''
  2. import xlwings as xw
  3. app = xw.App(visible=False,add_book=False)#启动excel程序,不可见 不新增工作簿
  4. work_book = app.books.add()#新增工作簿
  5. work_sheet = work_book.sheets.add('当当网图书畅销榜')#新增名为当当网图书畅销榜的工作表
  6. work_sheet['A1'].value = '图书排行'#将A1到F1表头填写好
  7. work_sheet['B1'].value = '图书名称'
  8. work_sheet['C1'].value = '图书作者'
  9. work_sheet['D1'].value = '出版社'
  10. work_sheet['E1'].value = '出版时间'
  11. work_sheet['F1'].value = '价钱'
  12. '''以下5行代码是将dataset写入excel的关键 请读者尽量理解'''
  13. '''利用zip将键名与列数成对提取出来,共6列所以j取值1至6,对每一列共有500个数据,每列第一行已有数据,k取值2至502
  14. chr(64+j)表示将数字转换为大写字母,因为excel定位单元格需要,例如A1,B2等 '''
  15. for i,j in zip(dataset.keys(),range(1,7)):
  16. for k in range(2,502):
  17. cell = '{}{}'.format(chr(64+j),k)
  18. work_sheet[cell].value = dataset[i][k-2]
  19. print('第{}列已完成'.format(j))
  20. work_sheet.autofit()#单元格自适应大小
  21. work_book.save(r'C:\Users\admin\Desktop\当当网图书销量.xlsx')#保存至桌面
  22. work_book.close()#关闭工作簿
  23. app.quit()#退出excel

其中的5行关键代码,为小编想了好久的结晶,自己长时间不看的话也会忘记怎么写出来的,大家尽量理解吧!!

至此对静态网页的爬取(当当) 并进行excel保存就完成了!!!

小编再强调一下,还是非常建议大家使用BeautifulSoup来抓取信息,requests库有时会报错,不能保证每次都成功,而BeautifulSoup目前是可以成功的。

上面主要是利用requests的代码,下面我附上利用BeautifulSoup爬取图书畅销榜的全代码

供大家指出意见和学习!!

  1. import requests
  2. from bs4 import BeautifulSoup
  3. import re
  4. head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36\
  5. (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'}
  6. dataset = {'图书排行': [], '图书名称': [], '图书作者': [], '出版社': [], '出版时间': [],'价钱': []}
  7. for i in range(1,26):
  8. url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-recent7-0-0-1-{}'.format(i)
  9. data = requests.get(url=url,headers=head)
  10. data.encoding=data.apparent_encoding
  11. content = data.text
  12. soup = BeautifulSoup(content,'html.parser')
  13. li_list = soup.select('.bang_list li')
  14. for li in li_list:
  15. a = li.select('.list_num ')[0].text.replace('.','')
  16. dataset['图书排行'].append(a)
  17. b = li.select('.name')[0].text#因获取到的名称千奇百怪 用正则表达式进行筛选
  18. if ' (' in b :
  19. b = re.findall('(\S+) (',b)#正则表达式结果为列表形式 通过join函数连接字符串的形式将其变为字符串格式 列表连接为字符串
  20. b = (''.join(b))
  21. elif '(' in b :
  22. b = re.findall('(\S+)(',b)
  23. b = (''.join(b))
  24. if '-' in b:
  25. b = re.findall('(\S+)-', b)
  26. b = (''.join(b))
  27. if '・' in b:
  28. b = re.findall('(\S+)・', b)
  29. b = (''.join(b))
  30. if ',' in b:
  31. b = re.findall('(\S+),', b)
  32. b = (''.join(b))
  33. if ' ' in b:
  34. b = re.findall('(\S+) ', b)
  35. b = (''.join(b))
  36. if '·' in b:
  37. b = re.findall('(\S+)·')
  38. b = '《'+b+'》'
  39. dataset['图书名称'].append(b)
  40. try:#因图书作者存在两种html标签格式,故采用此方法
  41. c = li.select('.publisher_info')[0].select('a')[0].text
  42. except:
  43. c = li.select('.publisher_info')[0].text
  44. dataset['图书作者'].append(c)
  45. d = li.select('.publisher_info')[1].select('a')[0].text
  46. dataset['出版社'].append(d)
  47. e = li.select('.publisher_info')[1].select('span')[0].text
  48. dataset['出版时间'].append(e)
  49. f = li.select('.price_n')[0].text.replace('¥','')
  50. dataset['价钱'].append(f)
  51. print('第{}页爬取完成'.format(i))
  52. '''将上述内容写入excel'''
  53. import xlwings as xw
  54. app = xw.App(visible=False,add_book=False)#启动excel程序,不可见 不新增工作簿
  55. work_book = app.books.add()#新增工作簿
  56. work_sheet = work_book.sheets.add('当当网图书畅销榜')#新增名为当当网图书畅销榜的工作表
  57. work_sheet['A1'].value = '图书排行'#将A1到F1表头填写好
  58. work_sheet['B1'].value = '图书名称'
  59. work_sheet['C1'].value = '图书作者'
  60. work_sheet['D1'].value = '出版社'
  61. work_sheet['E1'].value = '出版时间'
  62. work_sheet['F1'].value = '价钱'
  63. for i,j in zip(dataset.keys(),range(1,7)):
  64. for k in range(2,502):
  65. cell = '{}{}'.format(chr(64+j),k)
  66. work_sheet[cell].value = dataset[i][k-2]
  67. print('第{}列已完成'.format(j))
  68. work_sheet.autofit()
  69. work_book.save(r'C:\Users\yzb\Desktop\当当网图书销量.xlsx')
  70. work_book.close()
  71. app.quit()

最后展示一下效果

小编留下QQ:1097512301    有兴趣的小伙伴可以一起交流 共同进步

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/825061
推荐阅读
相关标签
  

闽ICP备14008679号