第一个爬虫
目录
在Python中,一个完整的爬虫(互联网蜘蛛)的实现方式多种多样,但主要过程还是两步:
伪装HTTP Request并获取相应的HTML文件(包括且不限于CSS、JS等内容); 解析HTML(XML或DOM Tree),获取需要的数据; 在第一步中,常用的方法是使用urllib和urllib2(在Python3中这两个包已经合为一个包)来实现对网页资源的获取。当然,官方文档其实更推荐使用第三方库:requests。
- urllib(2)模块是Python标准库中用于处理URL的组件合集;
- requests是在urllib之上的HTTP客户端接口,某种意义上是一层高级的封装。
在第二步中,要解析扒下来的HTML文件(及其他),常用的是正则表达式(regex)和BeautifulSoup两种(lxml暂不做考虑,因为BS实际上可以用lxml来做解析引擎)。
- 正则表达式(regex)的学习难度视情况而定,如果之前有其他语言的正则表达式基础,对于Python中的正则表达式也能很快上手。
- BeautifulSoup上手更快,语言也更加偏自然化,但是有些编写不那么严谨的网页用BS可能很难解析出来,这时候就需要搭配正则表达式来做提取。
但这些方法某种意义上还是不那么方便,于是便有了Scrapy这种高级抽象的爬虫框架。(它不仅仅可以用来抓Web数据)
从学习难度和操作难度上,从urllib+regex、requests+BeautifulSoup到Scrapy,抽象程度依次加大,方便程度越来越好,但对底层的掌握能更好帮你理解一些实际操作时的Eoor和解析失败的原因。第一个爬虫,我们使用urllib+正则表达式的基础方法来实现。
首先我们先试着抓取百度首页的HTML内容
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import urllib.request
import urllib
url = 'http://www.baidu.com/'
response = urllib.request.urlopen(url)
content = response.read().decode('utf-8')
print(content)
抓取网易云音乐歌单
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'
}
#nn163_cloud_url = 'http://music.163.com/playlist?id=2208261223'
nn163_cloud_url = 'https://music.163.com/playlist?id=889892039'
s = requests.session()
bs = BeautifulSoup(s.get(nn163_cloud_url, headers=headers).content, "lxml")
for i in bs.ul.children:
# f = open("out.txt", "w") #只写入一条数据。
f = open('out.txt','a',encoding ='utf-8')
# print (i.string) #直接打印在屏幕上
print (i.string, file = f) #打印到文件
抓取豆瓣图书Top 250
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import requests
import mysql.connector
from idna import unicode
from bs4 import BeautifulSoup
__author__ = 'Carlos Leo'
id = 0
# 获取网页返回信息
def get_response(page):
resp = requests.get('https://book.douban.com/top250', params={'start': str(page * 10)})
if resp.status_code == 200:
return resp.text
else:
raise RecursionError('fail to request to target.')
# 使用BeautifulSoup解析
def parse_html(html):
soup = BeautifulSoup(html, 'lxml')
tables = soup.find('div', id='wrapper').find_all('table')
for table in tables:
img = table.find('img')['src']
name = table.select('.pl2')[0].a['title']
string = unicode(table.find('p').string)
lst = string.split(' / ')
author = lst[0].strip()
publisher = lst[-3].strip()
date = lst[-2].strip()
price = lst[-1].strip()
credit = unicode(table.select('.rating_nums')[0].string)
try:
desc = unicode(table.select('.inq')[0].string)
except IndexError:
desc = '无'
global id
id += 1
yield {
'id': id,
'img': img,
'name': name,
'author': author,
'publisher': publisher,
'date': date,
'price': price,
'credit': float(credit),
'desc': desc
}
# 写入文件
# def write_to_file():
# with open('books.txt', 'w') as f:
# for i in range(10):
# for book in parse_html(get_response(i)):
# json.dump(book, f, ensure_ascii=False)
# f.write('\n')
# print(book, 'was saved into book.txt')
conn = mysql.connector.connect(host='192.168.1.71', user='root', password='root', database='message')
cursor = conn.cursor()
#创建表
cursor.execute('create table book (id int(11) primary key,img varchar(100),name varchar(30),author varchar(30),publisher varchar(30),date varchar(20),price varchar(15),credit float,description varchar(30))')
# 存入数据库
def save():
for i in range(10):
for book in parse_html(get_response(i)):
save_to_db(book['id'], book['img'], book['name'], book['author'], book['publisher'], book['date'],
book['price'], book['credit'], book['desc'])
print('save book' + str(book) + 'to db')
# 存入一本书到数据库
def save_to_db(*args):
conn = mysql.connector.connect(host='192.168.1.71',user='root', password='root', database='message')
cursor = conn.cursor()
cursor.execute('insert into book(id, img, name, author, publisher, date, price, credit, description) '
'values(%s, %s, %s, %s, %s, %s, %s, %s, %s)', args)
conn.commit()
cursor.close()
conn.close()
if __name__ == '__main__':
save()