python 爬虫的常用技巧总结,带你轻松入门
前几天我总结了一下使用 nodejs
写爬虫的一些常用的技巧,并且表示写爬虫没有最好的语言,只有最合适的,选择自己最熟悉的最顺手的语言最好。然而,最近在爬取一些数据的过程中需要处理 HTML 表格,虽然可以自己手动处理,但是有现成的轮子干嘛不用?写爬虫就是为了获取数据,经过数据的分析处理得到有趣的结论,为了能够尽快的得到结论,根据场景选择合适编程语言就显得很重要,尤其当所需要的工具是语言独占的时候(其他语言也许有移植版,但是社区活跃度显然没有原版高),比如说 pandas
。
想把表格数据转换成 dataframe
只需要一句话:
# 引入 pandas
import pandas as pd
# 简单的一句话,即可将 html 转换成含有 dataframe 的列表
df_list = pd.read_html(html)
# 对每个 dataframe 也就是每张表格做处理
for df in df_list:
print(df)
pandas
的这个功能真的深深的戳中了我的痛点,于是把整个爬虫用 python
重新写了一遍,这里也和上一次总结 nodejs
一样,总结一下 python
写爬虫的常用方法,方便以后复用,提高效率。
传送门:用 nodejs 写爬虫的常用技巧、pandas 快速入门
注:本文代码均基于 python3.6.5 版本,使用其他版本有可能导致运行错误。
请求网页方法
python
请求网页一般会使用 requests 这个库,正如其介绍的那样:built for human beings。相当的通俗易懂,简单易用。
import requests
# get 请求
r = requests.get(url)
# 带参数
payload = {
'key': 'value'
}
r = requests.get(url, params=payload)
# post 请求
r = requests.post(url)
# 带 form 参数
form_data = {
'key': 'value'
}
r = requests.post(url, data=form_data)
# 带 json 参数
json_data = {
'key': 'value'
}
r = requests.post(url, json=json_data)
伪装浏览器与串改请求头
其实伪装浏览器的本质就是修改请求头(request header),来让服务器难以辨别请求是来自爬虫还是真实用户的浏览器。通常设置 User-Agent
即可应对大部分网站。
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
}
r = request.get(url, headers=headers)
获取和设置 Cookies
这里就涉及到 requests
发送请求后的返回值了,也就是上面例子中的 r
。用户存储在浏览器的 Cookies 通常是浏览器根据返回头(response header)中的 Set-Cookie
的值来设置的,在 python
中这样获取:
r = request.get(url)
cookie = r.headers.get('set-cookie').split(';')[0].strip()
取消自动重定向
nodejs 的技巧文章中解释过,自动重定向可能会使用不正确的 Cookie 导致结果永远不对,因此有时需要取消这个功能:
r = requests.get(url, allow_redirects=False)
页面解析
我喜欢使用 beautifulsoup:
from bs4 import BeautifulSoup
r = requests.get(url)
# 这个 html.parser 是解析器,你也可以设置其他的,比如:lxml,如果你要解析 XML 文档,那么你就要把它设置为:lxml-xml。当然使用前要安装 lxml。
soup = BeautifulSoup(r.text, 'html.parser')
# 例:找到并打印页面中的所有超链接
for item in soup.find_all('a'):
print('{} - {}'.format(item.get_text(), item.get('href')))
使用代理
难免的情况,不论是 IP 被封,还是外网无法访问,均要使用代理来绕过限制:
教你科学上网:正确的科学上网方式
proxies = {
'http': 'http://127.0.0.1:6153/',
'https': 'http://127.0.0.1:6154/',
}
# 简直是直观的不能再直观了
r = requests.get(url, proxies=proxies)
多线程并行爬取
看了 nodejs 版本的朋友需要注意下,这里是多线程了,不是多进程。这里就提供一个线程池的模板:
import queue
import time
import threading
# 任务队列
q = queue.Queue()
# 线程数
THREADS = 4
# 任务列表
JOBS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 单个任务的处理方法
def run(job):
print(job)
# 线程方法,不断的从任务队列中取出参数并执行处理方法
def thread_function():
while True:
job = q.get()
run(job)
time.sleep(1)
q.task_done()
# 开启 THREADS 个线程
for i in range(THREADS):
t = threading.Thread(target=thread_function)
t.setDaemon(True)
t.start()
# 把任务添加进队列
for param in JOBS:
q.put(param)
# 等待任务队列结束
q.join()
python
爬虫我写的不多,本文只能分享这些基本常用的方法,日后有更多经验再来补充~