近期出于某些原因突然对爬虫来了兴趣,于是花了几个小时研究了一下爬虫,重新捡起来了,理清了爬虫的一个流程,以前学了很久一直不是很懂,不会自己去爬需要的东西。理清楚之后很简单,很多东西一目了然。在此记录一下简单的爬虫流程。

爬虫的大致流程

  • 抓取到整个url的html代码
  • 解析代码中需要的部分
  • 数据保存
  • 高级爬虫(进阶)

上述流程中,我自己只学了前两个部分,对我自己来说也是够用了,第三部分对于不以爬虫为工作的,我认为就不用专门去学习了,可以写入txt文件或者直接下载图片。。至于最后一部分就涉及到爬虫的框架,分布式爬虫等等,这个对于个人来说我觉得也是不必要的。

具体知识点

抓取url

我用的是方便、简单的requests库,操作如下:

import requests
url = 'https://www.baidu.com'
headers = {'User-Agent': "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"}
response = requests.get(url=url, headers=headers)
reponse.status_code # 200表示正常访问
#抓取到的html的所有代码
html_text = response.text

第一步比较简单,几行代码,当然其中也有高级操作,比如代理之类的,后面在讲。

解析html 重点

xpath比较全的一个博客:https://www.jianshu.com/p/85a3004b5c06

拿到html内容后,就要分析一下,找出自己需要的内容,html解析有xpathBeautifulSoup 等库,由于Bs4我并不会(虽然学过),所以这里就用xpath~

表达式描述
nodename选取此节点的所有子节点
/从当前节点选区直接子节点
//全局查找某个节点
.选取当前节点
..选取当前节点的父节点
@选取属性
and多个属性同时匹配

我认为会这些基本就够了,可以抓取下来任何自己想要的了,至少解析不会有问题。

import lxml.etree
parser = etree.HTMLParser(encoding='utf-8') # 创建解释器
html = etree.parse('baidu.html', parser=parser) # 解析html
# xpath返回的是list
# 全局搜索id为pins的ul标签下面所有的li标签下面的a标签中的href(链接)
# @为精确匹配
link = html.xpath("//ul[@id='pins']//li/a/@href")
 
# 全局搜索class为"item-0"的li标签下面的第一个a标签中的文本 用/text()获取
result = html.xpath('//li[@class="item-0"]/a/text()')
 
# and表示同时满足多个属性
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
 
# 模糊匹配 全局搜索class名称包含'li'的li标签下面的第一个a标签中的文本  
result = html.xpath('//li[contains(@class, "li")]/a/text()')
 

至此就解析完成,拿到了自己想要的,爬虫基本也随之结束了。

拿到的是一堆字符串,要下载要提取就用python的方法处理即可,关于下载图片可以用requests直接保存:

h = open(img_name,'wb') # img_name 为要保存的图片名称
h.write(requests.get(img_src,headers=header).content) #img_src为字符串
h.close()

问题、解决:

  • 抓取url

在抓取url时(get),有时候非常慢,或者是下载多了ip会直接被封。有以下几个解决方案:

  • 爬虫时例如下载图片时,一定要有时间间隔

    time.sleep(1)
  • 动态获取ip:

    # ------------------------------------------------------------------------------
    # # @Time    : 2020/6/7 下午 8:09
    # # @Author  : fry
    # @FileName: ip.py
    # ------------------------------------------------------------------------------
    import requests
    import time
    from lxml import etree
    def pnw():  # 定义一个循环的函数
        headers = {
            'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 "
                          "(KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1"}
        # 依次遍历生成2-99
        ip_address = []
        for i in range(2, 100):
            url = "https://www.kuaidaili.com/free/inha/" + str(i) + "/"  # 爬取的免费ip
            response = requests.get(url, headers=headers).text  # 获得网页文本数据
            response_xpath = etree.HTML(response)  # 转换为xpath可用结构
            ips = response_xpath.xpath('//[@id="list"]/table/tbody/tr/td[1]/text()')  # ip的信息
            dks = response_xpath.xpath('//*[@id="list"]/table/tbody/tr/td[2]/text()')  # 端口的信息
            https = response_xpath.xpath('//*[@id="list"]/table/tbody/tr[2]/td[4]/text()')  # http信息
            for ip, dk, http in zip(ips, dks, https):
                proxy = "http://" + ip + ":" + dk  # 拼接ip
                proxies = {"http": proxy}
                ip_address.append(proxies)
        return ip_address
    if __name__ == '__main__':
        ips = pnw()
        print(ips)

    以上代码可以获取ip,使用时:

    ip = pnw()
    pic_page = requests.get(url=url_pic, headers=header,proxies=ip[0]) #使用ip代理

基本如此,掌握之后可以随心所欲爬取自己所需。


  • 如果想要爬一个网站所有的东西,需要自己去分析一下url规律,比如哪个标签里面有所有的链接等等

  • 关于反爬机制,用好代理

最后,关于爬虫的合法性:

url拼接上/robots.txt 可以看到网站的爬虫协议:

User-agent:  Baiduspider # 允许百度爬虫引擎
Allow:  /article # 允许访问/article.htm,/article/12345.com
Allow:  /oshtml      
Allow:  /wenzhang
Disallow:  /product/ # 禁止访问/product/12345.com
Disallow:  /         # 禁止了访问除Allow规定页面的其他所有页面
 
User-Agent:  Googlebot  # 谷歌爬虫引擎
Allow:  /article
Allow:  /oshtml
Allow:  /product # 允许访问/product.htm,/product/12345.com
Allow:  /spu
Allow:  /dianpu
Allow:  /wenzhang
Allow:  /oversea
Disallow:  /
 

但是这只是网站的协议,具体的:

从目前的情况来看,如果抓取的数据属于个人使用或科研范畴,基本不存在问题; 而如果数据属于商业盈利范畴,就要就事而论,有可能属于违法行为,也有可能不违法。