最近由于工作需要爬取一些数据,分享几篇文章爬虫实战的文章。
网址:http://www.hdb.com/hangzhou/
对于爬虫首先你要了解一些基础知识,Http 请求等。使用chrome浏览器,安装一个插件,可以使用浏览器的抓包工具,我这里使用的是Safari浏览器,大致一样。在浏览器右击有一个检查元素,我的是Inspect Element。
我是用的是python,使用的requests库做请求,页面解析用lxml库,页面信息提取用xpath(这里浏览器我安装了一个xpath插件,作为一个xpath取值的验证工具)
提示:接下来几篇文章是用不同的页面解析工具和取值方法,包括Beautifulsoup、常用的正则取值等,希望可以继续看。
我需要爬取的是我在搜索框内输入关键词,然后返回的页面中活动商家的名称和手机号(注意只匹配手机号)
然后到二级页面取所需要的值,一个活动的店名,一个是手机号
首先你要从一级页面获取到每一个二级页面的对应链接,才可以进入二级页面取到对应的值
可以找到每个活动的信息都在ul这个标签下,一个li标签下面包含一个活动,点开后发现<a>标签里包着二级页面的链接,在href属性。所以你的目标是取到每一个<li>下的<a>标签的href属性的文本。
代码:
# 发送请求的库
import requests
# 将中文改成网址的url的库
from urllib.parse import quote
# 取随机数的库
import random
# 正则匹配的库
import re
# 解析页面的库
from lxml import etree
# 请求头中的User_agent,模仿浏览器发送请求必备
user_agent = [
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
]
# 请求头,这里我只用了一个User_Agent,你可以添加其他
headers = {'User-Agent': random.choice(user_agent)}
# 用循环去搜索多个关键词
dict_objs = ['绘画','主持人','跆拳道']
for dict_obj in dict_objs:
# 将汉字转化成url路径
encode_after = quote(dict_obj)
# 用循环爬取多页
for i in range(1, 80):
# 请求所传的参数,查看页面使用的get请求,这些参数都会拼接在基础url后
data = {
'word':encode_after,
'area_code': 'quanguo',
'page_num': str(i),
}
# 基础url
url = "http://www.hdb.com/info_search?"
# 发送get请求
response = requests.get(url=url, headers=headers, params=data)
# 打印请求的实际url
print(response.url)
# 将返回的请求对象转化成content流文本
response = response.content
# 用lxml库下的etree将流文本转化成HTML文档树
html_tree = etree.HTML(response)
# 用xpath取到所有li的链接
ret = html_tree.xpath('/html/body/div[2]/div/ul/li/div/h3/a/@href')
for i in ret:
# 向二级页面发送请求
response1 = requests.get(url=i, headers=headers)
上述代码每一段都注释的很清楚了。下面分析二级页面,我们要用xpath拿到商家名称很容易,重要的是拿取详情页面的手机号。分析到手机号都是在详情页面的div里,所以先用xpath取到详情页面的所有内容,再用re正则匹配手机号。如下图:
<div id="dt_content" >这个标签下是详情页面的div,然后用正则匹配手机号。
代码如下:
try:
# 用re匹配到<div id="dt_content">标签里所有的内容
tel_page = re.findall(r'<div id="dt_content" class="dt_content" ms-skip >(.*?)</div>',response1.text, re.S)
tel_str = tel_page[0]
# 在用re匹配到详情页面的手机号
tel = re.findall(r'13[0-9]\d{8}|14[5,7]\d{8}|^:15[0-3,5-9]\d{8}|17[0,3,5-8]\d{8}|18[0-9]\d{8}|166\d{8}|198\d{8}|199\d{8}|147\d{8}',tel_str)
html_tree1 = etree.HTML(response1.content)
# 用xpath拿到商家名称
biaoti = html_tree1.xpath('//*[@id="dt_title"]/text()')
# 用xpath拿到发布者所在的链接,这是新加的上面没讲
fabuzhe=html_tree1.xpath('//*[@id="subinfo_name"]/@href')
# print(fabuzhe)
print(tel)
print(biaoti[1].strip())
pub=re.search(r'/timeline/(.*?).html', fabuzhe[0])
publishUserId36=pub.group(1)
print(publishUserId36)
# 将发布者链接发送post请求,拿到json数据
url1 = 'http://api.hdb.com/ajax/api:4009?'
data = {
'queryType': 2,
'publishUserId36': publishUserId36,
}
response2=requests.post(url=url1,data=data,headers=headers)
fabuzhe_xiangxi = response2.json()
# 解析json数据,拿到发布者信息
fabuzhe_xiangxi1 = fabuzhe_xiangxi['result']['shopName']
最后来一个整体代码:
import requests
from urllib.parse import quote
import random
import re
from lxml import etree
user_agent = [
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
]
headers = {'User-Agent': random.choice(user_agent)}
dict_objs = ['绘画','主持人']
for dict_obj in dict_objs:
encode_after = quote(dict_obj)
for i in range(1, 80):
data={
'word':encode_after,
'area_code': 'quanguo',
'page_num': str(i),
}
url = "http://www.hdb.com/info_search?"
response = requests.get(url=url, headers=headers, params=data)
print(response.url)
response = response.content
html_tree = etree.HTML(response)
ret = html_tree.xpath('/html/body/div[2]/div/ul/li/div/h3/a/@href')
for i in ret:
response1 = requests.get(url=i, headers=headers)
try:
tel_page = re.findall(r'<div id="dt_content" class="dt_content" ms-skip >(.*?)</div>',response1.text, re.S)
tel_str = tel_page[0]
tel = re.findall(r'13[0-9]\d{8}|14[5,7]\d{8}|^:15[0-3,5-9]\d{8}|17[0,3,5-8]\d{8}|18[0-9]\d{8}|166\d{8}|198\d{8}|199\d{8}|147\d{8}',tel_str)
html_tree1 = etree.HTML(response1.content)
biaoti = html_tree1.xpath('//*[@id="dt_title"]/text()')
fabuzhe=html_tree1.xpath('//*[@id="subinfo_name"]/@href')
# print(fabuzhe)
print(tel)
print(biaoti[1].strip())
pub=re.search(r'/timeline/(.*?).html', fabuzhe[0])
publishUserId36=pub.group(1)
print(publishUserId36)
url1 = 'http://api.hdb.com/ajax/api:4009?'
data = {
'queryType': 2,
'publishUserId36': publishUserId36,
}
response2=requests.post(url=url1,data=data,headers=headers)
fabuzhe_xiangxi = response2.json()
fabuzhe_xiangxi1 = fabuzhe_xiangxi['result']['shopName']
喜欢就点个赞吧?