20170428:
由于moozik.cn更换了程序,文中代码某些可能已失效
pip
pip是python的包管理工具,他的路径一般是在C:\Python35\Scripts,这也就是为什么要把他加入环境变量,pip是安装python包非常简单方便的工具。
pip3 install requests
pip3 install lxml
pip3 install pymysql
这里引用一篇详细介绍了与python爬虫相关工具的文章。
requests
requests库是抓取网站数据最常用工具,不应该说是最常用的,应该说是必用的。requests把复杂的http请求的细节统统封装在库程序中,只需要很简单的代码就可以进行非常简洁高效的抓取。下面是基本语法。
import requests
#发送请求
r = requests.get('https://github.com/timeline.json')
r = requests.post("http://httpbin.org/post")
r = requests.put("http://httpbin.org/put")
r = requests.delete("http://httpbin.org/delete")
r = requests.head("http://httpbin.org/get")
r = requests.options("http://httpbin.org/get")
#为URL传递参数
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
#这时r.url='http://httpbin.org/get?key2=value2&key1=value1'
#传递表单内容
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=payload)
#响应内容
import requests
r = requests.get('https://github.com/timeline.json')
print(r.text)
#注:每次访问text属性,requests都会尝试解码,修改默认解码的方法是使用encoding参数
#内置json解码
import requests
r = requests.get('https://github.com/timeline.json')
print(r.json())
lxml与bs4
lxml是常用与解析网页结构,获取目标文本的常用工具。这里有必要说一下beautifulsoup4,他们的区别还是挺大的。
lxml是c写的,beautifulsoup4(简称bs4)是python写的,从这里就可以看出效率的差别。另外lxml匹配html的数据是使用xpath匹配的,并且每次搜索均为独立查找。bs4读取一个页面,会把html中的每个节点和标签都转换成对象以供调用,读取整个文件的代价就是效率低下。
另外lxml也可以被bs4作为解析器调用,所以直接使用lxml是最好的选择,而且xpath并不难学。下面是一个获取页面所有a链接的例子。
import requests
from lxml import etree
html_str = requests.get('http://moozik.cn').text
html = etree.HTML(html_str)
alink = html.xpath('//a')
print('所有a链接名称和地址')
for item in alink:
print(item.text,item.attrib['href'])
#输出横线
print(60 * '-')
print('近期文章名称,近期文章链接')
print(html.xpath('//aside[@id="recent-posts-2"]/ul/li/a/text()'))
print(html.xpath('//aside[@id="recent-posts-2"]/ul/li/a/@href'))
print(60 * '-')
print('从a遍历名称和链接')
alink = html.xpath('//aside[@id="recent-posts-2"]/ul/li/a')
for item in alink:
print(item.text,item.attrib['href'])
print(60 * '-')
print('从li遍历名称和链接')
alink = html.xpath('//aside[@id="recent-posts-2"]/ul/li')
for item in alink:
#print(dir(item)) #查看item中可用的方法和属性
#这里打印出的是空字典,这里只是说明,遍历li的侧重点是li的属性中或者li下面其他标签有我们需要的数据
print(item.attrib)
item2 = item.xpath('a')
print(item2[0].text,item2[0].attrib['href'])
print(60 * '-')
print('遍历http://moozik.cn/archives/date/2017/01 中所有文章的信息')
html_str = requests.get('http://moozik.cn/archives/date/2017/01').text
html = etree.HTML(html_str)
article = html.xpath('//article')
#使用字典存储
article_dict = {}
#遍历文章
for art_item in article:
#article标签的id
art_id = art_item.attrib['id']
article_dict[art_id] = {}
#标题
article_dict[art_id]['title'] = art_item.xpath('header/h1/a/text()')[0]
#地址
article_dict[art_id]['link'] = art_item.xpath('header/h1/a/@href')[0]
#分类
article_dict[art_id]['category'] = art_item.xpath('header/div[1]/span/a/text()')[0]
#文章时间
article_dict[art_id]['datetime'] = art_item.xpath('header/div[2]/span[1]/a/time/@datetime')[0]
#文章内容,这里使用//用于无限深度得查找所有文本内容,并使用join将返回的列表合并
article_dict[art_id]['content'] = ''.join(art_item.xpath("div[@class='entry-content']//text()"))
#打印所有数据
print(article_dict)
我初学xpath的时候,具体方法就是照葫芦画瓢,结合chrome右键中的“Copy XPath”不断尝试,不断用print()查看返回结果,最后理解了xpath的表达方式之后,就可以熟练的提取想要的数据了。
如果你的浏览器是chrome,或者支持chrome插件的浏览器,那么你可以安装一个xpath的辅助插件来定位你想要查找的数据,非常好用。如果下面的链接你打不开,那么你大概是被墙了。
XPath Helper
这里是一篇介绍xpath语法的文章XPath详解,总结