Python 三国人物数据快速采集极简方法汇总

作为一名数据分析师而并非开发工程师,需要掌握的爬虫必备的知识内容,能获取需要的数据即可,如果需要更专业的基于爬虫工程师的内容请浏览 『Scrapy 爬虫框架』部分内容。

以最最最基础的《三国志 13》人物数据采集举例了解和掌握基础的爬虫技能和数据整理技巧。

整套学习自学教程中应用的数据都是《三國志》、《真·三國無雙》系列游戏中的内容。

Python 三国人物数据快速采集极简方法汇总

数据目标

武将一覧 - 三国志13 攻略 WIKI

我们要获取该页面中全部的武将数据信息。

Python 三国人物数据快速采集极简方法汇总


爬虫 requests 几种方式

基本使用方法

"""例"""
from urllib import request
response = request.urlopen(r'https://sangokushi13wiki.wiki.fc2.com/wiki/%E6%AD%A6%E5%B0%86%E4%B8%80%E8%A6%A7') 

#返回状态 200证明访问成功
print("返回状态码:  "+str(response.status))
返回状态码:  200

Request 静态页面数据获取

静态网页 的网址形式通常是以 .htm、.html、.shtml、.xml 等为后缀。一般来说是最简单的HTML网页,服务器端和客户端是一样的。在 HTML 格式的网页上也可以出现各种动态的效果,如 GIF 格式的动画、FLASH、滚动字母等,这些动态效果只是视觉上的。

我们本地抓取的目标就是静态页面。

使用 request() 来包装请求,再通过 urlopen() 获取页面,俗称伪装。让服务器知道我们是通过浏览器来访问的页面,有些情况可能会被直接毙掉。

# 加载第三方使用插件和基础配置
import requests
from bs4 import BeautifulSoup
import pandas as pd
import random
import warnings
warnings.filterwarnings("ignore")

# 浏览器 header 
USER_AGENT_LIST = [
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
]

# 使用本地代理 可以使用也可以不使用
proxies = {
    "http": "http://127.0.0.1:19180",
    "https": "https://127.0.0.1:19180"
}

headers = {
    "User-Agent":random.choice(USER_AGENT_LIST),
}

# https://sangokushi13wiki.wiki.fc2.com/wiki/武将一覧
url = "https://sangokushi13wiki.wiki.fc2.com/wiki/%E6%AD%A6%E5%B0%86%E4%B8%80%E8%A6%A7"

html = requests.get(url,headers=headers,proxies=proxies,verify=False)

soup = BeautifulSoup(html.text,"lxml")

soup


Python 三国人物数据快速采集极简方法汇总

Python 三国人物数据快速采集极简方法汇总

Python 三国人物数据快速采集极简方法汇总


Request 动态页面数据获取

动态网页是以 .asp、.jsp、.php、.perl、.cgi 等形式为后缀。动态网页与网页上的各种动画、滚动字幕等视觉上的动态效果没有直接关系,动态网页也可以是纯文字内容的,也可以是包含各种动画的内容,这些只是网页具体内容的表现形式,无论网页是否具有动态效果,采用动态网站技术生成的网页都称为动态网页。动态网站也可以采用静动结合的原则,适合采用动态网页的地方用动态网页,如果必要使用静态网页,则可以考虑用静态网页的方法来实现,在同一个网站上,动态网页内容和静态网页内容同时存在也是很常见的事情。

import requests
from bs4 import BeautifulSoup
url = "http://news.cqcoal.com/blank/nl.jsp?tid=238"
html = requests.get(url)
soup =  BeautifulSoup(html.text,"lxml")
soup.text


Python 三国人物数据快速采集极简方法汇总

Python 三国人物数据快速采集极简方法汇总

抓取该网页看不到任何的信息证明是动态网页,正确抓取方法如下。


Python 三国人物数据快速采集极简方法汇总


import urllib
import urllib.request
import requests

url = "http://news.cqcoal.com/manage/newsaction.do?method:webListPageNewsArchivesByTypeid"
post_param = {'pageNum':'1',\
              'pageSize':'20',\
              'jsonStr':'{"typeid":"238"}'}
return_data = requests.post(url,data =post_param)
content=return_data.text
content


Python 三国人物数据快速采集极简方法汇总


总结来说:页面内容变了网址也会跟着变基本都是静态网页,反之是动态网页。

Request 异常处理

from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError
req = Request("http://www.111cn.net/")
try:
    response = urlopen(req)
except HTTPError as e:
    print('服务器无法满足请求.')
    print('错误代码: ', e.code)
except URLError as e:
    print('不能访问服务器.')
    print('原因: ', e.reason)
else:
    print("OK!")
    print(response.read().decode("utf8"))

不能访问服务器.
原因:  [Errno 11001] getaddrinfo failed

Request HTTP认证

import urllib.request

# 私密代理授权的账户
user = "user_name"
# 私密代理授权的密码
passwd = "uesr_password"
# 代理IP地址  比如可以使用百度西刺代理随便选择即可
proxyserver = "177.87.168.97:53281"
# 1. 构建一个密码管理对象,用来保存需要处理的用户名和密码
passwdmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# 2. 添加账户信息,第一个参数realm是与远程服务器相关的域信息,一般没人管它都是写None,后面三个参数分别是 代理服务器、用户名、密码
passwdmgr.add_password(None, proxyserver, user, passwd)
# 3. 构建一个代理基础用户名/密码验证的ProxyBasicAuthHandler处理器对象,参数是创建的密码管理对象
#   注意,这里不再使用普通ProxyHandler类了
proxyauth_handler = urllib.request.ProxyBasicAuthHandler(passwdmgr)
# 4. 通过 build_opener()方法使用这些代理Handler对象,创建自定义opener对象,参数包括构建的 proxy_handler 和 proxyauth_handler
opener = urllib.request.build_opener(proxyauth_handler)
# 5. 构造Request 请求
request = urllib.request.Request("http://bbs.pinggu.org/")
# 6. 使用自定义opener发送请求
response = opener.open(request)
# 7. 打印响应内容
print (response.read())

ROBOT协议

目标网址后加/robots.txt,例如:京东官网机器人协议


Python 三国人物数据快速采集极简方法汇总

第一个的意思就是说对于所有的爬虫,不能爬取在/?开头的路径,也不能访问和/pop/*.html 匹配的路径。 后面四个用户代理的爬虫不允许访问任何资源。

所以Robots协议的基本语法如下: - User-agent: 这里是爬虫的名字。 - Disallow: /该爬虫不允许访问的内容。

爬虫的网页抓取

爬虫的用途

实现浏览器的功能,通过制定的URL,直接返回用户所需要的数据。

一般步骤:

  • 查找域名对应的IP地址 (比如:119.75.217.109是哪个网站?)。
  • 向对应的IP地址发送get或者post请求。
  • 服务器相应结果200,返回网页内容。
  • 开始抓你想要的东西吧。

网页分析

获取对应内容之后进行分析,其实就需要对一个文本进行处理,把你需要的内容从网页中的代码中提取出来的过程。BeautifulSoup 可实现惯用的文档导航、查找、修改文档功能。如果 lib 文件夹下没有 BeautifulSoup 的使用命令行安装即可。

pip install BeautifulSoup

数据提取

# 想要抓取我们需要的东西需要进行定位,寻找到标志
from bs4 import BeautifulSoup
soup = BeautifulSoup('',"html.parser")
tag=soup.meta

# tag的类别
type(tag)
bs4.element.Tag

# tag的name属性
tag.name
'meta'

# attributes属性
tag.attrs
{'content': 'all', 'name': 'robots'}

# BeautifulSoup属性
type(soup)
>>> bs4.BeautifulSoup
soup.name
'[document]'

# 字符串的提取
markup='房产'
soup=BeautifulSoup(markup,"lxml")
text=soup.b.string
text
'房产'
type(text)
bs4.element.NavigableString

人物列表数据解析

# 加载第三方使用插件和基础配置
import requests
from bs4 import BeautifulSoup
import pandas as pd
import random
import warnings
warnings.filterwarnings("ignore")

# 浏览器 header 
USER_AGENT_LIST = [
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
    "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
    "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
]

headers = {
    "User-Agent":random.choice(USER_AGENT_LIST),
}

# https://sangokushi13wiki.wiki.fc2.com/wiki/武将一覧
url = "https://sangokushi13wiki.wiki.fc2.com/wiki/%E6%AD%A6%E5%B0%86%E4%B8%80%E8%A6%A7"

html = requests.get(url,headers=headers,verify=False)
soup = BeautifulSoup(html.text,"lxml")

soup


Python 三国人物数据快速采集极简方法汇总


# 由于是多个表格要一个一个处理,将数据填进列表
data_list = []
for data in soup.find_all("table",class_="table"):
    data_list.append(data)

# 遍历循环页面数据提取
result_data_list = []
for num in range(len(data_list)):
    for i in data_list[num].find_all("tr"):
        try:
            one_data = [d.text for d in i.find_all("td")] 
            one_url = ["https://sangokushi13wiki.wiki.fc2.com" + i.find_all("td")[1].a["href"]]
            result_data = one_data + one_url
            result_data_list.append(result_data)
        except:
            pass

# 数据写入表格
df = pd.DataFrame(result_data_list)
df.columns = ["相性","名前","読み","性別","生年","登場","没年","統率","武力","知力","政治","槍兵","騎兵","弓兵","伝授特技","重臣特性","戦法","理想威名","url"]

# 删除首行数据,重置索引
df.drop(index=0,inplace=True)
df.reset_index(drop=True,inplace=True)
df


Python 三国人物数据快速采集极简方法汇总


人物详情数据解析

根据刚抓取的人物列表数据,提取人物详情数据信息,从而构建完整的人物数据。

# 构建一个空的df数据框
df_info = pd.DataFrame()

for num in range(len(df)):
    # 获取每个人物的详情数据完整信息
    url = df["url"][num]
    html = requests.get(url,headers=headers,proxies=proxies,verify=False)
    soup = BeautifulSoup(html.text,"lxml")

    # 由于是多个表格要一个一个处理,将数据填进列表
    data_list = []
    for data in soup.find_all("table",class_="table"):
        data_list.append(data)

    # 处理第一个表格数据 基本信息补全
    title_list = []
    for i in data_list[0].find_all("tr"):
        one_data = [d.text for d in i.find_all("th")] 
        title_list.append(one_data)
    content_list = []
    for i in data_list[0].find_all("tr"):
        one_data = [d.text for d in i.find_all("td")] 
        content_list.append(one_data)

    # 补全人物基本信息
    df_temp1_col = [i for i in title_list[0] if i != ""]  # 获取字段信息
    df_temp1_content = ["-"] + content_list[1] if len(content_list[1])<11 else content_list[1] # 判断数据不足不全信息
    df_temp_1 = pd.DataFrame(df_temp1_content).T
    df_temp_1.columns = df_temp1_col

    # 补全人物列传信息
    df_temp2_col = [i for i in title_list[4] if i != ""]  # 获取字段信息
    df_temp2_content = content_list[5] # 获取列传信息
    df_temp_2 = pd.DataFrame(df_temp2_content).T
    df_temp_2.columns = df_temp2_col


    # 处理第三个表格数据 特技数据
    title_list = []
    for i in data_list[2].find_all("tr"):
        one_data = [d.text for d in i.find_all("th")] 
        title_list.append(one_data)
    content_list = []
    for i in data_list[2].find_all("tr"):
        one_data = [d.text for d in i.find_all("td")] 
        content_list.append(one_data)

    # 不抓取最后3个统计选项数据
    df_temp3_col = title_list[0][:-3]
    df_temp3_content = content_list[1][:-3]

    df_temp_3 = pd.DataFrame(df_temp3_content).T
    df_temp_3.columns = df_temp3_col


    # 处理第四个表格数据 性格・嗜好
    title_list = []
    for i in data_list[3].find_all("tr"):
        one_data = [d.text for d in i.find_all("th")] 
        title_list.append(one_data)
    content_list = []
    for i in data_list[3].find_all("tr"):
        one_data = [d.text for d in i.find_all("td")] 
        content_list.append(one_data)

    # 不抓取最后3个统计选项数据
    df_temp4_col = title_list[0]
    df_temp4_content = content_list[1]

    df_temp_4 = pd.DataFrame(df_temp4_content).T
    df_temp_4.columns = df_temp4_col


    # 横向拼接
    result_temp_1 = pd.concat([
        df_temp_1,df_temp_2,df_temp_3,df_temp_4
    ], axis=1)

    result_temp_1["名前"] = df["名前"][num]

    df_info = df_info.append(result_temp_1)

df_info 


Python 三国人物数据快速采集极简方法汇总


Xpath 应用举例

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。

四种标签的使用方法

  • // 双斜杠 定位根节点,会对全文进行扫描,在文档中选取所有符合条件的内容,以列表的形式返回。
  • / 单斜杠 寻找当前标签路径的下一层路径标签或者对当前路标签内容进行操作
  • /text() 获取当前路径下的文本内容
  • /@xxxx 提取当前路径下标签的属性值
  • | 可选符 使用|可选取若干个路径 如//p | //div 即在当前路径下选取所有符合条件的p标签和div标签。
  • . 点 用来选取当前节点
  • .. 双点 选取当前节点的父节点
from lxml import etree

html="""



    test
    



    
  • NO.1
  • NO.2
  • NO.3
  • one
  • two
crossgate pinggu """ #这里使用id属性来定位哪个div和ul被匹配 使用text()获取文本内容 selector=etree.HTML(html) content=selector.xpath('//div[@id="content"]/ul[@id="ul"]/li/text()') for i in content: print (i)


Python 三国人物数据快速采集极简方法汇总


#这里使用//从全文中定位符合条件的a标签,使用“@标签属性”获取a便签的href属性值
con=selector.xpath('//a/@href') 
for i in con:
    print (i)


Python 三国人物数据快速采集极简方法汇总


#使用绝对路径 #使用相对路径定位 两者效果是一样的
con=selector.xpath('/html/body/div/a/@title') 
print (len(con))
print (con[0],con[1])


Python 三国人物数据快速采集极简方法汇总

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章