专门是五星图书

翻页也格外简单,只不过有一点点坑的是,爬回去的链接在代码中,须要对其翻页,就要求把链接构造出来。对重回来的链接举办辨析,发现唯有是中档有八个数字不一致。于是我把那多少个数据取出来,在一而再中传进去,这样可以协会通用的链接。

2.爬取七个新闻


分级复制《追风筝的人》、《小王子》、《围城》、《解忧杂货店》评分的 xpath
音讯举办对照:

//*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div[2]/span[2]
//*[@id="content"]/div/div[1]/div/table[2]/tbody/tr/td[2]/div[2]/span[2]
//*[@id="content"]/div/div[1]/div/table[3]/tbody/tr/td[2]/div[2]/span[2]
//*[@id="content"]/div/div[1]/div/table[4]/tbody/tr/td[2]/div[2]/span[2]

深信您早就得以秒写出爬取全部评分的xpath了:

//*[@id=“content”]/div/div[1]/div/table/tr/td[2]/div[2]/span[2]

把评分的xpath放入事先的代码,运行:


前几日大家再把书名和评分同时爬取下来:


此处大家默认书名和评分爬到的都是完全的、正确的音讯,那种默许一般情状没难点,但实际是有通病的,假若大家某一项少爬或多爬了音信,那么两种多少的量就不平等了,从而匹配错误。比如上面的例子:

书名xpath 后的@title 改为
text(),获取的公文数量与评分数量不等同,出现匹配错位。


只要咱们以每本书为单位,分别取获取相应的音信,那一定完全匹配


书名的竹签肯定在那本书的框架内,于是我们从书名的标签向上找,发现覆盖整本书的价签(左边网页会有代码包罗内容的新闻),把xpath
音讯复制下来:

//*[@id="content"]/div/div[1]/div/table[1]


俺们将整本书和书名的xpath进行自查自纠

//*[@id=“content”]/div/div[1]/div/table[1]   #整本书
//*[@id=“content”]/div/div[1]/div/table[1]/tr/td[2]/div[1]/a   #书名
//*[@id=“content”]/div/div[1]/div/table[1]/tr/td[2]/div[2]/span[2]   #评分


一见倾心发现,书名和评分 xpath 的前半有的和整本书的 xpath 一致的,
那大家可以通过那样写 xpath 的形式来恒定新闻:

file=s.xpath(“//*[@id=“content”]/div/div[1]/div/table[1]”)
title =div.xpath(“./tr/td[2]/div[1]/a/@title”)
score=div.xpath(“./tr/td[2]/div[2]/span[2]/text()”)


在事实上的代码中来看一下:


见惯不惊大家爬了一本书的新闻,那怎么爬那些页面所有书呢?很简短啊,把 xpath
中<table>前边定位的序号去掉就ok。


毕竟看到武当山精神了,不过,等等~

title = div.xpath("./tr/td[2]/div[1]/a/@title")[0]    
score=div.xpath("./tr/td[2]/div[2]/span[2]/text()")[0]

怎么那两行前面多了个 [0]
呢?我们事先爬出来的数目是列表,外面带个方框,瞅着这几个不爽,列表唯有一个值,对其取第二个值就OK。如若不通晓列表的学问,能够回去补补。

接下去就是依据那样的法子多爬多少个因素啦!


有一个点须要注意的是:

num=div.xpath("./tr/td[2]/div[2]/span[3]/text()")[0].strip("(").strip().strip(")")

那行代码用了多少个 strip() 方法,()里面表示要刨除的情节,strip(“(”)
表示删除括号, strip() 表示删除空白符。

哦,已经把一个页面搞定了,接下去须要,把装有页面的信息都爬下来。

于是,第一步就是要得到分化分类的页面链接,先以“随笔”类目作为样例来测试一下,复制xpath音信并收获链接。

3.翻页,爬取所有页面新闻

先来看一下翻页后url是哪些转移的:

https://book.douban.com/top250?start=0   #第一页
https://book.douban.com/top250?start=25   #第二页
https://book.douban.com/top250?start=50   #第三页

url 变化的原理很粗略,只是 start=()
的数字不等同而已,而且是以每页25为单位,递增25,那不正是每页的图书的数码吗?于是,我们只须要写一个循环就足以了啊。

for a in range(10):    
  url = 'https://book.douban.com/top250?start={}'.format(a*25)
  #总共10个页面,用 a*25 保证以25为单位递增


此间要强调一下 Python range() 函数

主导语法:range(start, stop, step)
start:计数从 start 开端。默认是从 0 初始。例如 range(5)
等价于range(0,5);
end:计数到 end 甘休,但不包罗 end。例如:range(0,5)是 [0,1,2,3,4]
没有5
step:步长,默认为1。例如:range(0,5) 等价于 range(0,5,1)

>>>range(10)    #从 0 开始到 10 (不包含)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

>>> range(1, 11)    #从 1 开始到 11 (不包含)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

>>> range(0, 30, 5)    #从0到30(不包含),步长为5 
[0, 5, 10, 15, 20, 25]


丰硕循环之后,完整代码如下:

from lxml import etree
import requests
import time

for a in range(10):
    url = 'https://book.douban.com/top250?start={}'.format(a*25)
    data = requests.get(url).text

    s=etree.HTML(data)
    file=s.xpath('//*[@id="content"]/div/div[1]/div/table')
    time.sleep(3)

    for div in file:
        title = div.xpath("./tr/td[2]/div[1]/a/@title")[0]
        href = div.xpath("./tr/td[2]/div[1]/a/@href")[0]
        score=div.xpath("./tr/td[2]/div[2]/span[2]/text()")[0]
        num=div.xpath("./tr/td[2]/div[2]/span[3]/text()")[0].strip("(").strip().strip(")").strip()
        scrible=div.xpath("./tr/td[2]/p[2]/span/text()")

        if len(scrible) > 0:
            print("{},{},{},{},{}\n".format(title,href,score,num,scrible[0]))
        else:
            print("{},{},{},{}\n".format(title,href,score,num))


来运转一下:

请务须求自己陶冶五回,你以为自己看懂了,依旧会出错,不信我们赌五毛钱。

Python
的功底语法很重点,没事的时候多去看看:字符串、列表、字典、元组、条件语句、循环语句……

编程最紧要的是实战,比如您曾经可以爬TOP250的图书了,去试试TOP250电影呢。

好了,那节课就到那边!


下节预先报告:Python爬虫入门 | 5
爬虫必备Python知识

总体7节科目目录:
Python爬虫入门 | 1
Python环境的装置

Python爬虫入门 | 2
爬取豆瓣电影音信

Python爬虫入门 | 3
爬虫必备Python知识

Python爬虫入门 | 4
爬取豆瓣TOP250图书信息

Python爬虫入门 | 5
爬取小猪短租租房音信

Python爬虫入门 | 6
将爬回去的数据存到本地

Python爬虫入门 | 7
分类爬取豆瓣电影,解决动态加载难题

白白~

当当网本身没有啥反爬机制,所以爬取也相比较顺遂。唯一的小麻烦就是抓回去的链接继续翻页和中间部分书本中有的音讯缺失的拍卖。当然,那一个对于有些有点经历的同室来说都不是什么样事。

1. 爬取单个新闻

我们先来品尝爬取书名,利用从前的套路,仍旧先复制书名的xpath:


得到第一本书《追风筝的人》的书名xpath如下:

//*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div[1]/a


收获xpath,我们就可以根据事先的不二法门来尝试一下:


再次来到的居然是空值,那就很狼狈了。

此处必要留意,浏览器复制的 xpath
新闻并不是全然有限帮忙的,浏览器常常会协调在其间增加多余的 tbody
标签,大家必要手动把这几个标签删掉。


修改 xpath 后再来尝试,结果如下:

难忘:浏览器复制 xpath 不是一心保证,看到 tbody 标签尤其要注意。


独家复制《追风筝的人》、《小王子》、《围城》、《解忧杂货店》的 xpath
消息实行相比较:

//*[@id="content"]/div/div[1]/div/table[1]/tbody/tr/td[2]/div[1]/a
//*[@id="content"]/div/div[1]/div/table[2]/tbody/tr/td[2]/div[1]/a
//*[@id="content"]/div/div[1]/div/table[3]/tbody/tr/td[2]/div[1]/a
//*[@id="content"]/div/div[1]/div/table[4]/tbody/tr/td[2]/div[1]/a

正如可以窥见书名的 xpath 音讯唯有 table
后的序号不同,并且跟书的序号一致,于是去掉序号(去掉
tbody),大家得以获取通用的 xpath 音信:

//*[@id=“content”]/div/div[1]/div/table/tr/td[2]/div[1]/a


好了,我们摸索把这一页全部书名爬下来:

复制”小说”类目的xpath信息

from lxml import etree
import requests

url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-all-0-0-1-1'
data = requests.get(url).text
s = etree.HTML(data)
items = s.xpath('//*[@id="sortRanking"]/div')

for item in items:
    book_url=item.xpath('./a/@href')
    item_name=item.xpath('./a/text()')

    if len(book_url)>0:  #避免抓回来的链接是空的情况
        href=book_url[0]
        item_title=item_name[0]
        print(item_title)
        print(href)


咱俩就要爬取哪些音讯:书名、链接、评分、一句话评价……

累计10000多行数据,对应分化世界的10000多本高评分的图书,当然会有一部分重新统计,比如随笔和理学,就有成百上千书是同时在那八个类目标。然则不管怎么说,都拿到了数量。


先来探视页面长啥样的:https://book.douban.com/top250

http://bang.dangdang.com/books/fivestars/01.03.00.00.00.00-all-0-0-1-1
http://bang.dangdang.com/books/fivestars/01.03.00.00.00.00-all-0-0-1-2
http://bang.dangdang.com/books/fivestars/01.03.00.00.00.00-all-0-0-1-3
…………………………

当当网五星图书页面

品味得到各第三个类目的名号和链接

于是乎构造出每个类目下都有25个页面的链接:

接下去就是去抓取不同页面的信息,没有异步加载,所以平素用xpath定位就OK。当然中间有部分小地点需求小心的是,每本书所富含的信息是不等同的,所以用xpath去取得的时候不肯定能获取到,就会出错。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from lxml import etree
import requests
import time

url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-all-0-0-1-1'

headers = {
            'Host': 'bang.dangdang.com',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
        }

data = requests.get(url,headers=headers).text
s = etree.HTML(data)

with open('dangdang.csv','w') as outputfile:
    items = s.xpath('//*[@id="sortRanking"]/div')

    for item in items:
        book_url=item.xpath('./a/@href')
        item_name=item.xpath('./a/text()')

        if len(book_url)>0:
            href=book_url[0]
            item_title=item_name[0]
            a=href[41:46]
            print(item_title)

            for page in range(1,26):

                per_url= 'http://bang.dangdang.com/books/fivestars/{}.00.00.00.00-all-0-0-1-{}'.format(a,page)
                data2=requests.get(per_url).text
                f=etree.HTML(data2)

                try:
                    file=f.xpath('//ul[@class="bang_list clearfix bang_list_mode"]/li')
                    print('正在打印{}第{}页…………'.format(item_title,page))
                    time.sleep(2)

                    for book in file:
                        title=book.xpath('./div[@class="name"]/a/@title')[0]
                        author=book.xpath('string(./div[@class="publisher_info"][1])')
                        pinglun=book.xpath('./div[@class="star"]/a/text()')[0].strip('条评论')
                        wuxing=book.xpath('./div[@class="biaosheng"]/span/text()')[0].strip('次')
                        price_now=book.xpath('./div[@class="price"]/p/span[1]/text()')[0]
                        price_before=book.xpath('./div[@class="price"]/p/span[2]/text()')[0]
                        price_sale=book.xpath('./div[@class="price"]/p/span[3]/text()')[0]

                        try:
                            date=book.xpath('./div[@class="publisher_info"]/span/text()')[0]
                        except:
                            date='出版时间不详'

                        try:
                            company=book.xpath('./div[@class="publisher_info"][2]/a/text()')[0]
                        except:
                            company='出版社不详'

                        try:
                            price_e=book.xpath('./div[@class="price"]/p[@class="price_e"]/span/text()')[0]
                        except:
                            price_e="没有电子书"

                        outputfile.write('{},{},{},{},{},{},{},{},{},{}'.format(title,author,date,company,pinglun,wuxing,price_now,price_before,price_sale,price_e))

                except:
                    pass

胜利地赢得了类目的称呼和链接:

废话不多说,先上准备爬取的页面链接:
http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-all-0-0-1-1


到那里基本可以了解,当当网的反爬确实不严加,我甚至还不曾安装Headers的信息,竟然也得以爬取到想要的数目。但结尾在全体的代码中,照旧把headers加上了,保障起见吧。

本次作业选取爬取的网站是当当网,一方面是因为神话相比简单,另一方面也有相比多的图书数据,越发是五星图书,包括了各样领域最受欢迎的书籍音信,对于寻找有价值的图书、分析好书的部分意况拥有一定的市值。

from lxml import etree
import requests

url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-all-0-0-1-1'
data = requests.get(url).text
s = etree.HTML(data)

title = s.xpath('//*[@id="sortRanking"]/div[2]/a/text()')
href = s.xpath('//*[@id="sortRanking"]/div[2]/a/@href')

print(title)
print(href)

结构的翻页链接-小说

爬取数据截图

为了抓各分类下的图书音讯,首先看望点击各分类的时候,链接是不是发生变化。经过测试,在分歧的分类,链接都是不等同的,事实阐明不是JS加载。

//*[@id="sortRanking"]/div[2]/a

爬取数据截图

接下去就是个别爬取每个分类下的书籍新闻,以“小说”为例,其实翻页越发简单,给多少个比较如下:

爬回去的一些的链接

提请了DC学员的爬虫课程,断断续续学了五个星期,才看完第一章。固然技术还很菜,但部分骨干的东西可以爬取了,也想趁本次作业,来品尝一下那段时日攻读的学问。

爬取的数量如下:


得到的xpath如下:

@DC学院《Python爬虫:入门+进阶》


本身想爬取的多少是各分类(小说、中小学教辅、文学、成功/励志……)下边的五星图书音讯(书名、评论数、小编、出版社、出版时间、五星评分次数、价格、电子书价格之类)。


根据稳定的覆辙,尝试获得类目的题和页面链接:

总体的代码如下:

结构的翻页链接-中小学教辅

这一次写爬虫,确实也是五次相比系统地尝试,从前也没爬过那样多的多寡。自知技术来不够获得可以作业和奖赏,可是非常手舞足蹈能从中得到升高,大神们见笑了。

既是那样,其余的链接也足以经过那样的方法来收获,于是相比较了一下多少个类目标xpath,很容易觉察规律。获取具有的类目链接如下:

对此翻页的数量,粗略地看了瞬间依次类目的最大页数,最多的是25页,当然也有个别25页的。

具体的页面如下图:

from lxml import etree
import requests
import time

url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-all-0-0-1-1'
data = requests.get(url).text
s = etree.HTML(data)
items = s.xpath('//*[@id="sortRanking"]/div')

for item in items:
    book_url=item.xpath('./a/@href')
    item_name=item.xpath('./a/text()')

    if len(book_url)>0:
        href=book_url[0]
        item_title=item_name[0]
        a=href[41:46]
        print(item_title)

        for page in range(1,26):
            per_url= 'http://bang.dangdang.com/books/fivestars/{}.00.00.00.00-all-0-0-1-{}'.format(a,page)
            print(per_url)