0%

python爬虫

python爬虫

计算机网络

IP

用32位二进制表示,记录时每八位转化为一个十进制数:xxx.xxx.xxx.xxx

  • 局域网IP

  • 动态IP:回收

  • 静态IP:购买服务器

URL

1
http://www.xxx.com:80/path/index.html?value1=1&value2=2#maodian
  • 协议:http, https, file, ftp;
  • 域名或IP
  • 端口:默认80;
  • 路径
  • 参数:通过问号直接拼接在URL,多个参数用&连接;
  • 锚点:锚点链接是超链接中的一种,可以使用它链接到文档中的某个特定位置。

网络协议

  • 应用层:http, ftp, pop3, DNS;应用程序;
  • 表示层:
  • 会话层:
  • 传输层:TCP, UDP;
  • 网络层:IP, ICMP, IGMP;路由器;
  • 数据链路层:ARP, RARP;交换机;
  • 物理层:物理传输介质;双绞线/集线器;

TCP/IP协议

  • IP地址:是逻辑地址,可以变化;
  • TCP(传输控制协议):负责把需要传输的数据分解成一定长度的片段;
    是一种字节流,会处理IP层即以下的丢包、重复以及错误问题。
    TCP提供了一种可靠、面向连接、字节流、传输层的服务,采用3次握手建立一个连接,4次挥手来关闭一个连接。
  • IP协议:负责将数据片段贴上标签成为数据包,标签包括源IP地址目标IP地址,决定数据传输的路径;
  • 路由器:会根据数据包的地址信息查询路由表,然后以最佳路径发送数据包,不会确保数据的完整性。

socket编程

套接字

1
2
3
4
5
6
7
8
9
import socket
socket.socket(协议族(默认即可),协议(默认TCP))# new一个套接字
.bind(('IP',端口)) # 服务器端绑定,注意参数是元组
.listen() # 服务器端监听
.accept() # 服务器端阻塞连接
.connect() # 客户端连接
.send(byte) # 客户端发送数据
.recv(数量) # 服务器端接收数据,是阻塞的,连接断开后才会进行下一步
.close()

Q:由于目标计算机积极拒绝,无法连接。

A:换个端口试试。可能是被防火墙屏蔽了。

Q:[WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试。

A:再换个端口,可能是被占用了。:cry:

Q:过段时间发现突然连不上了

A:你可能换了个WiFi,IP地址变了:cry:

多线程

实现多个客户端与服务端的交互

1
2
3
4
5
import threading
while True:
sock, addr = server.accept()
client_thread = threading.Thread(target=handle_sock, args=(sock, addr))#注意target的值是函数名称而不是直接调用,args表示传递
client_thread.start()

HTTP协议

超文本传输协议,应用层协议。

特点:

  • 是单向的,只有客户端发送了请求才会有服务器响应;
  • 是纯文本协议,我们只需要传递纯文本就可以,web服务器会根据约定好的方法生成对应的HTTP信息;
  • 通过指定content-type可以传递任意类型的数据对象;
  • 无连接-每次连接处理一个请求然后断开连接
  • 无状态-没有记忆能力,需要cookie和session来区别
1
2
3
4
5
6
请求方法 URL 协议版本		//请求行
头部字段名:值 //请求头部
……
头部字段名:值

请求数据

Q:通过python-socket写一个http响应,传送到浏览器却一直无响应,一直转圈圈;

A:不知道怎么就好了,,可能是响应写错了?\r\n表示换行

前端基础

html,css,JavaScript

浏览器的加载过程:

  1. 构建dom树;
  2. 子资源加载——加载外部的css,js,图片等;
  3. 样式渲染——css执行

dom树

ajax,json,xml

get,post

content-type:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json

爬虫技术

爬虫数据采集分类

  • 按照采集对象分类
    • 全网采集(搜索引擎)
    • 全站采集
    • 具体网站的指定数据(目的明确)
  • 采集方案分类
    • 利用http协议采集-页面分析
    • 利用API接口采集-APP数据采集
    • 利用目标网站的API采集(开放的):github,微博

request

方法

1
2
3
4
import requests
requests.get("url",参数……)
requests.post("url",参数……) #参数可以是json格式:json=...
requests.status_code()

状态码

  • 1*:信息,服务器收到请求,需要请求者继续执行操作;
  • 2*:200,201等,成功,操作被成功接收并处理;
  • 3*:301,302等,重定向,需要进一步的操作以完成请求;
  • 4*:401,404,400,403等,客户端错误,请求包含语法错误或无法完成请求;
  • 5*:500,501,502等,服务端错误,服务器在请求的过程中发生了错误。

正则表达式

基本语法

符号 作用
. 匹配任意字符(不包括换行符)
^ 匹配开始位置
$ 匹配结束位置
* 匹配前一个元字符0到多次(匹配最长长度)
+ 匹配前一个元字符1到多次
? 匹配前一个元字符0到1次
{m,n} 匹配前一个元字符m到n次
\\ 转义字符
[ ] 字符集,可匹配其中任意一个字符
[]中的短横线-表示区间,所以想表示一个字符时要放在末尾
|
\b 匹配位于单词开始或结束位置的空字符串(可以自行判断是否是一个单词)
\B 匹配不位于单词开始或结束位置的空字符串
\d 匹配一个数字=[0-9]
\D 匹配非数字
\s 匹配任意空白字符=[ \t\n\r\f\v]
\S 匹配任意非空白字符
\w 匹配数字、字母、下划线中任意一个字符=[a-zA-Z0-9_]
\W 匹配非数字、字母、下划线中任意字符

re

编译:re.compile("正则语法") 返回pattern对象,可供findall和match使用。

提取字符串

1
2
3
4
import re
re.findall("正则语法","参数") #返回数组
re.match("正则语法","参数") #从字符串的开头开始匹配,返回一个对象,只能匹配一行
re.search("正则语法","参数") #返回一个对象(与match类似),可多行

match:正则语法中用小括号表示分组,匹配结果的对象自带group方法。

替换

1
re.sub("正则语法","new","参数")

模式

1
2
re.IGNORECASE	#忽略大小写
re.DOTALL #多行匹配

beautifulsoup4

1
2
from bs4 import BeautifulSoup
bs = BeautifulSoup("html","解析器")

解析器

  • html.parser

  • lxml

  • lxml-xml

  • xml

  • html5lib

定位方法

  • 标签:bs.标签名

  • find

    • bs.find("标签名")
      bs.find(id=" ")
      bs.find("标签名",id=' ')
      bs.find("标签名",{"class":"类名"})
      bs.find("标签名",id=re.compile("正则表达式"))
      
      1
      2
      3
      4
      5
      6
      7
        


      - ```python
      result = bs.find_all("标签名")
      for tag in result:
      #循环体

节点获取

  • 子节点

    1
    2
    3
    4
    children = result.contents		#子元素
    children = result.descendants #所有子元素,包括子元素的子元素
    for child in chhildren:
    pass
  • 父节点

    1
    2
    3
    4
    parent = result.parent			#返回单个父元素
    parents = result.parents #返回所有父元素
    for parent in parents:
    pass
  • 兄弟节点

    1
    2
    3
    4
    next_siblings = result.next_siblings			#返回目标之后的同等级节点内容
    previous_siblings = result.previous_siblings #返回目标之前的同等级节点内容
    for sibling in next_siblings:
    pass

属性获取

1
2
3
# 以class属性为例
1.result["class"] #如果没有该属性会报错,第二个不会
2.result.get("class")

XPATH

scrapy安装

官方安装文档:https://www.osgeo.cn/scrapy/intro/install.html#intro-install

第三方库的地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/

  • lxml

    1
    2
    pip install lxml
    pip install 对应的whl文件 #在上述网址中去找lxml

    whl文件的下载一定要注意版本问题:https://blog.csdn.net/loopwastemytime/article/details/79919865

    若想本地的库在pycharm的项目能使用,在项目\venv\pyvenv.cfg文件中,将include-system-site-packages的值修改为true

  • twisted:与lxml的whl文件下载安装类似

XPATH简介

对象:xml&html

节点关系:

  • 父节点
  • 子节点
  • 同胞节点
  • 先辈节点

XPATH语法

符号介绍:

符号 说明
/ 从根节点选取,使用绝对路径,路径必须完全匹配
// 从整个文档中选取,使用相对路径
. 从当前节点开始选取
从当前节点父节点开始选取
@ 选取属性

例子:

表达式 说明
article 选取所有article元素的所有子节点
/article 选取根元素article
article/div 选取所有属于article的子元素的div元素
//div 选取所有div子元素
article//div 选取所有属于article元素的后代的div元素
//@class 选取所有名为class的属性
/article/div[1] 选取属于article的子元素的第一个div元素
/article/div[last()] 选取属于article的子元素的最后一个div元素
//div[@class] 选取所有拥有class属性的div元素
//div[@class=’name’] 选取所有class属性值为name的div元素
/div/* 选取属于div元素的所有子节点
//* 选取所有元素
//div[@*] 选取所有带属性的div元素
//div/a|//div/p 选取所有div元素的a和p元素
//span|//ul 选取文档中的span和ul元素
article/div/p|//span 选取所有属于article元素的div元素的p元素,和所有的span元素

插播一条血的教训:一定注意文件名称,不要与python的包名重复!

1
2
3
4
5
6
7
from scrapy import Selector
sel = Selector(text='html')
result = sel.xpath("xpath语法") #返回一个对象
result.extract() #返回list
#xpath中有很多内置的方法
result = sel.xpath("xpath语法/text()") #取标签中的值
result = sel.xpath("//div[contains(@class,'属性名')]") #模糊

项目实战

  1. github地址:https://github.com/Alfred1984/interesting-python/tree/master/Weibo_Comment_Pics
    相关微信文章:https://mp.weixin.qq.com/s/iTtVXMVdoTBxWHzEzbQH1Q
    断更,做不出来。
  2. https://www.cnblogs.com/dhsfdhfhgufdu/p/15108793.html
    每天一个放弃小技巧
    1. 遇到百度安全验证,把请求头header带上
    2. 想要的内容被隐藏了,标签内容为空,源代码找不到,但是页面审查可以找到。