python实例:某套图网站爬虫

 案例一:

某套图网站,套图以封面形式展现在页面,需要依次点击套图,点击广告盘链接,最后到达百度网盘展示页面。

这一过程通过爬虫来实现,收集百度网盘地址和提取码,采用xpath爬虫技术

 

1、首先分析图片列表页,该页按照更新先后顺序暂时套图封面,查看HTML结构。每一组“li”对应一组套图。属性href后面即为套图的内页地址(即广告盘链接页)。所以,我们先得获取列表页内所有的内页地址(即广告盘链接页)

代码如下:

import requests   倒入requests库
from lxml import etree   倒入lxml 库(没有这个库,pip install lxml安装)
url = "https://www.xxxx.com/gc/"  请求地址
response = requests.get(url= url)   返回结果
wb_data = response.text   文本展示返回结果
html = etree.HTML(wb_data)   将页面转换成文档树
b = html.xpath('//ul[@class = "clearfix"]//@href')  这一步的意思是class“clearfix”下所有属性为“href”赋值给“b”,因为我们的目标内容都展示在class“clearfix”下,且在href属性后面
print(b)   打印b,这里的b是一个数组
print(b[0]) 打印b的第一项数据

执行结果:成功返回所有内页

 

2、打开内页(即广告盘链接页),获取广告盘地址。下图红色箭头,还不是真正的百度盘页,需要点击后才可以看的到百度盘的地址。所以这一步骤,只需要抓取红色箭头内容地址;

 

代码如下:

url = "https://www.xxxx.com/gc/toutiao/87098.html"
response = requests.get(url= url)
wb_data = response.text # 将页面转换成文档树
html = etree.HTML(wb_data)
b = html.xpath('//div[@class = "pictext"]//@href')
c=b[1]      #需要注意的地方,class = "pictext"下有两个href,我们只需要第一个href的值,所以返回值再赋值给c且取第二项数据
print(c)

执行结果:成功返回所有内页

 

3、获取到广告盘地址,接下来要打开该地址,抓百度盘真实地址。链接和提取码在两个不同的元素中,所有最后返回两组数据。

 

 

代码如下:

url = "http://xxx.la/xam9I6"
response = requests.get(url= url)
wb_data = response.text
# 将页面转换成文档树
html = etree.HTML(wb_data)
b = html.xpath('//tr/td/text()')
c=b[6]#提取码
d = html.xpath('//tr//@href')#百度地址
print(c)
print(d)

注意,这里html.xpath写法与上面有些区别,目标元素的上级没有class,只能模糊取值

比如提取码的HTML结构如下图,结构为//tr/td/,单/代表父节点下的子节点,双/代表父节点后的子孙节点。提取码为tr的子节点。但是这个结构下有很多组数据,最后输出一个数组b(看上面代码b)。如此,我们找到提取码位于数组序列,赋值给c(看上面代码c),这样获得了真实的百度盘地址

网盘地址则因为有href属性,所以好爬去一些,注意/的数量即可

 

4、把以上步骤拼成一个脚本,这里就涉及到函数和函数之间的传参,还有循环的问题。代码直接贴出来

 

# -*-coding:utf8-*-
# encoding:utf-8

import requests
from lxml import etree
import os
import sys

path = os.path.abspath(os.path.dirname(sys.argv[0]))

firstlink = "https://www.xxx.com/gc/qt/xxx.html"
AA=["https://www.xxx.com/gc/",
   "https://www.xxx.com/gc/index_2.html",
   "https://www.xxx.com/gc/index_3.html",
    "https://www.xxx.com/gq/",
    "https://www.xxx.com/gq/index_2.html",
    "https://www.xxx.com/gq/index_3.html",
    "https://www.xxx.com/gq/index_4.html"]

#第1步,获取每一页所有的资源地址,地址格式“https://www.xxx.com/gq/mistar/mistar300.html”
def stepa (AA):
    lit=[]
    for url in AA:
        response = requests.get(url=url)
        wb_data = response.text
        # 将页面转换成文档树
        html = etree.HTML(wb_data)
        a = html.xpath('//ul[@class = "clearfix"]//@href')
        lit.append(a)
    return(lit) 
alllink = stepa(AA)

#第2步,获取的地址,循环读取打开,从而获取百度网盘信息
def stepb(alllink,firstlink):
    for list in alllink:
        for url in list:
            if url in firstlink:
                continue
            elif "www" in url:
                url2 = url
            else:
                url2 ="https://www.xxx.com" +url
            response = requests.get(url=url2)
            wb_data = response.text # 将页面转换成文档树
            html = etree.HTML(wb_data)
            b = html.xpath('//div[@class = "pictext"]//@href')
            g = html.xpath('//div[@class = "pictext"]/text()')
            c = b[1]#地址(广告盘地址或者百度盘地址)地址格式“http://xxx.la/Tm1R2T“或者”https://pan.baidu.com/s/xxx-xxx-azplbTIQ“
            h = g[-1]
            i=h[14:18]#提取码(获取到的提取码打印出来的是乱码,如果获取到内容不正确,优先考虑是这里的问题)
            test3=c+i#把链接和提取码拼接成一条数据
 #下面的条件判断是解决获取链接不一致的问题,本来通过第一步骤获取的套图页,需要进一步点击广告页获取百度地址,有些资源不需要获取广告盘地址,点击后直接是百度地址
 # 所以做了判断,如果是百度地址,直接写入文档,如果是广告盘地址,则打开广告盘地址,再获取百度盘地址写入文档           
            if "pan.baidu.com" in c:
                with open(path+'\\1.txt', 'a',encoding='utf-8') as w:
                    w.write('\n'+test3)
                    w.close()
            else:
                #获取到广告页地址
                url3 = c
                response = requests.get(url=url3)
                wb_data = response.text
                # 将页面转换成文档树
                html = etree.HTML(wb_data)
                d = html.xpath('//tr/td/text()')
                #print(d)
                e=d[6]#获取提取码
                f = html.xpath('//tr//@href')#获取地址
                test = e[-5:]#提取码值只保留提取码(4位)
                test2 = f[-1]#链接只保留链接内容,去掉前后['']
                test3=test2+test#把链接和提取码拼接成一条数据
                print(test3)
                with open(path+'\\1.txt', 'a',encoding='utf-8') as w:
                    w.write('\n'+test3)
                    w.close()
stepb(alllink,firstlink)

#第3步:提示爬取完成
def over():
    print("ok")
over()   

 

 需要注意的地方:

1、return的用法,如果想把函数生成的值传给后面的函数用,就需要返回这个值,如def stepa 里定义的a为爬去的套图封面地址(通过打开这个地址进行下一步),就需要return(a)返回a的值,否则执行后无数据

2、Continue的应用,因为第一个套图地址打开的内容没有目标内容,这样找不到元素会报错,所以需要读取套图地址的时候要跳过第一个地址。加一个if判断,当第一个地址等于事先定义好的非正常地址的时候,跳过这个循环

 

打印结果:

 

 

 案例二:

爬取豆瓣的读书的评论

分析html,评论存储放在标红色元素位置,且观察结构,其他评论都存储在li节点的相同位置

所以,xpath的解析对象为//*[@id="comments"]//div[2]/p/span

前面的实例讲过"//" 代表从当前节点选取子孙节点,这里就可以直接跳过li节点,直接选择li后的div[2]/p/span内容

代码如下:

# -*-coding:utf8-*-
# encoding:utf-8

import requests
from lxml import etree

firstlink = "https://book.douban.com/subject/30172069/comments/hot?p=6"

def stepa (firstlink):
    response = requests.get(url=firstlink)
    wb_data = response.text
    html = etree.HTML(wb_data)
    a = html.xpath('//*[@id="comments"]//div[2]/p/span')
    print(a)
stepa (firstlink)

运行代码,打印出来的结果如下图,没有得到想要的评论内容

后来发现,想要获取内容,必须以文本的形式输出,即xpath的解析对象为//*[@id="comments"]//div[2]/p/span/text()

修改后的代码

 

# -*-coding:utf8-*-
# encoding:utf-8

import requests
from lxml import etree

firstlink = "https://book.douban.com/subject/30172069/comments/hot?p=6"

def stepa (firstlink):
    response = requests.get(url=firstlink)
    wb_data = response.text
    html = etree.HTML(wb_data)
    a = html.xpath('//*[@id="comments"]//div[2]/p/span/text()')
    print(a)
stepa (firstlink)

执行一下,内容来了

 

参考地址:https://cuiqingcai.com/5545.html

posted @ 2019-08-11 16:42  小贝书屋  阅读(8960)  评论(0编辑  收藏  举报