近期出于某些原因突然对爬虫来了兴趣,于是花了几个小时研究了一下爬虫,重新捡起来了,理清了爬虫的一个流程,以前学了很久一直不是很懂,不会自己去爬需要的东西。理清楚之后很简单,很多东西一目了然。在此记录一下简单的爬虫流程。
爬虫的大致流程
- 抓取到整个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解析有xpath、BeautifulSoup 等库,由于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: /
但是这只是网站的协议,具体的:
从目前的情况来看,如果抓取的数据属于个人使用或科研范畴,基本不存在问题; 而如果数据属于商业盈利范畴,就要就事而论,有可能属于违法行为,也有可能不违法。