当前位置:   article > 正文

爬取当当网python类书籍的信息(存储在mysql中)_爬取当当网上python相关的图书信息,包括:书名、作者、出版时间、出版社、价格、简

爬取当当网上python相关的图书信息,包括:书名、作者、出版时间、出版社、价格、简

我爬取到的数据是存储在mysql数据库中的,没有需要安装。

本文设计到的python库有:bs4、scrapy、pymysql、

首先在cmd命令行输入下图(1)的命令,显示下图(2)中的内容时,项目创建成功,然后用pycharm打开这个项目。

没有安装scrapy框架的建议用anaconda安装,然后在anacomda prompt输入(1)的命令

使用pycharm打开项目后目录结构如下(在spiders中新建mySpider.py、book下新建run.py):

然后分析当当网的图书数据进行分析,打开当当网,在搜索中输入python,看到如下页面:

此时的地址为:http://search.dangdang.com/?key=python&act=input

分析html代码的结构,我们看到每本书都是一个<li>的项目,而它们的结构是完全一样的,这些

<li>包含在一个<ul>中,我们只关心图书的名称title、作者author、出版时间date、出版社publisher、

价格price和内容简介detail。下面对提取这些信息的代码做一个分析:

1、title = li.xpath("./a[position()=1]/@title").extract_first()

<li>中有多个<a>标签,从html代码中可以看到书名信息包含在一个<a>的title属性中,因此通过position()=1

找出第一个<a>,然后取出title属性值就是书名title。

2、price = li.xpath("./p[@class='price']/span[@class='search_now_price']/text()").extract_first()

价格包含在<li>中的class='price'的<p>元素下面的class='search_now_price'的span元素的文本中

3、author = li.xpath("./p[@class='search_book_author']/span[position()=1]/a/@title").extract_first()

作者包含在<li>下面的class='search_book_author'的<p>元素下面的第一个<span>元素的<a>标签的

title属性中,其中span[position()=1]就是限定第一个<span>元素。

4、date = li.xpath("./p[@class='search_book_author']/span[position()=last()-1]/text()").extract_first()

出版日期包含在<li>下面的class='search_book_author'<p>元素下面的倒数第二个<span>元素的文本中

5、publisher = li.xpath("./p[@class='search_book_author']/span[position()=last()]/a/@title").extract_first()

出版社包含在<li>下面的class='search_book_author'的<p>元素下面的最后一个span元素的<a>标签中的title属性中。

6、detail = li.xpath("./p[@class='detail']/text()").extract_first()

在<li>下面的class='detail'的<p>的文本就是书的简介。

下面来看具体的代码:

1、编写items.py的数据项目类:

  1. import scrapy
  2. class BookItem(scrapy.Item):
  3. title = scrapy.Field()
  4. author = scrapy.Field()
  5. date = scrapy.Field()
  6. publisher = scrapy.Field()
  7. detail = scrapy.Field()
  8. price = scrapy.Field()

2、编写pipelines.py的数据处理类:

  1. import pymysql
  2. class BookPipeline(object):
  3. # 爬虫开始是执行的函数
  4. def open_spider(self, spider):
  5. print("opened")
  6. try:
  7. # 连接数据库,密码写自己的密码
  8. self.con = pymysql.connect(host="127.0.0.1",port=3306, user="root",passwd="123456", charset="utf8")
  9. self.cursor = self.con.cursor(pymysql.cursors.DictCursor)
  10. try:
  11. self.cursor.execute("create database mydb")
  12. except:
  13. pass
  14. self.con.select_db("mydb")
  15. try:
  16. self.cursor.execute("drop table books")
  17. except:
  18. pass
  19. try:
  20. sql = """
  21. create table books(
  22. bID varchar(8) primary key,
  23. bTitle varchar(512),
  24. bAuthor varchar(256),
  25. bPublisher varchar(256),
  26. bDate varchar(32),
  27. bPrice varchar(16),
  28. bDetail text
  29. )ENGINE=InnoDB DEFAULT CHARSET=utf8; # 保证建立的表与打开的数据库编码一致
  30. """
  31. self.cursor.execute(sql)
  32. except:
  33. self.cursor.execute("delete from books")
  34. self.opened = True
  35. self.count = 0
  36. except Exception as err:
  37. print(err)
  38. self.opened = False
  39. def close_spider(self, spider):
  40. if self.opened:
  41. self.con.commit()
  42. self.con.close()
  43. self.opened = False
  44. print("closed")
  45. print("总共爬取", self.count, "本书籍")
  46. def process_item(self, item, spider):
  47. try:
  48. print(item["title"])
  49. print(item["author"])
  50. print(item["publisher"])
  51. print(item["date"])
  52. print(item["price"])
  53. print(item["detail"])
  54. print()
  55. if self.opened:
  56. self.count += 1 # 用来构造bID
  57. ID = str(self.count)
  58. while len(ID) < 8:
  59. ID = "0" + ID
  60. # 插入数据到表中
  61. self.cursor.execute("insert into books(bID,bTitle,bAuthor,bPublisher,bDate,bPrice,bDetail) values(%s,%s,%s,%s,%s,%s,%s)",(ID, item["title"], item["author"], item["publisher"], item["date"], item["price"],item["detail"]))
  62. except Exception as err:
  63. print("wrong error:"+str(err))
  64. return item
  在scrapy的过程中一旦打开一个spider爬虫就会执行这个类的open_spider(self,spider)函数,一旦这个spider
关闭就执行这个类的close_spider(self,spider)函数,因此程序在open_spider函数中连接MySQL数据库,并创建操作
游标self.cursor,在close_spider中提交数据并关闭数据库,程序中使用count变量统计爬取的书籍数量
  在数据处理函数中每次有数据到达,就显示数据内容,并使用insert的SQL语句把数据插入到数据库中。

3、编写scrapy的配置文件setting.py的数据处理类:

找到以下两个地方,第一处打开,第二处修改

DEFAULT_REQUEST_HEADERS = {     #模拟浏览器
  'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  'Accept-Language': 'en',
}
ITEM_PIPELINES = {
   'book.pipelines.BookPipeline': 300,
}

这样就可以把爬取的数据推送到pipelin的BookPipeline类中去了。

4、编写scrapy的爬虫程序mySpider.py:

  1. import scrapy
  2. from book.items import BookItem #如果你的目录结构和我不一样注意一下
  3. from bs4 import UnicodeDammit
  4. class MySpider(scrapy.Spider):
  5. name = "mySpider"
  6. key = 'python'
  7. source_url = 'http://search.dangdang.com/'
  8. def start_requests(self): #程序开始时会调用
  9. url = MySpider.source_url+"?key="+MySpider.key+"&act=input"
  10. yield scrapy.Request(url=url, callback=self.parse) # 调用parse函数
  11. def parse(self, response):
  12. try:
  13. dammit = UnicodeDammit(response.body, ["utf-8", "gbk"])
  14. data = dammit.unicode_markup
  15. selector = scrapy.Selector(text=data)
  16. lis = selector.xpath("//li['@ddt-pit'][starts-with(@class,'line')]") # 取到当前页面中所有带有属性ddt-pit的<li>,即每一条书籍
  17. for li in lis:
  18. title = li.xpath("./a[position()=1]/@title").extract_first()
  19. price = li.xpath("./p[@class='price']/span[@class='search_now_price']/text()").extract_first()
  20. author = li.xpath("./p[@class='search_book_author']/span[position()=1]/a/@title").extract_first()
  21. date = li.xpath("./p[@class='search_book_author']/span[position()=last()-1]/text()").extract_first()
  22. publisher = li.xpath("./p[@class='search_book_author']/span[position()=last()]/a/@title").extract_first()
  23. detail = li.xpath("./p[@class='detail']/text()").extract_first()
  24. # detail 有时没有,结果为None
  25. item = BookItem()
  26. item["title"] = title.strip() if title else ""
  27. item["author"] = author.strip() if title else ""
  28. item["date"] = date.strip()[1:] if title else "" #注意到日期前有一个符号/,所以从1开始取值
  29. item["publisher"] = publisher.strip() if publisher else ""
  30. item["price"] = price.strip() if price else ""
  31. item["detail"] = detail.strip() if detail else ""
  32. yield item # 将爬取到的一条记录推送到pipelines.py由process_item函数处理
  33. #最后一页是link为None
  34. link = selector.xpath("//div[@class='paging']/ul[@name='Fy']/li[@class='next']/a/@href").extract_first()
  35. if link:
  36. url = response.urljoin(link)
  37. yield scrapy.Request(url=url, callback=self.parse)
  38. except Exception as err:
  39. print(err)

 仔细分析网站的HTML代码发现在一个<div class='paging'>的元素中包含了翻页的信息,<div>下面的<ul name='Fy'>下面的

<li class='next>下面的<a>链接就是下一页的链接,取出这个链接地址,通过response.urljoin函数整理成绝对地址,再次产生一个

scrapy.Request对象请求,回调函数仍为这个parse函数,这样就可以递归调用parser函数,实现下一个网页的数据爬取。

5、编写run.py:

from scrapy import cmdline
cmdline.execute("scrapy crawl mySpider -s LOG_ENABLED=False".split())

运行run.py,查看mysql数据库得到如下图所示结果:

 

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

闽ICP备14008679号