紧跟着《生信修炼手册》的步伐,开始学习了解Python爬虫开发,为后续打下基础。
网络爬虫流程:
- 网页内容下载
- urllib、request、selenium
- html内容清洗
- 正则表达式、xpath表达式、beautifulsoup
- 数据库内容存储
- sqlite、mysql、monogodb
- sqlite、mysql、monogodb
用户代理在爬虫中的应用
用户代理(User-Agent),其具体内容为一行字符串,用来表征操作系统,浏览器版本等信息。
通过修改http请求中的user-agent信息,可以将普通的爬虫程序伪装成一个浏览器的请求,从而绕过服务器反爬虫机制中对user-agent的限制。
# urllib模块中设定UA
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}
IP代理在网络爬虫中的应用
通过用户代理可以将普通的爬虫程序伪装成浏览器,而IP代理的作用则是用于突破目标服务器对同一IP访问频率的限制。
在python中,通过urllib和requests这两个模块都实现IP代理。
## urllib 检测IP可行性
proxy="http://119.8.44.244:8080"
proxy_support=urllib.request.ProxyHandler({'http':proxy})
opener = urllib.request.build_opener(proxy_support)
urllib.request.install_opener(opener)
r = urllib.request.urlopen('http://icanhazip.com')
r.read()
## requests 检测IP可行性
import requests
proxies = {'http':'http://119.8.44.244:8080'}
r=requests.get("http://icanhazip.com", proxies=proxies)
r.text
## 完整流程
import requests
import random
import threading
# 获取代理IP
def get_proxy():
ip_list = [
'http://197.231.196.44:42461',
'http://190.124.164.78:8080',
'http://87.117.169.23:48705',
]
return random.choice(ip_list)
# 下载单个网页
def getHtml(url, proxy):
retry_count = 5
while retry_count > 0:
try:
html = requests.get(url, proxies= {'http':proxy})
return html
except Exception:
retry_count -= 1
return None
# 每个线程的处理逻辑
def download_html(ko, semaphore, proxy):
semaphore.acquire()
url = 'https://www.genome.jp/dbget-bin/www_bget?ko:{}'.format(ko)
out = './{}.kgml'.format(ko)
r = getHtml(url, proxy)
if r:
print('{} download success!'.format(ko))
with open(out, 'w') as fp:
fp.write(r.text)
else:
print('{} download failed!'.format(ko))
semaphore.release()
if __name__ == '__main__':
ko_list = ['K{:05d}'.format(i) for i in range(1, 201)]
thread_list = []
semaphore = threading.BoundedSemaphore(100)
for cnt, ko in enumerate(ko_list):
if cnt % 10 == 0:
proxy = get_proxy()
p = threading.Thread(target = download_html, args = (ko, semaphore, proxy ))
p.start()
thread_list.append(p)
for thread in thread_list:
thread.join()
cookie在网络爬虫中的应用
主要用于解决需要登录的网页的问题。ookie是一种存储在本地浏览器中的用户认证信息。一般使用F12查看。
cookie是一个动态信息,是和服务器交互之后生成的,具有时效性,在有效期内,cookie可以保持用户的登录状态,避免重复登录。当我们手动重新登录时,可以看到cookie的信息发生了变化.
# urllib模块中的用法
headers = {
... 'Cookie': 'sessionid=feli4ngf23njptxxb0qma5tl04x8wc43; csrftoken=O9YSm7TMaIb2ZdqEnENJY1GBXj3xUE26',
... 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
... }
request = urllib.request.Request('http://www.test.com', headers = headers)
response = urllib.request.urlopen(request)
# requests模块中的用法
import requests
headers = {
... 'Cookie': 'sessionid=feli4ngf23njptxxb0qma5tl04x8wc43; csrftoken=O9YSm7TMaIb2ZdqEnENJY1GBXj3xUE26',
... 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
... }
r = requests.get('http://www.test.com', headers=headers)
# 模拟登录
import urllib.request
import http.cookiejar
url = 'http://www.test.com'
user = 'user'
password = 'passwd'
# 账号,密码的验证
pwdmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
pwdmgr.add_password(None, url, user, password)
auth_handler = urllib.request.HTTPBasicAuthHandler(pwdmgr)
# cookie处理
cookies = http.cookiejar.CookieJar()
cookie_handler = urllib.request.HTTPCookieProcessor(cookies)
# 构建opener
opener = urllib.request.build_opener(auth_handler, cookie_handler)
# 安装为全局
urllib.request.install_opener(opener)
r = urllib.request.urlopen(url)
for item in cookies:
... print(item.name+'='+item.value)
动态网页常用的两种数据加载方式ajax和js动态请求
ajax请求通过network选项中的xhr请求来查找;js请求通过network选项中的js请求来进行查找。
使用selenium自动化操作浏览器
selenium是一个浏览器自动测试工具,通过驱动程序来自动化操作对应的浏览器,包括了打开浏览器窗口,定位元素,点击按钮,上传文件等操作。巧妙回避普通爬虫程序遇到的动态页面解析的难点。
# 具体示例,打开百度网页及关闭
from selenium import webdriver
browser = webdriver.PhantomJS()
browser.get('https://www.baidu.com')
browser.close()
常见功能:
定位元素
- find_element_by_id
- find_element_by_name
- find_element_by_xpath
- find_element_by_link_text
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
- find_element_by_css_selector 操作元素
- send_keys, 填写文本框或者上传文件
- submit, 提交表单
- select_by_index, 选择下拉列表
- save_screenshot, 保存网页截图
使用BeautifulSoup解析网页内容
# 解析html和xml文档内容,构建对象
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
# 常规多用lxm解析器 -- 最终得到一个文档树
# 1. 访问标签
soup = BeautifulSoup(html_doc, 'lxml')
soup.head
soup.head.title
soup.a # 默认只会返回文档的第一个标签
soup.find_all("a") # 返回多个标签构成的列表
soup.find_all("a")[0]
# find方法添加过滤条件,精确定位
# 通过text进行筛选
soup.find_all('a',text='Elsie')
# 通过属性和值进行筛选
soup.find_all('a',attrs=['id','link1'])
# CSS选择器
soup.find_all('p',class_='title')
# 2. 访问标签内容和属性
# name和string可以访问标签的名字和内容
# get和中括号操作符则可以访问标签中的属性和值
soup.a['class']
soup.a.get('class')
soup.a.get('class')
soup.a.name
soup.a.string
xpath语法 – 提取网页信息
# 通过lxml模块来使用xpath
from lxml import etree
html = etree.parse("K00001.html", etree.HTMLParser())
html.xpath('/html')
# 绝对定位,用/表示,选取路径树中直接相连的子节点
# 相对定位,用//表示,表示路径树中所有的子孙节点
# 从根节点开始,依次指定路径
html.xpath('/html/head/title')
# 利用//符号,得到属于html标签孙节点的title标签
html.xpath('/html//title')
# 直接用//符号,捕获title标签
html.xpath('//title')
## 利用位置筛选
html.xpath('//link')
html.xpath('//link[1]')
html.xpath('//link[last()]')
html.xpath('//link[position() < 3]')
# 利用属性筛选
html.xpath('//link[@media]')
html.xpath('//link[@media = "only"]')
html.xpath('//link[@media = "only" and @herf="#"]')
## 获取对应信息
html.xpath('//title/text()')
html.xpath('//a/@href')