Python爬虫

1.HTTP协议

一种超文本传输协议,由请求和响应组成。

a. HTTP请求

由三部分组成:请求行+ 请求头+ 请求体

请求行: 请求方法(GET,POST,PUT) + url +http版本 GET /hello.html HTTP/1.1

请求头:包含请求体的长度,请求所支持的MIME类型等

1
2
3
4
5
6
7
8
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://www.example.com/index.html
Connection: keep-alive

请求体:包含了发给服务器的数据

b. HTTP响应

状态行+ 响应头+ 响应体

状态行:HTTP 版本+ 状态码+ 状态信息 例:HTTP/1.1 200 ok

响应头:包含响应体的长度、类型

1
2
3
4
5
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
Date: Fri, 26 Mar 2021 10:00:00 GMT
Server: Apache/2.4.41 (Ubuntu)

响应体:通常是HTMl,JSON,XML格式的文本。

2.XML相关技术

a. 解析

解析器的作用是将XML格式转为内存中的数据结构,方便程序对其进行操作。常见的XML解析器有SAX,DOM

b. DOM树

是一种把XML文件转为树型结构的模型,可通过节点、文本、属性等信息来表示XML的结构。常用xml.dom 与lxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import xml.dom.minidom

#加载XML文件
doc = xml.dom.minidom.parse("book.xml")

#获取XML根节点
root = doc.documentElement

#遍历DOM树
books = root.getElementsByTagName("book")
for book in books:
#获取根节点的子节点
titile = book.getElementsByTagName("titile")[0]
author = book.getElementsByTagName("author")[0]
year = book.getElementsByTagName("year")[0]
price = book.getElementsByTagName("price")[0]

# 获取子节点的文本内容和属性
print("Title: %s" % title.childNodes[0].data)
print("Author: %s" % author.childNodes[0].data)
print("Year: %s" % year.childNodes[0].data)
print("Price: %s" % price.childNodes[0].data)

c.XPATH

在XML中定位的语言,可通过路径来定位一个节点。 例/bookstore/book[1]/title

3. 正则表达式

1
2
3
4
5
6
7
8
9
10
11
12
.:匹配任意一个字符,除了换行符;
^:匹配行首;
$:匹配行尾;
*:匹配前面的字符出现零次或多次;
+:匹配前面的字符出现一次或多次;
?:匹配前面的字符出现零次或一次;
{m}:匹配前面的字符出现 m 次;
{m, n}:匹配前面的字符出现 m~n 次;
[]:匹配方括号中的任意一个字符;
[^...]:匹配不在方括号中的任意一个字符;
(ab):匹配括号中的正则表达式,可以使用 \1、\2、\3 等来引用匹配到的子组;
|:表示或,匹配两边任意一个表达式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import re
import requests
from bs4 import BeautifulSoup

# 发送请求获取网页源代码
url = "https://www.example.com"
response = requests.get(url)
html = response.text

# 使用 BeautifulSoup 清洗网页源代码
soup = BeautifulSoup(html, "html.parser")
clean_html = soup.get_text()

# 使用正则表达式匹配所有链接
pattern = r'<a.*?href="(.*?)".*?>.*?</a>'
links = re.findall(pattern, clean_html)

# 输出所有链接
for link in links:
print(link)

4. 多线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import requests
import threading

# 定义爬取函数
def crawl(url):
response = requests.get(url)
html = response.text
# 处理爬取结果
...

# 定义线程函数
def worker():
while True:
url = q.get()
if url is None:
break
crawl(url)
q.task_done()

# 创建任务队列
q = queue.Queue()

# 创建线程池
for i in range(num_threads):
t = threading.Thread(target=worker)
t.daemon = True
t.start()

# 添加任务到队列中
for url in urls:
q.put(url)

# 等待所有任务完成
q.join()