【0基础】纵横中文网python爬虫实战

原文在此:【0基础】纵横中文网python爬虫实战

大家好,我是你们的机房老哥!

在粉丝群的日常交流中,爬虫是比较常见的话题。python最强大的功能之一也是爬虫。

考虑到很多0基础的小白想要入门爬虫。老哥今天就通过一个比较简单的爬虫,介绍一下python爬虫的流程及思路,并扫盲爬虫常用工具的语法。

本次教程您将学到:

爬虫思路、流程

xpath全解析

css选择器全解析

requests_html库进阶

【0基础】纵横中文网python爬虫实战_第1张图片
▲最终成果

话不多说,接下来就是:

-STUDY PYTHON WITH-

基础教程——纵横中文python爬虫

-OLDER BROTHER-

获取小说信息

http://book.zongheng.com/store.html

【0基础】纵横中文网python爬虫实战_第2张图片
▲纵横中文网

要爬取的网址如上图所示。

导入老哥最常用的爬虫库requests_html库,首先将HTMLSession()函数定义为session。使用session.get()命令提交响应,最后打印r.html.html查看网页源代码。

```

from requests_html import HTMLSession

session = HTMLSession()

url = 'http://book.zongheng.com/store.html'

r = session.get(url)print(r.html.html)

```

【0基础】纵横中文网python爬虫实战_第3张图片
▲打印网页源码

如上图所示,老哥已经成功获得网页源码了。说明网站的反爬手段比较弱,适合新手练习。

【0基础】纵横中文网python爬虫实战_第4张图片
▲分析网址结构

按F12打开控制台,可以看到左侧小说的信息在

下,右侧小说的信息在
下。网址结构非常简单。

【0基础】纵横中文网python爬虫实战_第5张图片
▲分析小说名称

我们点入每个小说信息的div下,获取小说的信息。

可以看到,标签下的a标签中,href是小说网址,内容是小说标题。

标签下的第一个a标签中,href是作者的介绍页网址,内容是作者笔名。第二个a标签中,href是小说分类主题页网址,内容是小说分类。第一个span中是小说连载状态,第二个span中是小说更新时间。

接下来通过xpath分别提取这些信息,代码如下:

```

bookname = r.html.xpath('//div[@class="bookname"]/a/text()')

bookname_links = r.html.xpath('//div[@class="bookname"]/a/@href')

authorname = r.html.xpath('//div[@class="bookilnk"]/a/text()')

author_links = r.html.xpath('//div[@class="bookilnk"]/a/@href')

typename = r.html.xpath('//div[@class="bookilnk"]/a[2]/text()')

type_links = r.html.xpath('//div[@class="bookilnk"]/a[2]/@href')

status = r.html.xpath('//div[@class="bookilnk"]/span/text()')

time_ = r.html.xpath('//div[@class="bookilnk"]/span[2]/text()')

for num in range(len(bookname_links)):

    print(bookname[num], bookname_links[num], authorname[num], author_links[num], typename[num], type_links[num],

          status[num].strip(), time_[num].strip())

```

解析上述代码:通过r.html.xpath调用库中自带的xpath语法提取小说名。//div代表任意位置的div标签,[@class="bookname"]是xpath语法,中括号中@符号后是div的属性,这里用div的标签class="bookname"定位到小说名称。/a代表这个div下的第一个a标签,最后用text()函数提取a标签内容,即小说标题。

提取网址方法类似,区别在于在a标签后接/@href提取a标签下的href属性。

当一个div标签下有两个a标签时,a[2]代表第二个a标签。

【0基础】纵横中文网python爬虫实战_第6张图片
▲获取小说信息

这里顺便扫盲一下xpath的基础语法:

详解xpath

选取节点:

xpath('/div')——从根节点上选取div节点。

xpath('//div')——选取所有div节点。

xpath('./div')——选取当前节点下的div节点。

xpath('../a')——选取当前的父节点下的第一个a节点。

谓语:

xpath('/body/div[1]') ——选取body下的第一个div节点。

xpath('/body/div[last()]')——选取body下的最后一个div节点。

xpath('/body/div[last()-1]')——选取body下的倒数第2个div节点。

xpath('/body/div[positon()<3]')——选取body下的前2个div节点。

xpath('/body/div[@class]')——选取body下带有class属性的div节点。

xpath('/body/div[@class="main"]')——选取body下class属性为main的div节点。

xpath('/body/div[price>35.00]')——选取body下price元素值大于35的div节点。

xpath('/div/*')——选取div下的所有子节点。

xpath('/div[@*]')——选取所有带属性的div节点。

xpath('/div/node()')——匹配div下任何类型的节点。

xpath('//div|//table')——选择所有div和table节点。

功能函数:

xpath('//div[starts-with(@id,"ma")]')——选取id值以ma开头的div节点。

xpath('//div[contains(@id,"ma")]')——选取id值包含ma的div节点。

xpath('//div[contains(@id,"ma") and contains(@id,"in")]')——选取id值包含ma和in的div节点。

xpath('//div[contains(text(),"ma")]')——选取文本中包含ma的节点。

在这里老哥在稍微拓展一下。获得小说链接,除了上文中的方式,还可以用如下代码:

bookname_links = r.html.xpath('//div[@class="bookname"]/a', first=True)

print(bookname_links.attrs['href'])

解析一下上述代码,使用first=True提取div下的第一个a标签。在这里用.attrs['href']命令提取a标签下的href属性,同样可以得到链接。

值得注意的是,first=True提取的是第一个标签,返回element格式。如果不加,则返回列表格式,就不能使用该方法了。

【0基础】纵横中文网python爬虫实战_第7张图片
▲方法2获得href下的链接  

进入小说内容页

上文中已经提取到小说的链接,我们只需要再次用session.get()命令请求这个链接,即可得到小说内容。

【0基础】纵横中文网python爬虫实战_第8张图片
▲小说详情页

不过,上文中提出的链接点进去是小说详情页,所以想要获取小说内容,还需要提取“开始阅读”对应的href链接。代码如下:

```

bookname_links = r.html.xpath('//div[@class="bookname"]/a/@href')

for num in range(len(bookname_links)):

    bookname_link = bookname_links[num]

    r = session.get(bookname_link)

    r2 = r.html.xpath('//div[contains(@class,"btn-group")]/child::a')[0].links

    print(r2)

```

解析上述代码:老哥为了拓展教程,用了第三种方式提取链接。首先解析xpath语法,//div[contains(@class,"btn-group")],代表获取包含"btn-group"的class属性的div节点。这种方式的好处在于,假如该div节点的class有很多,写起来比较复杂,就可以用contains获取该class中包含的某个唯一字段。/child::a代表该div下的第一个子节点a。

由于这种方式得到的是一个列表,提取列表的第一个值,该值包含小说链接。这个值是

'requests_html.Element'>类型,这种类型是requests_html库自带的类型,可以使用.links命令提取该requests_html.Element下的所有链接。因为本案例只有一个链接,所以就返回一个值,即小说的链接。

上述代码中的r2即小说内容页的链接。

进阶:requests_html的.links命令

为了更好的理解.links命令的强大之处,老哥附带一个小案例。例如用.links命令提取根网站下的所有网址,代码如下:

```

from requests_html import HTMLSession

session = HTMLSession()

url = 'http://book.zongheng.com/store.html'

r = session.get(url)

print(r.html.links)

```

【0基础】纵横中文网python爬虫实战_第9张图片
▲轻松获取所有链接

可以看到,如果请求的网址下有很多网址,用.links命令可以不费吹灰之力的得到他们。

有时一些链接只有后半部分,需要拼接网站的域名才能使用,这时候,只需要将.links改成.absolute_links,即可获得自动补全的所有链接。

小说内容提取

最后一步就是小说内容提取,方法和上文类似,就不赘述了。这个网站有趣的地方在于禁止左键、右键点击。如果不会爬虫,只会复制粘贴网页信息的话,就会被难住了。当然用爬虫就完全无视这种“小伎俩”啦。

【0基础】纵横中文网python爬虫实战_第10张图片
▲小说内容

这部分和上文类似,解析标题、内容所在位置,为了拓展教程,老哥这里使用css选择器。代码如下:

```

r3 = session.get(list(r2)[0])

title = r3.html.find('.title_txtbox', first=True).text

author = r3.html.find('.bookinfo', first=True).text

content = r3.html.find('.content', first=True).text

```

解析上述代码,r3.html.find()代表使用css选择器。.title_txtbox代表选择class为title_txtbox的值,.是css选择器中选择class类型的符号。最后用.text命令获取内容,类似.links命令。

扫盲一下css选择器的基础语法:

详解CSS选择器

.intro——选择class="intro"的所有元素。 

#firstname——选择id="firstname"的所有元素。 

*——选择所有元素。 

p——选择所有

元素。 

div,p——选择所有

元素和所有

元素。 

divp——选择

元素内部的所有

元素。 

div>p——选择父元素为

元素的所有

元素。 

div+p——选择紧接在

元素之后的所有

元素。 

[target]——选择带有target属性所有元素。 

[target=_blank]——选择target="_blank"的所有元素。 

[title~=flower]——选择title属性包含单词"flower"的所有元素。 

[lang|=en]——选择lang属性值以"en"开头的所有元素。 

a:link——选择所有未被访问的链接。 

a:visited——选择所有已被访问的链接。 

a:active——选择活动链接。 

a:hover——选择鼠标指针位于其上的链接。 

input:focus——选择获得焦点的input元素。 

p:first-letter——选择每个

元素的首字母。 

p:first-line——选择每个

元素的首行。 

p:first-child——选择属于父元素的第一个子元素的每个

元素。 

p:before——在每个

元素的内容之前插入内容。 

p:after——在每个

元素的内容之后插入内容。 

p:lang(it)——选择带有以"it"开头的lang属性值的每个

元素。 

p~ul——选择前面有

元素的每个

你可能感兴趣的:(【0基础】纵横中文网python爬虫实战)