因兴趣写了一点点爬虫,浅谈爬虫的一些简单操作吧。
1. 第一步先确定要爬取的url
无论接口还好,还是html文本也好,获取其他的数据,先通过抓包工具确定好要爬取的url地址
2. 使用 Python 构造请求,然后开始爬取数据
对于互联网上的站点,接口等,模拟人类操作构造响应的请求,设置对应的请求头,来获取想要的数据
3. 对于第二步爬取到的数据,进行清洗
- 数据爬取到了,解析接口,解析xml文本,html文本数据,找到想要的数据,清洗不相关的数据,也是为了构造结构化数据吧。
- 常用到 xpath,正则等提取文本内容。
- 也可再次深度爬取,进行第一步操作
4. 数据持久化(数据保存到本地,[文件,数据库])
第三步爬取到想要的数据,构造好结构化数据就可以进行持久化存储了。文件或者数据库都可
题外:
再就是爬虫异常、分布式爬虫和反爬
- 爬虫异常:一般来说是反爬引起的异常,对方站点更新了反爬技术。
- 分布式爬虫:多机器的同时爬取同一站点上的数据,快速爬取站点数据
- 反爬:应对站点的一些反爬技术:验证码,ip,代码混淆等。
Web crawler: 网络爬虫
- 网络爬虫模拟人类使用浏览器浏览、操作页面的行为,对互联网的站点进行操作
- 网络爬虫获取到一个页面后,会分析出页面里的所有 URI,沿着这些 URI路径递归的遍历所有页面,因此被称为爬虫(Web crawler)、蜘蛛(Spider)、网络机器人(spiderbot)
案例一:根据关键词爬取新浪新闻数据,抓取新闻【标题,来源,发布时间,内容】
第一步:确定要爬取的url: https://search.sina.com.cn/?q=%E6%98%A5%E8%8A%82&range=all&c=news&sort=time
python构造请求
def __send_page_req(self, page_num: int = 1):
"""
发起请求
:return:
"""
search_url = self.__init_search_url(page_num)
response = requests.get(search_url)
response = Selector(response=response)
return response
def __init_search_url(self, page: int = 1):
"""
构造请求数据
:param page:
:return:
"""
params = {
'q': self.search_keyword,
'range': "all",
'c': 'news',
'sort': "time",
'page': page
}
str_params = urllib.parse.urlencode(params)
return self.search_url + '?' + str_params
数据清洗
def parse_page_req(self, page_num: int = 1):
pass
完整代码:(根据关键词爬取日期在2020-12-01 后的所有新浪新闻数据)
import requests
from scrapy.selector import Selector
import urllib.parse
import datetime
import re
class SinaNewsSpider:
"""
新浪新闻搜索
"""
search_url = 'https://search.sina.com.cn/?{params}'
spider_source = 'sina'
title_compile = re.compile('<a.*?>([\s\S]*?)</a>')
article_min_date = '2020-12-01 00:00:00' # 新闻的最早时间
def __init__(self, search_keyword: str):
self.search_keyword = search_keyword
def go(self):
page_num = 1
while True:
news_data, min_date = self.parse_page_req(page_num)
[self.__save(item) for item in self.parse_data(news_data)]
if min_date > self.article_min_date:
page_num += 1
else:
break
def __save(self, data):
"""
数据存储
:param data:
:return:
"""
print(data)
pass
def parse_data(self, news_data):
"""
数据解析
:param news_data:
:return:
"""
for news in news_data:
content = self.__get_content(news['detail_url'])
if content is None:
print('error:', news)
else:
item = {}
item['content'] = content
item['source'] = 'sina'
item['keyword'] = self.search_keyword
item['news_url'] = news['detail_url']
item['insert_time'] = str(datetime.datetime.today())
item['title'] = news['title']
item['release_time'] = news['release_time']
item['author'] = news['author']
yield item
def __get_content(self, url):
response = requests.get(url)
response = Selector(text=response.content.decode('utf-8'))
content = response.xpath('//div[@id="article"]').extract_first()
content_artibody = response.xpath('//div[@id="artibody"]').extract_first()
content_section = response.xpath('//section[@class="art_pic_card art_content"]').extract_first()
return content or content_artibody or content_section
def parse_page_req(self, page_num: int = 1):
"""
解析翻页请求
:param response:
:return:
"""
response = self.__send_page_req(page_num)
news_list = response.xpath('//div[@id="result"]/div[@class="box-result clearfix"]')
news_data = []
for news in news_list:
item = {}
title = news.xpath(".//h2/a").extract_first()
item['title'] = self.title_compile.findall(title)[0]
item['detail_url'] = news.xpath(".//h2/a/@href").extract_first()
source_time_str = news.xpath(".//h2/span/text()").extract_first().strip()
item['author'], item['release_time'] = source_time_str.split(" ", maxsplit=1)
news_data.append(item)
return news_data, min(map(lambda x: item['release_time'], news_data))
def __send_page_req(self, page_num: int = 1):
"""
发起请求
:return:
"""
search_url = self.__init_search_url(page_num)
response = requests.get(search_url)
response = Selector(response=response)
return response
def __init_search_url(self, page: int = 1):
"""
构造请求数据
:param page:
:return:
"""
params = {
'q': self.search_keyword,
'range': "all",
'c': 'news',
'sort': "time",
'page': page
}
str_params = urllib.parse.urlencode(params)
return self.search_url.format(params=str_params)
sina = SinaNewsSpider("春节")
news_data = sina.go()
python 还是一个非常不错的工具。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。